import { useEffect, useRef, useState } from 'react';
import {
  Button,
  Form,
  Input,
  Modal,
  Popconfirm,
  Popover,
  Select,
  Space,
  Spin,
  Table,
  Tag,
  Typography,
  Alert,
  message,
} from 'antd';
import {
  PlusOutlined,
  EditOutlined,
  DeleteOutlined,
  FilterOutlined,
  UploadOutlined,
  DownloadOutlined,
} from '@ant-design/icons';
import { AppContainer } from '../../components/AppContainer';
import jwtAxios from '../../api/axiosInstance';
import { ENDPOINTS } from '../../api/endpoints';

const { Text } = Typography;

const ENTITY_LABEL = 'Districts'; // e.g. 'State', 'District'
const ENTITY_ENDPOINT = ENDPOINTS.DISTRICTS; // e.g. ENDPOINTS.STATES

interface RowResult {
  row: number;
  name: string;
  status: 'imported' | 'skipped';
  reason?: string;
}

interface DataRecord {
  key: number;
  name: string;
  tamilName: string;
  status: boolean;
  stateId: string;
  state?: {
    id: string;
    name: string;
    tamilName: string | null;
  };
}

interface StateOption {
  id: string;
  name: string;
  tamilName: string | null;
}

const Districts = () => {
  const [form] = Form.useForm();
  const [open, setOpen] = useState(false);
  // null = "Add" mode. Holds the record's id while editing.
  const [editingId, setEditingId] = useState<string | null>(null);
  const [searchText, setSearchText] = useState('');
  // null = "All" (no status filter sent to backend)
  const [statusFilter, setStatusFilter] = useState<boolean | null>(null);
  const [data, setData] = useState<DataRecord[]>([]);
  const [loading, setLoading] = useState<boolean>(false);
  // statuses stays exactly as the API returns it: { "Active": true, "Inactive": false }
  const [statuses, setStatuses] = useState<Record<string, boolean>>({});
  // states used to populate the "State" dropdown in the Add/Edit form
  const [states, setStates] = useState<StateOption[]>([]);
  const [pagination, setPagination] = useState({
    current: 1,
    pageSize: Number(import.meta.env.VITE_PAGE_SIZE) || 10,
    total: 0,
    totalPages: 0,
  });

  // ── Import modal state ──
  const [importOpen, setImportOpen] = useState(false);
  const [importLoading, setImportLoading] = useState(false);
  const [importFile, setImportFile] = useState<File | null>(null);
  const [importResults, setImportResults] = useState<{ importedCount: number; skippedCount: number; results: RowResult[] } | null>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);

  // ── Import handlers ──────────────────────────────────────────
  const handleOpenImport = () => {
    setImportFile(null);
    setImportResults(null);
    setImportOpen(true);
  };

  const handleDownloadTemplate = async () => {
    try {
      const response = await jwtAxios.get(ENDPOINTS.DISTRICTS_IMPORT_TEMPLATE, { responseType: 'blob' });
      const blob = new Blob([response.data], {
        type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      });
      const url = window.URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = url;
      link.download = 'district-import-template.xlsx';
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.URL.revokeObjectURL(url);
    } catch {
      message.error('Failed to download template');
    }
  };

  const handleImportSave = async () => {
    if (!importFile) {
      message.warning('Please choose an Excel file first.');
      return;
    }
    setImportLoading(true);
    try {
      const formData = new FormData();
      formData.append('file', importFile);
      const res = await jwtAxios.post(ENDPOINTS.DISTRICTS_IMPORT, formData, {
        headers: { 'Content-Type': 'multipart/form-data' },
      });
      setImportResults(res.data);
      message.success(res.data.message);
      fetchData(1, pagination.pageSize, '');
    } catch (err: any) {
      message.error(err.response?.data?.message || 'Import failed');
    } finally {
      setImportLoading(false);
    }
  };

  const handleAdd = () => {
    setEditingId(null);
    form.resetFields();
    setOpen(true);
  };

  // Edit button click — GET the single record by id, then populate the
  // same form/modal used for "Add". We just switch modes with editingId.
  const handleEdit = async (id: string) => {
    setLoading(true);
    try {
      const res = await jwtAxios.get(`${ENTITY_ENDPOINT}/${id}`);
      // Adjust this line if your single-record response is wrapped
      // differently (e.g. res.data.result.data instead of res.data.result).
      const record = res.data?.result ?? res.data;

      form.setFieldsValue({
        name: record.name,
        tamilName: record.tamilName,
        status: record.status,
        stateId: record.stateId,
      });

      setEditingId(id);
      setOpen(true);
    } catch (err: any) {
      message.error(err.response?.data?.message || `Failed to load ${ENTITY_LABEL.toLowerCase()}`);
    } finally {
      setLoading(false);
    }
  };

  // -----------------------------
  // Fetch statuses — ONLY ONCE on mount. This never changes after load,
  // so it does not belong inside fetchData (which runs on every
  // search / page change).
  // -----------------------------
  const fetchStatuses = async () => {
    try {
      const statusRes = await jwtAxios.get(ENDPOINTS.STATUS);
      // Response shape is already { "Active": true, "Inactive": false }
      setStatuses(statusRes.data || {});
    } catch (err: any) {
      message.error(err.response?.data?.message || 'Failed to fetch statuses');
      setStatuses({});
    }
  };

  // -----------------------------
  // Fetch states — ONLY ONCE on mount, same reasoning as statuses.
  // Used to populate the searchable "State" dropdown in the Add/Edit form.
  // -----------------------------
  const fetchStates = async () => {
    try {
      const res = await jwtAxios.get(ENDPOINTS.STATES_WITH_DISTRICTS);
      // Response shape: { message, result: [ { id, name, tamilName }, ... ] }
      setStates(res.data?.result || []);
    } catch (err: any) {
      message.error(err.response?.data?.message || 'Failed to fetch states');
      setStates([]);
    }
  };

  // -----------------------------
  // Fetch list — runs on initial load, page change, page-size change,
  // and whenever a search or status filter is triggered.
  // -----------------------------
  const fetchData = async (
    page: number = pagination.current,
    limit: number = pagination.pageSize,
    search: string = searchText,
    status: boolean | null | undefined = statusFilter
  ) => {
    setLoading(true);

    try {
      // Only add "status" to the query string when a filter is actually
      // selected. null / undefined means no status param at all.
      let url = ENTITY_ENDPOINT + `?page=${page}&limit=${limit}&search=${search}`;
      if (status !== null && status !== undefined) {
        url += `&status=${status}`; // sends true or false
      }

      const res = await jwtAxios.get(url);
      // message.success(res?.data?.message);
      // Response shape: { message, result: { data: [...], meta: { total, page, limit, totalPages } } }
      const records = res.data?.result?.data || [];
      const meta = res.data?.result?.meta || {};

      const formattedData = records.map((item: any) => ({
        key: item.id,
        ...item,
      }));

      setData(formattedData);
      setPagination((prev) => ({
        ...prev,
        current: meta.page ?? page,
        pageSize: meta.limit ?? limit,
        total: meta.total ?? prev.total,
        totalPages: meta.totalPages ?? prev.totalPages,
      }));
    } catch (err: any) {
      message.error(err.response?.data?.message || 'Failed to fetch data');
      setData([]);
    } finally {
      setLoading(false);
    }
  };

  // Initial load: statuses + states once each, plus first page of records.
  useEffect(() => {
    fetchStatuses();
    fetchStates();
    fetchData(1, pagination.pageSize, '');
  }, []);

  // -----------------------------
  // Search — simple & easy to follow:
  // 1. onChange just updates the input's text (what you see typed).
  // 2. onSearch (Enter key or the search icon) actually triggers the API call,
  //    and resets pagination back to page 1 since it's a new result set.
  // No debounce, no extra state — one function does the work.
  // -----------------------------
  const handleSearch = (value: string) => {
    fetchData(1, pagination.pageSize, value, statusFilter);
  };

  // Status dropdown — same idea as search: pick a value, refetch from
  // page 1, using the current search text so both filters combine.
  const handleStatusFilterChange = (value: boolean | null | undefined) => {
    console.log("Changed:", value);
    const status = value ?? null;

    setStatusFilter(status);
    fetchData(1, pagination.pageSize, searchText, status);
  };

  // Delete — actual API call happens only after the user confirms
  // in the Popconfirm popup (see the Actions column below).
  const handleDelete = async (id: string) => {
    setLoading(true);
    try {
      const res = await jwtAxios.delete(`${ENTITY_ENDPOINT}/${id}`);
      message.success(res.data?.message || `${ENTITY_LABEL} deleted successfully`);
      fetchData(pagination.current, pagination.pageSize, searchText, statusFilter);
    } catch (err: any) {
      message.error(err.response?.data?.message || `Failed to delete ${ENTITY_LABEL.toLowerCase()}`);
    } finally {
      setLoading(false);
    }
  };

  const handleSubmit = async (values: any) => {
    setLoading(true);

    try {
      const response = editingId
        ? await jwtAxios.put(`${ENTITY_ENDPOINT}/${editingId}`, values)
        : await jwtAxios.post(ENTITY_ENDPOINT, values);

      message.success(
        response.data?.message ||
        `${ENTITY_LABEL} ${editingId ? 'updated' : 'added'} successfully`
      );
      setOpen(false);
      setEditingId(null);
      form.resetFields();
      fetchData(pagination.current, pagination.pageSize, searchText, statusFilter); // refresh current view only
    } catch (err: any) {
      message.error(
        err.response?.data?.message ||
        `Failed to ${editingId ? 'update' : 'add'} ${ENTITY_LABEL.toLowerCase()}`
      );
    } finally {
      setLoading(false);
    }
  };

  const columns = [
    { title: 'ID', dataIndex: 'id' },
    {
      title: 'Name',
      dataIndex: 'name',
    },
    {
      title: 'Tamil Name',
      dataIndex: 'tamilName',
    },
    {
      title: 'State',
      dataIndex: 'state',
      render: (state: DataRecord['state']) =>
        state ? `${state.name}${state.tamilName ? `(${state.tamilName})` : ''}` : '-',
    },
    {
      title: 'Status',
      dataIndex: 'status',
      render: (status: boolean) => (
        <Tag color={status ? 'green' : 'red'}>{status ? 'Active' : 'Inactive'}</Tag>
      ),
    },
    {
      title: 'Actions',
      render: (_: any, record: any) => (
        <Space>
          <Popover content={"Edit"}>
            <Button type="link" icon={<EditOutlined />} onClick={() => handleEdit(record.id)} />
          </Popover>
          <Popover content={"Delete"}>
            <Popconfirm
              title={`Delete ${ENTITY_LABEL.toLowerCase()}`}
              description={`Are you sure you want to delete "${record.name}"?`}
              okText="Delete"
              cancelText="Cancel"
              okButtonProps={{ danger: true }}
              onConfirm={() => handleDelete(record.id)} // API call fires only after confirm
            >
              <Button danger type="link" icon={<DeleteOutlined />} />
            </Popconfirm>
          </Popover>
        </Space>
      ),
    },
  ];

  return (
    <div>
      <Spin spinning={loading}>
        <AppContainer
          title={`${ENTITY_LABEL}`}
          headerAction={
            <Space>
              <Button
                icon={<UploadOutlined />}
                onClick={handleOpenImport}
              >
                Import
              </Button>
              <Button
                type="primary"
                icon={<PlusOutlined />}
                onClick={handleAdd}
                className="bg-green-600"
              >
                Add {ENTITY_LABEL}
              </Button>
            </Space>
          }
        >
          {/* Toolbar Section */}
          <div className="flex justify-between items-center mb-4 pb-4 border-b border-gray-200">
            <Space>
              <Select
                placeholder={
                  <>
                    <FilterOutlined /> Status
                  </>
                }
                allowClear
                style={{ width: 150 }}
                value={statusFilter}
                onChange={handleStatusFilterChange} // fires when a status is picked
                onClear={() => handleStatusFilterChange(undefined)} // back to "All"
                options={Object.entries(statuses).map(([label, value]) => ({
                  label,
                  value, // boolean: true / false, sent to backend as-is
                }))}
              />
              <Input.Search
                placeholder="Search..."
                value={searchText}
                onChange={(e) => {
                  const val = e.target.value;
                  setSearchText(val);
                  if (!val) {
                    handleSearch('');
                  }
                }}
                onSearch={handleSearch}
                allowClear
                style={{ width: 200 }}
              />
            </Space>
          </div>

          {/* Table Section */}
          <Table
            rowKey="key"
            columns={columns}
            dataSource={data}
            loading={loading}
            scroll={{ x: 'max-content', y: 400 }}
            pagination={{
              current: pagination.current,
              pageSize: pagination.pageSize,
              total: pagination.total,
              showSizeChanger: true,
            }}
            onChange={(pageInfo) => {
              fetchData(pageInfo.current!, pageInfo.pageSize!, searchText, statusFilter);
            }}
          />
          <div className="text-center mt-2">
            <Tag color="cyan">
              Page {pagination.current} of {pagination.totalPages}
            </Tag>
          </div>
        </AppContainer>

        <Modal
          title={editingId ? `Edit ${ENTITY_LABEL}` : `Add ${ENTITY_LABEL}`}
          open={open}
          onCancel={() => {
            setOpen(false);
            setEditingId(null);
          }}
          onOk={() => form.submit()}
          confirmLoading={loading}
          okText="Submit"
        >
          <Form form={form} layout="vertical" onFinish={handleSubmit}>
            {/* Searchable state dropdown. showSearch + filterOption let the
                user type a few letters of the state name to filter the list. */}
            <Form.Item label="State" name="stateId" rules={[{ required: true }]}>
              <Select
                showSearch
                placeholder="Select a state"
                optionFilterProp="label" // search matches against `label` below
                filterOption={(input, option) =>
                  (option?.label ?? '').toLowerCase().includes(input.toLowerCase())
                }
                options={states.map((state) => ({
                  label: state.name,
                  value: state.id,
                }))}
              />
            </Form.Item>

            <Form.Item label="District Name" name="name" rules={[{ required: true }]}>
              <Input />
            </Form.Item>

            <Form.Item label="District in Tamil" name="tamilName" rules={[{ required: true }]}>
              <Input />
            </Form.Item>

            <Form.Item
              label="Status"
              name="status"
              initialValue={true}
              rules={[{ required: true }]}
            >
              <Select
                options={Object.entries(statuses).map(([label, value]) => ({
                  label,
                  value, // boolean
                }))}
              />
            </Form.Item>
          </Form>
        </Modal>

        {/* ── Bulk Import Modal ── */}
        <Modal
          title="District Bulk Import"
          open={importOpen}
          onCancel={() => setImportOpen(false)}
          footer={null}
          width={780}
          destroyOnHidden
        >
          <div style={{ display: 'flex', gap: 24 }}>
            {/* Left panel */}
            <div style={{ flex: 1 }}>
              <div style={{ marginBottom: 16 }}>
                <Text strong>Upload File <span style={{ color: 'red' }}>*</span></Text>
                <div style={{ marginTop: 8, display: 'flex', alignItems: 'center', gap: 8 }}>
                  <Button
                    icon={<UploadOutlined />}
                    onClick={() => fileInputRef.current?.click()}
                    style={{ background: '#1d1b4b', color: '#fff', border: 'none' }}
                  >
                    CHOOSE FILE
                  </Button>
                  <Text type={importFile ? 'success' : 'secondary'}>
                    {importFile ? importFile.name : 'No file chosen'}
                  </Text>
                  <input
                    ref={fileInputRef}
                    type="file"
                    accept=".xlsx"
                    style={{ display: 'none' }}
                    onChange={(e) => {
                      const file = e.target.files?.[0] ?? null;
                      setImportFile(file);
                      setImportResults(null);
                      e.target.value = '';
                    }}
                  />
                </div>
              </div>

              <Button
                icon={<DownloadOutlined />}
                type="link"
                style={{ paddingLeft: 0, marginBottom: 16 }}
                onClick={handleDownloadTemplate}
              >
                Download Template
              </Button>

              {/* Import results summary */}
              {importResults && (
                <div style={{ marginBottom: 12 }}>
                  <Alert
                    type={importResults.skippedCount > 0 ? 'warning' : 'success'}
                    title={`${importResults.importedCount} imported, ${importResults.skippedCount} skipped`}
                    style={{ marginBottom: 8 }}
                  />
                  {importResults.results.filter(r => r.status === 'skipped').length > 0 && (
                    <div style={{ maxHeight: 160, overflowY: 'auto', fontSize: 12 }}>
                      {importResults.results.filter(r => r.status === 'skipped').map(r => (
                        <div key={r.row} style={{ color: '#cf1322', marginBottom: 4 }}>
                          Row {r.row} — <strong>{r.name}</strong>: {r.reason}
                        </div>
                      ))}
                    </div>
                  )}
                </div>
              )}

              <div style={{ display: 'flex', gap: 12, marginTop: 8 }}>
                <Button danger onClick={() => setImportOpen(false)} style={{ flex: 1 }}>
                  Cancel
                </Button>
                <Button
                  type="primary"
                  loading={importLoading}
                  onClick={handleImportSave}
                  style={{ flex: 1, background: '#1d1b4b', border: 'none' }}
                >
                  Save
                </Button>
              </div>
            </div>

            {/* Right panel — instructions */}
            <div
              className="
                flex-1
                bg-[#fafafa]
                border border-[#e8e8e8]
                rounded-lg
                p-4
                text-[13px]
              "
            >
              <Text strong>Important Instructions:</Text>
              <ul style={{ marginTop: 10, paddingLeft: 18, lineHeight: 2 }}>
                <li>Upload only Excel (.xlsx) files.</li>
                <li>All required columns must be present in the sheet.</li>
                <li>Maximum file size: 5 MB.</li>
                <li style={{ color: '#cf1322' }}>
                  You can upload / import only <strong>new districts</strong> — they must not already exist in this software.
                </li>
                <li><strong>State Name</strong> is required and must match an existing State in the system.</li>
                <li><strong>District Name</strong> is required and must be unique.</li>
                <li><strong>Tamil Name</strong> is required and must be unique.</li>
                <li>All imported districts are set to <strong>Active</strong> by default.</li>
              </ul>
            </div>
          </div>
        </Modal>
      </Spin>
    </div>
  );
};

export default Districts;
