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

const ENTITY_LABEL = 'Staff'; // e.g. 'State', 'District'
const ENTITY_ENDPOINT = ENDPOINTS.STAFF; // e.g. ENDPOINTS.STATES

interface DataRecord {
  key: number;
  name: string;
  email: string;
  mobileNo: string;
  status: boolean;
  roleId: number;
  role?: {
    id: number;
    name: string;
  };
}

interface RoleOption {
  id: number;
  name: string;
}

const Staff = () => {
  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>>({});
  // roles used to populate the "Role" dropdown in the Add/Edit form
  const [roles, setRoles] = useState<RoleOption[]>([]);
  const [pagination, setPagination] = useState({
    current: 1,
    pageSize: Number(import.meta.env.VITE_PAGE_SIZE) || 10,
    total: 0,
    totalPages: 0,
  });

  // const handleExport = () => {
  //   message.info('Export functionality coming soon');
  // };

  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.
  // Password is intentionally left blank — it's only sent if the user
  // types a new one (see handleSubmit).
  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,
        email: record.email,
        mobileNo: record.mobileNo,
        roleId: record.roleId,
        status: record.status,
      });

      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 roles — ONLY ONCE on mount, same reasoning as statuses.
  // Used to populate the "Role" dropdown in the Add/Edit form.
  // -----------------------------
  const fetchRoles = async () => {
    try {
      const res = await jwtAxios.get(ENDPOINTS.STAFF_ROLE);
      // Response shape: { message, result: [ { id, name }, ... ] }
      setRoles(res.data?.result || []);
    } catch (err: any) {
      message.error(err.response?.data?.message || 'Failed to fetch roles');
      setRoles([]);
    }
  };

  // -----------------------------
  // 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 + roles once each, plus first page of records.
  useEffect(() => {
    fetchStatuses();
    fetchRoles();
    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 payload: any = {
        name: values.name,
        email: values.email,
        mobileNo: values.mobileNo,
        roleId: values.roleId,
        status: values.status,
      };

      // On Add, password is always required and sent.
      // On Edit, only send it if the user actually typed a new one —
      // an empty password field should not overwrite the existing one.
      if (!editingId || values.password) {
        payload.password = values.password;
      }

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

      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) {
      const responseData = err.response?.data;
      const fieldErrors = responseData?.errors;

      if (fieldErrors && typeof fieldErrors === 'object') {
        // Map { email: "Email already exists", ... } onto the matching
        // Form.Item (name="email") so the error shows right under that
        // field instead of only as a toast.
        form.setFields(
          Object.entries(fieldErrors).map(([name, error]) => ({
            name,
            errors: [String(error)],
          }))
        );
        message.error(responseData?.message || 'Please fix the highlighted fields');
      } else {
        message.error(
          responseData?.message ||
          `Failed to ${editingId ? 'update' : 'add'} ${ENTITY_LABEL.toLowerCase()}`
        );
      }
    } finally {
      setLoading(false);
    }
  };

  const columns = [
    { title: 'ID', dataIndex: 'id' },
    {
      title: 'Name',
      dataIndex: 'name',
    },
    {
      title: 'Email',
      dataIndex: 'email',
    },
    {
      title: 'Mobile No',
      dataIndex: 'mobileNo',
      render: (mobileNo: DataRecord['mobileNo']) => (mobileNo ? mobileNo : '-')
    },
    {
      title: 'Role',
      dataIndex: 'role',
      render: (role: DataRecord['role']) => {
        return (
          <Tag color="blue">{role?.name}</Tag>
        )
      },
    },
    {
      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>
        </Space>
      ),
    },
  ];

  return (
    <div>
      <Spin spinning={loading}>
        <AppContainer
          title={`${ENTITY_LABEL}`}
          headerAction={
            <Space>
              {/* <Button
                icon={<DownloadOutlined />}
                style={{ color: '#52c41a', borderColor: '#52c41a' }}
                onClick={handleExport}
              >
                Export
              </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}>
            <Row gutter={16}>
              <Col xs={24} sm={24} md={12}>
                <Form.Item label="Name" name="name" rules={[{ required: true }]}>
                  <Input />
                </Form.Item>
              </Col>

              <Col xs={24} sm={24} md={12}>
                <Form.Item
                  label="Email"
                  name="email"
                  rules={[
                    { required: true },
                    { type: 'email', message: 'Enter a valid email address' },
                  ]}
                >
                  <Input />
                </Form.Item>
              </Col>

              <Col xs={24} sm={24} md={12}>
                <Form.Item
                  label="Mobile No"
                  name="mobileNo"
                  rules={[
                    { required: true },
                    {
                      pattern: /^[0-9]{10}$/,
                      message: 'Enter a valid 10-digit mobile number',
                    },
                  ]}
                >
                  <Input maxLength={10} />
                </Form.Item>
              </Col>

              <Col xs={24} sm={24} md={12}>
                <Form.Item label="Role" name="roleId" rules={[{ required: true }]}>
                  <Select
                    showSearch
                    placeholder="Select a role"
                    optionFilterProp="label"
                    filterOption={(input, option) =>
                      (option?.label ?? '').toLowerCase().includes(input.toLowerCase())
                    }
                    options={roles.map((role) => ({
                      label: role.name,
                      value: role.id,
                    }))}
                  />
                </Form.Item>
              </Col>

              <Col xs={24} sm={24} md={12}>
                <Form.Item
                  label="Password"
                  name="password"
                  rules={[
                    { required: !editingId, message: 'Please enter a password' },
                    { min: 8, message: 'Password must be at least 8 characters' },
                  ]}
                  extra={editingId ? 'Leave blank to keep the current password' : undefined}
                >
                  <Input.Password autoComplete="new-password" />
                </Form.Item>
              </Col>

              <Col xs={24} sm={24} md={12}>
                <Form.Item
                  label="Confirm Password"
                  name="confirmPassword"
                  dependencies={['password']}
                  rules={[
                    {
                      required: !editingId,
                      message: 'Please confirm your password',
                    },
                    ({ getFieldValue }) => ({
                      validator(_, value) {
                        const password = getFieldValue('password');

                        // Editing and password left blank
                        if (editingId && !password && !value) {
                          return Promise.resolve();
                        }

                        if (!value || password === value) {
                          return Promise.resolve();
                        }

                        return Promise.reject(
                          new Error('Passwords do not match')
                        );
                      },
                    }),
                  ]}
                >
                  <Input.Password autoComplete="new-password" />
                </Form.Item>
              </Col>

              <Col xs={24} sm={24} md={12}>
                <Form.Item
                  label="Status"
                  name="status"
                  initialValue={true}
                  rules={[{ required: true }]}
                >
                  <Select
                    options={Object.entries(statuses).map(([label, value]) => ({
                      label,
                      value, // boolean
                    }))}
                  />
                </Form.Item>
              </Col>
            </Row>
          </Form>
        </Modal>
      </Spin>
    </div>
  );
};

export default Staff;