import { useState, useMemo, useEffect, useCallback, CSSProperties } from 'react';
import { Table, Card, Button, Space, Input, Select, DatePicker, Alert, Breadcrumb, Typography, Modal, Descriptions, message, Tag } from 'antd';
import { DownloadOutlined, SearchOutlined } from '@ant-design/icons';
import { useNavigate } from 'react-router-dom';
import { useApi } from '@/hooks/useApi';
import { AuditLogService } from '@/services/auditLog';
import { parseError } from '@/utils/errorHandler';
import { ROUTES } from '@/constants/routes';
import type { ColumnsType, TablePaginationConfig } from 'antd/es/table';
import type { SorterResult } from 'antd/es/table/interface';
import type { Dayjs } from 'dayjs';

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

interface AuditLogDetail extends AuditLog {
  user_first_name: string | null;
  user_last_name: string | null;
}

const AdminAuditLogsPage = () => {
  const [messageApi, contextHolder] = message.useMessage();
  const navigate = useNavigate();

  const [auditLogs, setAuditLogs] = useState<AuditLog[]>([]);
  const [loading, setLoading] = useState<boolean>(false);
  const [totalCount, setTotalCount] = useState<number>(0);
  const [currentPage, setCurrentPage] = useState<number>(1);
  const [pageSize, setPageSize] = useState<number>(20);
  const [filterUserSearch, setFilterUserSearch] = useState<string>('');
  const [filterAction, setFilterAction] = useState<string>('');
  const [filterEntityType, setFilterEntityType] = useState<string>('');
  const [filterDateRange, setFilterDateRange] = useState<[Dayjs, Dayjs] | null>(null);
  const [sortOrder, setSortOrder] = useState<string>('descend');
  const [expandedRowKeys, setExpandedRowKeys] = useState<string[]>([]);
  const [exportLoading, setExportLoading] = useState<boolean>(false);
  const [detailModalVisible, setDetailModalVisible] = useState<boolean>(false);
  const [selectedLog, setSelectedLog] = useState<AuditLogDetail | null>(null);

  const offset = useMemo(() => (currentPage - 1) * pageSize, [currentPage, pageSize]);
  const hasFilters = useMemo(
    () => filterUserSearch !== '' || filterAction !== '' || filterEntityType !== '' || filterDateRange !== null,
    [filterUserSearch, filterAction, filterEntityType, filterDateRange]
  );

  const { execute: fetchAuditLogs } = useApi(AuditLogService.list);
  const { execute: fetchAuditLogDetails } = useApi(AuditLogService.getDetails);

  const loadAuditLogs = useCallback(async () => {
    setLoading(true);
    try {
      const params: Record<string, unknown> = {
        limit: pageSize,
        offset,
      };
      if (filterUserSearch) params.user_id = filterUserSearch;
      if (filterAction) params.action = filterAction;
      if (filterEntityType) params.entity_type = filterEntityType;

      const response = await fetchAuditLogs(params);
      if (response?.data) {
        setAuditLogs(Array.isArray(response.data) ? response.data : []);
        setTotalCount(Array.isArray(response.data) ? response.data.length : 0);
      }
    } catch (e) {
      const { message: errorMessage } = parseError(e);
      messageApi.error(errorMessage || 'Failed to load audit logs. Please try again.');
    } finally {
      setLoading(false);
    }
  }, [pageSize, offset, filterUserSearch, filterAction, filterEntityType, fetchAuditLogs, messageApi]);

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

  const onPageChange = useCallback((page: number, newPageSize: number) => {
    setCurrentPage(page);
    setPageSize(newPageSize);
  }, []);

  const onUserSearchChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    setFilterUserSearch(e.target.value);
    setCurrentPage(1);
  }, []);

  const onActionFilterChange = useCallback((value: string) => {
    setFilterAction(value || '');
    setCurrentPage(1);
  }, []);

  const onEntityTypeFilterChange = useCallback((value: string) => {
    setFilterEntityType(value || '');
    setCurrentPage(1);
  }, []);

  const onDateRangeChange = useCallback((dates: [Dayjs, Dayjs] | null) => {
    setFilterDateRange(dates);
    setCurrentPage(1);
  }, []);

  const onSortChange = useCallback(
    (_pagination: TablePaginationConfig, _filters: Record<string, unknown>, sorter: SorterResult<AuditLog> | SorterResult<AuditLog>[]) => {
      if (!Array.isArray(sorter)) {
        setSortOrder((sorter.order as string) || 'descend');
      }
    },
    []
  );

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

  const onCloseDetailModal = useCallback(() => {
    setDetailModalVisible(false);
    setSelectedLog(null);
  }, []);

  const handleRowClick = useCallback(
    async (record: AuditLog) => {
      setSelectedLog(record as AuditLogDetail);
      setDetailModalVisible(true);
      try {
        const response = await fetchAuditLogDetails({ auditlog_id: record.id });
        if (response?.data) {
          setSelectedLog(response.data as AuditLogDetail);
        }
      } catch (e) {
        const { message: errorMessage } = parseError(e);
        messageApi.error(errorMessage || 'Failed to load log details.');
      }
    },
    [fetchAuditLogDetails, messageApi]
  );

  const exportCsv = useCallback(async () => {
    setExportLoading(true);
    try {
      const csvContent = [
        ['Timestamp', 'User ID', 'Action', 'Entity Type', 'Entity ID', 'IP Address', 'Details'].join(','),
        ...auditLogs.map((log) =>
          [
            log.timestamp,
            log.user_id || 'System',
            log.action,
            log.entity_type || '',
            log.entity_id || '',
            log.ip_address || '',
            JSON.stringify(log.details || {}),
          ].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('Audit logs exported successfully');
    } catch (e) {
      const { message: errorMessage } = parseError(e);
      messageApi.error(errorMessage || 'Failed to export audit logs');
    } finally {
      setExportLoading(false);
    }
  }, [auditLogs, messageApi]);

  const clearFilters = useCallback(() => {
    setFilterUserSearch('');
    setFilterAction('');
    setFilterEntityType('');
    setFilterDateRange(null);
    setCurrentPage(1);
    messageApi.info('Filters cleared');
  }, [messageApi]);

  const navigateToDashboard = useCallback(() => {
    navigate(ROUTES.ADMIN);
  }, [navigate]);

  const navigateToUsers = useCallback(() => {
    navigate(ROUTES.ADMIN_USERS);
  }, [navigate]);

  const navigateToCategories = useCallback(() => {
    navigate(ROUTES.ADMIN_CATEGORIES);
  }, [navigate]);

  const columns: ColumnsType<AuditLog> = useMemo(
    () => [
      {
        title: 'Timestamp',
        dataIndex: 'timestamp',
        key: 'timestamp',
        sorter: true,
        defaultSortOrder: 'descend',
        width: 180,
        render: (text: string) => new Date(text).toLocaleString(),
      },
      {
        title: 'User',
        dataIndex: 'user_id',
        key: 'user_id',
        width: 160,
        render: (text: string | null) => text || 'System',
      },
      {
        title: 'Action',
        dataIndex: 'action',
        key: 'action',
        width: 120,
        render: (text: string) => <Tag color="blue">{text}</Tag>,
      },
      {
        title: 'Entity Type',
        dataIndex: 'entity_type',
        key: 'entity_type',
        width: 140,
      },
      {
        title: 'Entity ID',
        dataIndex: 'entity_id',
        key: 'entity_id',
        width: 160,
        ellipsis: true,
      },
      {
        title: 'IP Address',
        dataIndex: 'ip_address',
        key: 'ip_address',
        width: 130,
      },
      {
        title: 'Details',
        dataIndex: 'details',
        key: 'details',
        width: 200,
        ellipsis: true,
        render: (details: Record<string, unknown> | null) => (details ? JSON.stringify(details).substring(0, 50) + '...' : '-'),
      },
      {
        title: 'Actions',
        key: 'row_actions',
        width: 80,
        fixed: 'right',
        render: (_: unknown, record: AuditLog) => (
          <Button type="link" size="small" onClick={() => handleRowClick(record)}>
            View
          </Button>
        ),
      },
    ],
    [handleRowClick]
  );

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

  const pageHeaderSectionStyle: CSSProperties = {
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: '16px',
    flexWrap: 'wrap',
    gap: '12px',
  };

  const headerLeftStyle: CSSProperties = {
    display: 'flex',
    flexDirection: 'column',
    gap: '4px',
  };

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

  const descriptionsItems = useMemo(() => {
    if (!selectedLog) return [];
    return [
      { label: 'Log ID', children: selectedLog.log_id },
      { label: 'Timestamp', children: new Date(selectedLog.timestamp).toLocaleString() },
      {
        label: 'User',
        children:
          selectedLog.user_first_name && selectedLog.user_last_name
            ? `${selectedLog.user_first_name} ${selectedLog.user_last_name}`
            : '-',
      },
      { label: 'User ID', children: selectedLog.user_id || '-' },
      { label: 'Action', children: selectedLog.action },
      { label: 'Entity Type', children: selectedLog.entity_type || '-' },
      { label: 'Entity ID', children: selectedLog.entity_id || '-' },
      { label: 'IP Address', children: selectedLog.ip_address || '-' },
      { label: 'User Agent', children: selectedLog.user_agent || '-' },
      {
        label: 'Details',
        children: selectedLog.details ? <pre>{JSON.stringify(selectedLog.details, null, 2)}</pre> : '-',
      },
    ];
  }, [selectedLog]);

  return (
    <div style={mainContainerStyle}>
      {contextHolder}
      <Space size="small" style={{ marginBottom: '16px' }}>
        <Button type="link" onClick={navigateToDashboard}>
          Dashboard
        </Button>
        <Button type="link" onClick={navigateToUsers}>
          Users
        </Button>
        <Button type="link" onClick={navigateToCategories}>
          Categories
        </Button>
        <Button type="link" disabled style={{ fontWeight: 'bold' }}>
          Audit Logs
        </Button>
      </Space>

      <div style={pageHeaderSectionStyle}>
        <div style={headerLeftStyle}>
          <Breadcrumb
            items={[
              { title: 'Admin', href: ROUTES.ADMIN },
              { title: 'Audit Logs' },
            ]}
          />
          <Typography.Title level={2} style={{ margin: 0 }}>
            Audit Logs
          </Typography.Title>
        </div>
        <Space size="middle">
          <Button type="primary" icon={<DownloadOutlined />} loading={exportLoading} onClick={exportCsv}>
            Export CSV
          </Button>
        </Space>
      </div>

      <Alert
        type="info"
        showIcon
        message="Data Retention Policy"
        description="Audit logs are retained for a minimum of 90 days in compliance with system data retention policies. Logs older than the retention period may be automatically archived."
        closable={false}
        style={{ marginBottom: '16px' }}
      />

      <Card title="Filters" size="small" style={{ marginBottom: '16px' }}>
        <div style={filtersRowStyle}>
          <DatePicker.RangePicker
            placeholder={['Start Date', 'End Date']}
            allowClear
            format="YYYY-MM-DD"
            value={filterDateRange}
            onChange={onDateRangeChange}
            style={{ minWidth: '240px' }}
          />
          <Input.Search
            placeholder="Search by user ID..."
            allowClear
            value={filterUserSearch}
            onChange={onUserSearchChange}
            style={{ minWidth: '200px', maxWidth: '280px' }}
          />
          <Select
            placeholder="Filter by action"
            allowClear
            value={filterAction || undefined}
            onChange={onActionFilterChange}
            style={{ minWidth: '180px' }}
            options={[
              { label: 'Create', value: 'CREATE' },
              { label: 'Update', value: 'UPDATE' },
              { label: 'Delete', value: 'DELETE' },
              { label: 'Login', value: 'LOGIN' },
              { label: 'Logout', value: 'LOGOUT' },
              { label: 'Calculate', value: 'CALCULATE' },
              { label: 'Export', value: 'EXPORT' },
              { label: 'Disable', value: 'DISABLE' },
              { label: 'Enable', value: 'ENABLE' },
            ]}
          />
          <Select
            placeholder="Filter by entity type"
            allowClear
            value={filterEntityType || undefined}
            onChange={onEntityTypeFilterChange}
            style={{ minWidth: '180px' }}
            options={[
              { label: 'User', value: 'User' },
              { label: 'BMI Calculation', value: 'BmiCalculation' },
              { label: 'BMI Category', value: 'BmiCategory' },
              { label: 'Goal', value: 'Goal' },
              { label: 'Profile', value: 'Profile' },
            ]}
          />
          <Space size="small">
            <Button type="primary" icon={<SearchOutlined />} onClick={loadAuditLogs}>
              Apply
            </Button>
            <Button type="default" onClick={clearFilters}>
              Clear
            </Button>
          </Space>
        </div>
      </Card>

      <Card bodyStyle={{ padding: 0 }} style={{ flex: 1 }}>
        <Table<AuditLog>
          rowKey="id"
          dataSource={auditLogs}
          columns={columns}
          loading={loading}
          scroll={{ x: 1200 }}
          size="middle"
          pagination={{
            current: currentPage,
            pageSize,
            total: totalCount,
            showSizeChanger: true,
            showQuickJumper: true,
            showTotal: (total) => `Total ${total} log entries`,
            pageSizeOptions: ['10', '20', '50', '100'],
            onChange: onPageChange,
          }}
          onChange={onSortChange}
          expandable={{
            expandedRowKeys,
            onExpand: onExpandRow,
            expandedRowRender: (record) => <pre>{JSON.stringify(record.details, null, 2)}</pre>,
          }}
        />
      </Card>

      <Modal
        title="Audit Log Details"
        open={detailModalVisible}
        onCancel={onCloseDetailModal}
        footer={null}
        width={640}
      >
        <Descriptions bordered column={1} size="small" items={descriptionsItems} />
      </Modal>
    </div>
  );
};

export default AdminAuditLogsPage;