import { useState, useMemo, useEffect, useCallback, CSSProperties } from 'react';
import { Card, Button, Input, Select, DatePicker, Table, Typography, message } from 'antd';
import { ArrowLeftOutlined, DownloadOutlined, SearchOutlined } from '@ant-design/icons';
import { request } from '../api/client';
import { useNavigate } from 'react-router-dom';
import { ROUTES } from '../router/routes.constant';

interface AuditLog {
  id: string;
  user_id: string | null;
  action: string;
  entity_type: string;
  entity_id: string | null;
  old_values: Record<string, unknown> | null;
  new_values: Record<string, unknown> | null;
  ip_address: string | null;
  user_agent: string | null;
  timestamp: string;
  created_at: string;
  updated_at: string;
}

interface PaginationState {
  current: number;
  pageSize: number;
  total: number;
}

export default function AuditLogsPage() {
  const [messageApi, contextHolder] = message.useMessage();
  const navigate = useNavigate();

  const [auditLogs, setAuditLogs] = useState<AuditLog[]>([]);
  const [loading, setLoading] = useState<boolean>(false);
  const [searchText, setSearchText] = useState<string>('');
  const [filterActionType, setFilterActionType] = useState<string>('');
  const [filterEntityType, setFilterEntityType] = useState<string>('');
  const [filterUserId, setFilterUserId] = useState<string>('');
  const [dateRange, setDateRange] = useState<[unknown, unknown] | []>([]);
  const [pagination, setPagination] = useState<PaginationState>({
    current: 1,
    pageSize: 50,
    total: 0,
  });
  const [expandedRowKeys, setExpandedRowKeys] = useState<string[]>([]);

  const hasFiltersApplied = useMemo(() => {
    return searchText !== '' || filterActionType !== '' || filterEntityType !== '' || filterUserId !== '' || dateRange.length > 0;
  }, [searchText, filterActionType, filterEntityType, filterUserId, dateRange]);

  const loadAuditLogs = useCallback(async () => {
    setLoading(true);
    try {
      const queryParams: Record<string, string | number> = {
        limit: pagination.pageSize,
        offset: (pagination.current - 1) * pagination.pageSize,
      };

      if (filterUserId) {
        queryParams.user_id = filterUserId;
      }
      if (filterActionType) {
        queryParams.action = filterActionType;
      }
      if (filterEntityType) {
        queryParams.entity_type = filterEntityType;
      }

      const result = await request<AuditLog[]>({
        method: 'GET',
        path: '/audit-logs/',
        query: queryParams,
      });

      setAuditLogs(result.data);
      setPagination(prev => ({ ...prev, total: result.data.length }));
    } catch (error) {
      messageApi.error('Failed to load audit logs');
    } finally {
      setLoading(false);
    }
  }, [pagination.pageSize, pagination.current, filterUserId, filterActionType, filterEntityType, messageApi]);

  useEffect(() => {
    loadAuditLogs();
  }, []);

  const clearFilters = useCallback(() => {
    setSearchText('');
    setFilterActionType('');
    setFilterEntityType('');
    setFilterUserId('');
    setDateRange([]);
    setPagination(prev => ({ ...prev, current: 1 }));
    messageApi.success('Filters cleared');
    loadAuditLogs();
  }, [messageApi, loadAuditLogs]);

  const exportCsv = useCallback(() => {
    try {
      const headers = ['Timestamp', 'User ID', 'Action', 'Entity Type', 'Entity ID', 'IP Address'];
      const csvContent = [
        headers.join(','),
        ...auditLogs.map(log =>
          [
            log.timestamp,
            log.user_id || '',
            log.action,
            log.entity_type,
            log.entity_id || '',
            log.ip_address || '',
          ].join(',')
        ),
      ].join('\n');

      const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
      const link = document.createElement('a');
      const url = URL.createObjectURL(blob);
      link.setAttribute('href', url);
      link.setAttribute('download', 'audit_logs_export.csv');
      link.style.visibility = 'hidden';
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);

      messageApi.success('Export started');
    } catch (error) {
      messageApi.error('Failed to export audit logs');
    }
  }, [auditLogs, messageApi]);

  const navigateToDashboard = useCallback(() => {
    navigate(ROUTES.ADMIN_DASHBOARD || '/admin/dashboard');
  }, [navigate]);

  const handlePaginationChange = useCallback((page: number, pageSize: number) => {
    setPagination(prev => ({ ...prev, current: page, pageSize }));
  }, []);

  const handleExpandRow = useCallback((expanded: boolean, record: AuditLog) => {
    setExpandedRowKeys(prev =>
      expanded ? [...prev, record.id] : prev.filter(key => key !== record.id)
    );
  }, []);

  const columns = useMemo(() => [
    {
      title: 'Timestamp',
      dataIndex: 'timestamp',
      key: 'timestamp',
      sorter: true,
      width: 180,
      render: (text: string) => new Date(text).toLocaleString(),
    },
    {
      title: 'User',
      dataIndex: 'user_id',
      key: 'user_id',
      width: 160,
      render: (text: string | null) => text || 'N/A',
    },
    {
      title: 'Action Type',
      dataIndex: 'action',
      key: 'action',
      width: 160,
    },
    {
      title: 'Entity Type',
      dataIndex: 'entity_type',
      key: 'entity_type',
      width: 130,
    },
    {
      title: 'Entity ID',
      dataIndex: 'entity_id',
      key: 'entity_id',
      width: 140,
      render: (text: string | null) => text || 'N/A',
    },
    {
      title: 'IP Address',
      dataIndex: 'ip_address',
      key: 'ip_address',
      width: 140,
      render: (text: string | null) => text || 'N/A',
    },
  ], []);

  const expandedRowRender = useCallback((record: AuditLog) => {
    return (
      <div style={{ padding: '16px', backgroundColor: '#fafafa' }}>
        <Typography.Text strong style={{ display: 'block', marginBottom: '8px' }}>
          Before (Old Values)
        </Typography.Text>
        <Typography.Text
          code
          style={{ display: 'block', marginBottom: '16px', whiteSpace: 'pre-wrap' }}
        >
          {record.old_values ? JSON.stringify(record.old_values, null, 2) : 'N/A'}
        </Typography.Text>

        <Typography.Text strong style={{ display: 'block', marginBottom: '8px' }}>
          After (New Values)
        </Typography.Text>
        <Typography.Text code style={{ display: 'block', whiteSpace: 'pre-wrap' }}>
          {record.new_values ? JSON.stringify(record.new_values, null, 2) : 'N/A'}
        </Typography.Text>

        <Typography.Text
          type="secondary"
          style={{ display: 'block', marginTop: '12px', fontSize: '12px' }}
        >
          User Agent: {record.user_agent || 'N/A'}
        </Typography.Text>
      </div>
    );
  }, []);

  const mainContainerStyle: CSSProperties = {
    minHeight: '100vh',
    width: '100%',
    padding: '24px',
    backgroundColor: '#f5f5f5',
  };

  const pageHeaderStyle: CSSProperties = {
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: '24px',
  };

  const headerLeftStyle: CSSProperties = {
    display: 'flex',
    alignItems: 'center',
    gap: '12px',
  };

  const headerRightStyle: CSSProperties = {
    display: 'flex',
    gap: '8px',
  };

  const filtersRowStyle: CSSProperties = {
    display: 'flex',
    flexWrap: 'wrap',
    gap: '12px',
    alignItems: 'center',
  };

  const filtersActionsStyle: CSSProperties = {
    display: 'flex',
    gap: '8px',
    marginLeft: 'auto',
  };

  return (
    <div style={mainContainerStyle}>
      {contextHolder}

      <div style={pageHeaderStyle}>
        <div style={headerLeftStyle}>
          <Button type="text" icon={<ArrowLeftOutlined />} onClick={navigateToDashboard}>
            Back
          </Button>
          <Typography.Title level={2} style={{ margin: 0 }}>
            Audit Logs
          </Typography.Title>
        </div>
        <div style={headerRightStyle}>
          <Button type="primary" icon={<DownloadOutlined />} onClick={exportCsv}>
            Export CSV
          </Button>
        </div>
      </div>

      <Card size="small" style={{ marginBottom: '16px' }}>
        <div style={filtersRowStyle}>
          <DatePicker.RangePicker
            value={dateRange.length > 0 ? dateRange as [unknown, unknown] : undefined}
            onChange={(dates) => {
              setDateRange(dates || []);
              setPagination(prev => ({ ...prev, current: 1 }));
            }}
            placeholder={['Start Date', 'End Date']}
            allowClear
            aria-label="date_range_picker"
            style={{ minWidth: '240px' }}
          />

          <Input
            value={filterUserId}
            onChange={(e) => {
              setFilterUserId(e.target.value);
              setPagination(prev => ({ ...prev, current: 1 }));
            }}
            placeholder="Search by User ID"
            allowClear
            aria-label="user_search_filter"
            style={{ minWidth: '180px' }}
          />

          <Select
            value={filterActionType || undefined}
            onChange={(value) => {
              setFilterActionType(value || '');
              setPagination(prev => ({ ...prev, current: 1 }));
            }}
            placeholder="Action Type"
            allowClear
            aria-label="action_type_filter"
            style={{ minWidth: '180px' }}
            options={[
              { label: 'Login', value: 'Login' },
              { label: 'Logout', value: 'Logout' },
              { label: 'Checkout', value: 'Checkout' },
              { label: 'Return', value: 'Return' },
              { label: 'Payment', value: 'Payment' },
              { label: 'Create', value: 'Create' },
              { label: 'Update', value: 'Update' },
              { label: 'Delete', value: 'Delete' },
              { label: 'Configuration Change', value: 'Configuration Change' },
              { label: 'Renewal', value: 'Renewal' },
              { label: 'Reservation', value: 'Reservation' },
              { label: 'Fine Waived', value: 'Fine Waived' },
            ]}
          />

          <Select
            value={filterEntityType || undefined}
            onChange={(value) => {
              setFilterEntityType(value || '');
              setPagination(prev => ({ ...prev, current: 1 }));
            }}
            placeholder="Entity Type"
            allowClear
            aria-label="entity_type_filter"
            style={{ minWidth: '180px' }}
            options={[
              { label: 'Book', value: 'Book' },
              { label: 'Member', value: 'Member' },
              { label: 'Loan', value: 'Loan' },
              { label: 'Fine', value: 'Fine' },
              { label: 'Reservation', value: 'Reservation' },
              { label: 'User', value: 'User' },
              { label: 'Category', value: 'Category' },
              { label: 'Author', value: 'Author' },
              { label: 'Publisher', value: 'Publisher' },
              { label: 'Notification', value: 'Notification' },
              { label: 'Settings', value: 'Settings' },
            ]}
          />

          <Input.Search
            value={searchText}
            onChange={(e) => setSearchText(e.target.value)}
            placeholder="Search descriptions..."
            allowClear
            aria-label="search_input"
            style={{ minWidth: '220px' }}
          />

          <div style={filtersActionsStyle}>
            <Button type="primary" icon={<SearchOutlined />} onClick={loadAuditLogs}>
              Search
            </Button>
            <Button type="default" onClick={clearFilters}>
              Clear Filters
            </Button>
          </div>
        </div>
      </Card>

      <Card bodyStyle={{ padding: 0 }}>
        <Table
          rowKey="id"
          dataSource={auditLogs}
          columns={columns}
          loading={loading}
          expandable={{
            expandedRowRender,
            expandedRowKeys,
            onExpand: handleExpandRow,
          }}
          pagination={{
            current: pagination.current,
            pageSize: pagination.pageSize,
            total: pagination.total,
            showSizeChanger: true,
            pageSizeOptions: ['50', '100', '200', '500'],
            showTotal: (total) => `Total ${total} items`,
            onChange: handlePaginationChange,
          }}
          scroll={{ x: 1000 }}
          aria-label="audit_logs_table"
        />
      </Card>
    </div>
  );
}