import { useState, useEffect, useCallback, useRef } from 'react';
import {
  Table,
  Button,
  Input,
  Tag,
  Space,
  Drawer,
  Popconfirm,
  message,
  Row,
  Col,
  Card,
  Statistic,
  Descriptions,
  Grid,
} from 'antd';
import {
  SearchOutlined,
  DeleteOutlined,
  EyeOutlined,
  ReloadOutlined,
  SendOutlined,
} from '@ant-design/icons';
import type { ColumnsType, TablePaginationConfig } from 'antd/es/table';
import dayjs from 'dayjs';
import { useOutletContext, useNavigate } from 'react-router-dom';
import { api } from '@/lib/api';
import type { AppOutletContext } from '@/components/AppLayout';
import type {
  Representative,
  RepresentativesListResponse,
  RepresentativesListParams,
  RepresentativeLookupResponse,
  CacheStats,
} from '@/types/api';

export default function RepresentativesPage() {
  const [representatives, setRepresentatives] = useState<Representative[]>([]);
  const [pagination, setPagination] = useState({ page: 1, limit: 20, total: 0, totalPages: 0 });
  const [loading, setLoading] = useState(false);
  const [search, setSearch] = useState('');
  const [debouncedSearch, setDebouncedSearch] = useState('');
  const searchTimerRef = useRef<ReturnType<typeof setTimeout>>(undefined);
  const [postalCodeFilter, setPostalCodeFilter] = useState('');
  const [debouncedPostalCode, setDebouncedPostalCode] = useState('');
  const postalTimerRef = useRef<ReturnType<typeof setTimeout>>(undefined);

  const [lookupInput, setLookupInput] = useState('');
  const [lookupLoading, setLookupLoading] = useState(false);

  const [stats, setStats] = useState<CacheStats | null>(null);
  const [detailDrawerOpen, setDetailDrawerOpen] = useState(false);
  const screens = Grid.useBreakpoint();
  const isMobile = !screens.md;
  const [selectedRep, setSelectedRep] = useState<Representative | null>(null);

  const handleSearchChange = (value: string) => {
    setSearch(value);
    clearTimeout(searchTimerRef.current);
    searchTimerRef.current = setTimeout(() => setDebouncedSearch(value), 300);
  };

  const handlePostalCodeFilterChange = (value: string) => {
    setPostalCodeFilter(value);
    clearTimeout(postalTimerRef.current);
    postalTimerRef.current = setTimeout(() => setDebouncedPostalCode(value), 300);
  };

  useEffect(() => {
    return () => {
      clearTimeout(searchTimerRef.current);
      clearTimeout(postalTimerRef.current);
    };
  }, []);

  const fetchRepresentatives = useCallback(async (params?: RepresentativesListParams) => {
    setLoading(true);
    try {
      const { data } = await api.get<RepresentativesListResponse>('/representatives', {
        params: {
          page: params?.page ?? pagination.page,
          limit: params?.limit ?? pagination.limit,
          search: params?.search ?? (debouncedSearch || undefined),
          postalCode: params?.postalCode ?? (debouncedPostalCode || undefined),
        },
      });
      setRepresentatives(data.representatives);
      setPagination(data.pagination);
    } catch {
      message.error('Failed to load representatives');
    } finally {
      setLoading(false);
    }
  }, [pagination.page, pagination.limit, debouncedSearch, debouncedPostalCode]);

  const fetchStats = useCallback(async () => {
    try {
      const { data } = await api.get<CacheStats>('/representatives/cache-stats');
      setStats(data);
    } catch {
      // Stats are non-critical
    }
  }, []);

  useEffect(() => {
    fetchRepresentatives({ page: 1 });
  }, [debouncedSearch, debouncedPostalCode]); // eslint-disable-line react-hooks/exhaustive-deps

  useEffect(() => {
    fetchStats();
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  const handleTableChange = (pag: TablePaginationConfig) => {
    fetchRepresentatives({ page: pag.current ?? 1, limit: pag.pageSize ?? 20 });
  };

  const handleLookup = useCallback(async () => {
    const code = lookupInput.replace(/\s/g, '').toUpperCase();
    if (!code) return;
    setLookupLoading(true);
    try {
      const { data } = await api.get<RepresentativeLookupResponse>(
        `/representatives/by-postal/${encodeURIComponent(code)}`,
        { params: { refresh: 'true' } }
      );
      message.success(
        `Found ${data.representatives.length} representative(s) for ${code} (source: ${data.source})`
      );
      // Refresh table and stats
      fetchRepresentatives({ page: 1 });
      fetchStats();
    } catch (err: unknown) {
      const msg =
        (err as { response?: { data?: { error?: { message?: string } } } })
          ?.response?.data?.error?.message || 'Lookup failed';
      message.error(msg);
    } finally {
      setLookupLoading(false);
    }
  }, [lookupInput, fetchRepresentatives, fetchStats]);

  const handleDelete = async (id: string) => {
    try {
      await api.delete(`/representatives/${id}`);
      message.success('Representative removed from cache');
      fetchRepresentatives();
      fetchStats();
    } catch {
      message.error('Failed to delete representative');
    }
  };

  const handleClearPostalCode = async (postalCode: string) => {
    try {
      const { data } = await api.delete<{ deleted: number; postalCode: string }>(
        `/representatives/by-postal/${encodeURIComponent(postalCode)}`
      );
      message.success(`Cleared ${data.deleted} cached rep(s) for ${postalCode}`);
      fetchRepresentatives();
      fetchStats();
    } catch {
      message.error('Failed to clear cache');
    }
  };

  const openDetail = (rep: Representative) => {
    setSelectedRep(rep);
    setDetailDrawerOpen(true);
  };

  const columns: ColumnsType<Representative> = [
    {
      title: 'Name',
      dataIndex: 'name',
      key: 'name',
      render: (name: string | null) => name || '--',
    },
    {
      title: 'Postal Code',
      dataIndex: 'postalCode',
      key: 'postalCode',
      render: (code: string) => <Tag color="blue">{code}</Tag>,
    },
    {
      title: 'Elected Office',
      dataIndex: 'electedOffice',
      key: 'electedOffice',
      render: (office: string | null) => office || '--',
      responsive: ['md'],
    },
    {
      title: 'Party',
      dataIndex: 'partyName',
      key: 'partyName',
      render: (party: string | null) => party || '--',
      responsive: ['lg'],
    },
    {
      title: 'District',
      dataIndex: 'districtName',
      key: 'districtName',
      render: (district: string | null) => district || '--',
      responsive: ['lg'],
    },
    {
      title: 'Cached',
      dataIndex: 'cachedAt',
      key: 'cachedAt',
      render: (date: string) => dayjs(date).format('YYYY-MM-DD'),
      responsive: ['md'],
    },
    {
      title: 'Actions',
      key: 'actions',
      render: (_: unknown, record: Representative) => (
        <Space>
          <Button
            type="link"
            size="small"
            icon={<EyeOutlined />}
            onClick={() => openDetail(record)}
          />
          {record.id && (
            <Popconfirm
              title="Remove from cache?"
              onConfirm={() => handleDelete(record.id!)}
            >
              <Button type="link" size="small" danger icon={<DeleteOutlined />} />
            </Popconfirm>
          )}
        </Space>
      ),
    },
  ];

  const { setPageHeader } = useOutletContext<AppOutletContext>();
  const navigate = useNavigate();

  useEffect(() => {
    setPageHeader({ title: 'Representatives Cache' });
    return () => setPageHeader(null);
  }, [setPageHeader]);

  const drawerWidth = isMobile ? 0 : 640;

  return (
    <>
      <div style={{ marginRight: detailDrawerOpen ? drawerWidth : 0, transition: 'margin-right 0.15s cubic-bezier(0.2, 0, 0, 1)' }}>
        {stats && (
          <Row gutter={[16, 16]} style={{ marginBottom: 16 }}>
            <Col xs={24} sm={8}>
              <Card size="small">
                <Statistic title="Cached Representatives" value={stats.totalRepresentatives} />
              </Card>
            </Col>
            <Col xs={24} sm={8}>
              <Card size="small">
                <Statistic title="Postal Codes with Reps" value={stats.postalCodesWithRepresentatives} />
              </Card>
            </Col>
            <Col xs={24} sm={8}>
              <Card size="small">
                <Statistic title="Postal Codes with Geo Data" value={stats.totalPostalCodes} />
              </Card>
            </Col>
          </Row>
        )}

        <Row gutter={[12, 12]} style={{ marginBottom: 16 }} align="middle">
          <Col flex="auto">
            <Space wrap>
              <Button
                icon={<SendOutlined />}
                onClick={() => navigate('/app/campaigns')}
              >
                Campaigns
              </Button>
              <Input
                placeholder="Postal code (e.g. T2P1N3)"
                value={lookupInput}
                onChange={(e) => setLookupInput(e.target.value)}
                onPressEnter={handleLookup}
                style={{ width: 200 }}
              />
              <Button
                type="primary"
                icon={<ReloadOutlined />}
                loading={lookupLoading}
                onClick={handleLookup}
              >
                Lookup / Refresh
              </Button>
            </Space>
          </Col>
        </Row>

        <Row gutter={[12, 12]} style={{ marginBottom: 16 }}>
          <Col xs={24} sm={12} md={8}>
            <Input
              placeholder="Search name, email, or district"
              prefix={<SearchOutlined />}
              value={search}
              onChange={(e) => handleSearchChange(e.target.value)}
              allowClear
            />
          </Col>
          <Col xs={12} sm={7} md={4}>
            <Input
              placeholder="Filter by postal code"
              value={postalCodeFilter}
              onChange={(e) => handlePostalCodeFilterChange(e.target.value)}
              allowClear
            />
          </Col>
        </Row>

        <Table<Representative>
          columns={columns}
          dataSource={representatives}
          rowKey={(r) => r.id || `${r.postalCode}-${r.name}-${r.electedOffice}`}
          loading={loading}
          pagination={{
            current: pagination.page,
            pageSize: pagination.limit,
            total: pagination.total,
            showSizeChanger: true,
            showTotal: (total) => `${total} representatives`,
          }}
          onChange={handleTableChange}
          scroll={{ x: 'max-content' }}
          locale={{ emptyText: 'No cached representatives. Use the lookup above to fetch and cache results.' }}
        />
      </div>

      {/* Detail Drawer */}
      <Drawer
        title="Representative Details"
        open={detailDrawerOpen}
        destroyOnHidden
        mask={false}
        width={isMobile ? '100%' : 640}
        rootStyle={{ position: 'absolute', top: 64, height: 'calc(100vh - 64px)' }}
        onClose={() => {
          setDetailDrawerOpen(false);
          setSelectedRep(null);
        }}
        extra={
          <Space>
            {selectedRep?.postalCode && (
              <Popconfirm
                title={`Clear all cached reps for ${selectedRep.postalCode}?`}
                onConfirm={() => {
                  handleClearPostalCode(selectedRep.postalCode);
                  setDetailDrawerOpen(false);
                  setSelectedRep(null);
                }}
              >
                <Button danger>Clear Cache</Button>
              </Popconfirm>
            )}
            <Button onClick={() => { setDetailDrawerOpen(false); setSelectedRep(null); }}>
              Close
            </Button>
          </Space>
        }
      >
        {selectedRep && (
          <Descriptions column={1} bordered size="small">
            <Descriptions.Item label="Name">{selectedRep.name || '--'}</Descriptions.Item>
            <Descriptions.Item label="Email">{selectedRep.email || '--'}</Descriptions.Item>
            <Descriptions.Item label="Postal Code">{selectedRep.postalCode}</Descriptions.Item>
            <Descriptions.Item label="Elected Office">{selectedRep.electedOffice || '--'}</Descriptions.Item>
            <Descriptions.Item label="Party">{selectedRep.partyName || '--'}</Descriptions.Item>
            <Descriptions.Item label="District">{selectedRep.districtName || '--'}</Descriptions.Item>
            <Descriptions.Item label="Representative Set">{selectedRep.representativeSetName || '--'}</Descriptions.Item>
            <Descriptions.Item label="URL">
              {selectedRep.url ? (
                <a href={selectedRep.url} target="_blank" rel="noopener noreferrer">
                  {selectedRep.url}
                </a>
              ) : '--'}
            </Descriptions.Item>
            <Descriptions.Item label="Photo URL">
              {selectedRep.photoUrl ? (
                <a href={selectedRep.photoUrl} target="_blank" rel="noopener noreferrer">
                  {selectedRep.photoUrl}
                </a>
              ) : '--'}
            </Descriptions.Item>
            <Descriptions.Item label="Offices">
              {selectedRep.offices && Array.isArray(selectedRep.offices) && selectedRep.offices.length > 0
                ? (
                  <pre style={{ margin: 0, fontSize: 12, whiteSpace: 'pre-wrap' }}>
                    {JSON.stringify(selectedRep.offices, null, 2)}
                  </pre>
                )
                : '--'}
            </Descriptions.Item>
            <Descriptions.Item label="Cached At">
              {dayjs(selectedRep.cachedAt).format('YYYY-MM-DD HH:mm:ss')}
            </Descriptions.Item>
          </Descriptions>
        )}
      </Drawer>
    </>
  );
}
