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

const ENTITY_LABEL = 'Supplier Payment';
const ENTITY_ENDPOINT = ENDPOINTS.SUPPLIER_PAYMENTS;
const ENTITY_EXPORT = ENDPOINTS.SUPPLIER_PAYMENTS_EXPORT;
const ENTITY_EXPORT_PDF = ENDPOINTS.SUPPLIER_PAYMENTS_EXPORT_PDF;

interface DataRecord {
  key: string;
  id: string;
  paymentDate: string;
  amount: string;
  paymentMode: string;
  referenceNo: string;
  remarks: string;
  supplierId: string;
  supplier?: { name: string; outstandingBalance?: string | number };
  isWhatsappMessageSent?: boolean;
}

interface SupplierOption {
  id: string;
  name: string;
  outstandingBalance: string | number;
}

const { RangePicker } = DatePicker;

const SupplierPayments = () => {
  const [form] = Form.useForm();
  const [open, setOpen] = useState(false);
  const [editingId, setEditingId] = useState<string | null>(null);
  const [initialEditAmount, setInitialEditAmount] = useState<number>(0);
  const [searchText, setSearchText] = useState('');
  const [dateRange, setDateRange] = useState<[Dayjs, Dayjs] | null>(null);
  const [data, setData] = useState<DataRecord[]>([]);
  const [loading, setLoading] = useState<boolean>(false);
  const [metaLoading, setMetaLoading] = useState<boolean>(false);
  const [suppliers, setSuppliers] = useState<SupplierOption[]>([]);
  const [selectedSupplierBalance, setSelectedSupplierBalance] = useState<number | null>(null);
  const [paymentModes, setPaymentModes] = useState<{ label: string, value: string }[]>([]);

  const [exportPdfLoading, setExportPdfLoading] = useState<boolean>(false);
  const [viewOpen, setViewOpen] = useState(false);
  const [viewLoading, setViewLoading] = useState(false);
  const [viewRecord, setViewRecord] = useState<any>(null);

  const [pagination, setPagination] = useState({
    current: 1,
    pageSize: Number(import.meta.env.VITE_PAGE_SIZE) || 10,
    total: 0,
    totalPages: 0,
  });

  const handleExport = async () => {
    if (!data || data.length === 0) {
      message.warning('No data available to export');
      return;
    }
    setLoading(true);
    try {
      const params = new URLSearchParams();
      if (searchText) params.set('search', searchText);
      if (dateRange) {
        params.set('dateFrom', dateRange[0].format('YYYY-MM-DD'));
        params.set('dateTo', dateRange[1].format('YYYY-MM-DD'));
      }

      const response = await jwtAxios.get(
        `${ENTITY_EXPORT}?${params.toString()}`,
        { responseType: 'blob' }
      );

      const disposition = response.headers['content-disposition'];
      let fileName = `supplier-payments-${dayjs().format('YYYY-MM-DD_HHmmss')}.xlsx`;
      if (disposition) {
        const match = disposition.match(/filename\*?=(?:UTF-8'')?"?([^"\n;]+)"?/i);
        if (match?.[1]) fileName = decodeURIComponent(match[1]);
      }

      const blob = new Blob([response.data], {
        type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      });
      const objectUrl = window.URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = objectUrl;
      link.download = fileName;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.URL.revokeObjectURL(objectUrl);

      message.success('Supplier payments exported successfully');
    } catch (err: any) {
      message.error(err.response?.data?.message || 'Failed to export supplier payments');
    } finally {
      setLoading(false);
    }
  };

  const handleExportPdf = async () => {
    if (!data || data.length === 0) {
      message.warning('No data available to export');
      return;
    }
    setExportPdfLoading(true);
    try {
      const params = new URLSearchParams();
      if (searchText) params.set('search', searchText);
      if (dateRange) {
        params.set('dateFrom', dateRange[0].format('YYYY-MM-DD'));
        params.set('dateTo', dateRange[1].format('YYYY-MM-DD'));
      }

      const response = await jwtAxios.get(
        `${ENTITY_EXPORT_PDF}?${params.toString()}`,
        { responseType: 'blob' }
      );

      const disposition = response.headers['content-disposition'];
      let fileName = `supplier-payments-${dayjs().format('YYYY-MM-DD')}.pdf`;
      if (disposition) {
        const match = disposition.match(/filename\*?=(?:UTF-8'')?"?([^"\n;]+)"?/i);
        if (match?.[1]) fileName = decodeURIComponent(match[1]);
      }

      const blob = new Blob([response.data], { type: 'application/pdf' });
      const objectUrl = window.URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = objectUrl;
      link.download = fileName;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.URL.revokeObjectURL(objectUrl);

      message.success('Supplier payments exported as PDF successfully');
    } catch (err: any) {
      message.error(err.response?.data?.message || 'Failed to export supplier payments as PDF');
    } finally {
      setExportPdfLoading(false);
    }
  };

  const handleAdd = async () => {
    setEditingId(null);
    setInitialEditAmount(0);
    form.resetFields();
    form.setFieldsValue({ paymentDate: dayjs() });
    setSelectedSupplierBalance(null);
    setOpen(true);
    // Refresh meta dropdown data when opening modal
    await Promise.all([fetchSuppliers(), fetchPaymentModes()]);
  };

  const handleView = async (id: string) => {
    setViewLoading(true);
    setViewOpen(true);
    try {
      const res = await jwtAxios.get(`${ENTITY_ENDPOINT}/${id}`);
      const record = res.data?.result ?? res.data;
      setViewRecord(record);
    } catch (err: any) {
      message.error(err.response?.data?.message || `Failed to load ${ENTITY_LABEL.toLowerCase()}`);
      setViewOpen(false);
    } finally {
      setViewLoading(false);
    }
  };

  const handleEdit = async (id: string) => {
    setLoading(true);
    try {
      const [latestSuppliers] = await Promise.all([fetchSuppliers(), fetchPaymentModes()]);
      const res = await jwtAxios.get(`${ENTITY_ENDPOINT}/${id}`);
      const record = res.data?.result ?? res.data;

      form.setFieldsValue({
        paymentDate: record.paymentDate ? dayjs(record.paymentDate) : undefined,
        supplierId: record.supplierId ? record.supplierId.toString() : undefined,
        amount: Number(record.amount) || 0,
        paymentMode: record.paymentMode,
        referenceNo: record.referenceNo,
        remarks: record.remarks,
      });

      const suppList = latestSuppliers && latestSuppliers.length > 0 ? latestSuppliers : suppliers;
      const supp = suppList.find((s: any) => s.id === record.supplierId?.toString());
      if (supp && supp.outstandingBalance !== undefined) {
        setSelectedSupplierBalance(Number(supp.outstandingBalance));
      } else {
        setSelectedSupplierBalance(null);
      }

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

  const fetchSuppliers = async () => {
    try {
      setMetaLoading(true);
      const res = await jwtAxios.get(`${ENTITY_ENDPOINT}/meta`);
      const records = res.data?.result?.suppliers || [];
      const mapped = records.map((s: any) => ({
        id: s.id.toString(),
        name: s.name,
        outstandingBalance: s.outstandingBalance,
      }));
      setSuppliers(mapped);
      return mapped;
    } catch (err: any) {
      message.error(err.response?.data?.message || 'Failed to fetch suppliers');
      return [];
    } finally {
      setMetaLoading(false);
    }
  };

  const fetchData = async (
    page: number = pagination.current,
    limit: number = pagination.pageSize,
    search: string = searchText,
    range: [Dayjs, Dayjs] | null = dateRange
  ) => {
    setLoading(true);
    try {
      let url = `${ENTITY_ENDPOINT}?page=${page}&limit=${limit}&search=${search}`;
      if (range) {
        url += `&dateFrom=${range[0].format('YYYY-MM-DD')}&dateTo=${range[1].format('YYYY-MM-DD')}`;
      }

      const res = await jwtAxios.get(url);
      const records = res.data?.result?.data || [];
      const metaInfo = res.data?.result?.meta || {};

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

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

  const fetchPaymentModes = async () => {
    try {
      const res = await jwtAxios.get(ENDPOINTS.PAYMENTMODES);
      const modes = res.data?.PaymentMode || {};
      setPaymentModes(Object.entries(modes).map(([key, value]) => ({ label: key, value: String(value) })));
    } catch (err: any) {
      console.error('Failed to fetch payment modes', err);
    }
  };

  useEffect(() => {
    fetchSuppliers();
    fetchData(1, pagination.pageSize, '');
    fetchPaymentModes();
  }, []);

  const handleSearch = (value: string) => {
    fetchData(1, pagination.pageSize, value, dateRange);
  };

  const handleDateRangeChange = (values: any) => {
    const range = values ? (values as [Dayjs, Dayjs]) : null;
    setDateRange(range);
    fetchData(1, pagination.pageSize, searchText, range);
  };

  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, dateRange);
    } catch (err: any) {
      message.error(err.response?.data?.message || `Failed to delete ${ENTITY_LABEL.toLowerCase()}`);
    } finally {
      setLoading(false);
    }
  };

  const executeSubmit = async (values: any) => {
    setLoading(true);
    try {
      const payload = {
        paymentDate: values.paymentDate?.format('YYYY-MM-DD'),
        supplierId: values.supplierId,
        amount: values.amount,
        paymentMode: values.paymentMode,
        referenceNo: values.referenceNo,
        remarks: values.remarks,
      };

      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);
      setInitialEditAmount(0);
      form.resetFields();
      setSelectedSupplierBalance(null);

      fetchSuppliers();
      fetchData(pagination.current, pagination.pageSize, searchText, dateRange);
    } catch (err: any) {
      const responseData = err.response?.data;
      const fieldErrors = responseData?.errors;

      if (fieldErrors && typeof fieldErrors === 'object') {
        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 handleSubmit = async (values: any) => {
    const selectedSupplier = suppliers.find((s) => s.id === values.supplierId);
    const suppBalance = Number(selectedSupplier?.outstandingBalance || 0);
    const amount = Number(values.amount || 0);
    const maxAllowed = editingId ? suppBalance + initialEditAmount : suppBalance;

    if (amount > maxAllowed) {
      message.error(
        `Payment amount (₹${amount.toFixed(2)}) cannot exceed the supplier's outstanding balance (₹${maxAllowed.toFixed(2)}).`
      );
      return;
    }

    if (editingId) {
      await executeSubmit(values);
    } else {
      Modal.confirm({
        title: 'Confirm Supplier Payment',
        content: 'Are you sure you want to submit this supplier payment?',
        okText: 'Submit',
        cancelText: 'Cancel',
        okButtonProps: { className: 'bg-green-600' },
        onOk: async () => {
          await executeSubmit(values);
        },
      });
    }
  };

  const handleWhatsapp = async (paymentId: string) => {
    setLoading(true);
    try {
      await jwtAxios.post(ENDPOINTS.SUPPLIER_PAYMENTS_WHATSAPP_MESSAGE(paymentId));
      message.success('WhatsApp message sent successfully');
      fetchData(pagination.current, pagination.pageSize, searchText, dateRange);
    } catch (err: any) {
      message.error(err?.response?.data?.message || 'Failed to send WhatsApp message');
    } finally {
      setLoading(false);
    }
  };

  const paymentModeColor = (mode: string) => {
    switch (mode) {
      case 'CASH': return 'green';
      case 'BANK': return 'blue';
      case 'UPI': return 'purple';
      default: return 'default';
    }
  };

  const columns = [
    {
      title: "ID",
      dataIndex: "id",
    },
    {
      title: 'Payment Date',
      dataIndex: 'paymentDate',
      render: (date: string) => (date ? dayjs(date).format('DD MMM YYYY') : '-'),
    },
    {
      title: 'Supplier',
      dataIndex: 'supplier',
      render: (supplier: DataRecord['supplier']) => (supplier ? supplier.name : '-'),
    },
    {
      title: 'Amount',
      dataIndex: 'amount',
      render: (amount: string) => Number(amount).toFixed(2),
    },
    {
      title: 'Payment Mode',
      dataIndex: 'paymentMode',
      render: (mode: string) => <Tag color={paymentModeColor(mode)}>{mode}</Tag>,
    },
    {
      title: 'Reference No',
      dataIndex: 'referenceNo',
      render: (ref: string) => ref || '-',
    },
    {
      title: 'Remarks',
      dataIndex: 'remarks',
      render: (remarks: string) => remarks || '-',
    },
    {
      title: 'Actions',
      render: (_: any, record: any) => (
        <Space>
          <Popover content="View">
            <Button type="link" icon={<EyeOutlined />} onClick={() => handleView(record.id)} />
          </Popover>
          <Popover content="Edit">
            <Button type="link" icon={<EditOutlined />} onClick={() => handleEdit(record.id)} />
          </Popover>
          <Popconfirm
            title={`Delete ${ENTITY_LABEL.toLowerCase()}`}
            description={`Are you sure you want to delete this payment?`}
            okText="Delete"
            cancelText="Cancel"
            okButtonProps={{ danger: true }}
            onConfirm={() => handleDelete(record.id)}
          >
            <Button danger type="link" icon={<DeleteOutlined />} />
          </Popconfirm>
          <Popover
            content={
              record.isWhatsappMessageSent
                ? "Payment already sent"
                : "Share Payment via WhatsApp"
            }
          >
            <Button
              disabled={record.isWhatsappMessageSent ?? false}
              type="link"
              className={
                record.isWhatsappMessageSent
                  ? "text-gray-400! opacity-60! cursor-not-allowed!"
                  : "text-green-500!"
              }
              icon={<WhatsAppOutlined />}
              onClick={() => handleWhatsapp(record.id)}
            />
          </Popover>
        </Space>
      ),
    },
  ];

  const handleSupplierChange = (val: string) => {
    if (!val) {
      setSelectedSupplierBalance(null);
      return;
    }
    const supp = suppliers.find((s) => s.id === val);
    if (supp) {
      setSelectedSupplierBalance(Number(supp.outstandingBalance));
    } else {
      setSelectedSupplierBalance(null);
    }
  };

  return (
    <div>
      <Spin spinning={loading}>
        <AppContainer
          title={`${ENTITY_LABEL}`}
          headerAction={
            <Space>
              <Button
                icon={<DownloadOutlined />}
                style={{ color: '#52c41a', borderColor: '#52c41a' }}
                onClick={handleExport}
              >
                Export Excel
              </Button>
              <Button
                icon={<DownloadOutlined />}
                style={{ color: '#f5222d', borderColor: '#f5222d' }}
                onClick={handleExportPdf}
                loading={exportPdfLoading}
              >
                Export PDF
              </Button>
              <Button
                type="primary"
                icon={<PlusOutlined />}
                onClick={handleAdd}
                className="bg-green-600"
              >
                Add Payment
              </Button>
            </Space>
          }
        >
          <div className="flex justify-between items-center mb-4 pb-4 border-b border-gray-200">
            <Space>
              <RangePicker value={dateRange as any} onChange={handleDateRangeChange} />
              <Input.Search
                placeholder="Search..."
                value={searchText}
                onChange={(e) => setSearchText(e.target.value)}
                onSearch={handleSearch}
                allowClear
                style={{ width: 200 }}
              />
            </Space>
          </div>

          <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, dateRange);
            }}
          />
          <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);
            setInitialEditAmount(0);
            setSelectedSupplierBalance(null);
          }}
          footer={[
            <Button
              key="cancel"
              onClick={() => {
                setOpen(false);
                setEditingId(null);
                setInitialEditAmount(0);
                setSelectedSupplierBalance(null);
              }}
            >
              Cancel
            </Button>,
            <Button
              key="submit"
              type="primary"
              onClick={() => form.submit()}
              loading={loading}
              className="bg-green-600"
            >
              {editingId ? 'Update' : 'Save'}
            </Button>,
          ]}
          width={600}
        >
          <Form form={form} layout="vertical" onFinish={handleSubmit}>
            <Row gutter={16}>
              <Col xs={24} sm={12}>
                <Form.Item
                  label="Payment Date"
                  name="paymentDate"
                  rules={[{ required: true, message: 'Please select date' }]}
                  initialValue={dayjs()}
                >
                  <DatePicker style={{ width: '100%' }} />
                </Form.Item>
              </Col>
              <Col xs={24} sm={12}>
                <Form.Item
                  label="Supplier"
                  name="supplierId"
                  rules={[{ required: true, message: 'Please select a supplier' }]}
                >
                  <Select
                    showSearch
                    placeholder="Select a supplier"
                    optionFilterProp="children"
                    onChange={handleSupplierChange}
                    disabled={!!editingId}
                    loading={metaLoading}
                  >
                    {suppliers.map((s) => (
                      <Select.Option key={s.id} value={s.id}>
                        {s.name}
                      </Select.Option>
                    ))}
                  </Select>
                </Form.Item>
              </Col>

              {selectedSupplierBalance !== null && (
                <Col xs={24} sm={24}>
                  <div style={{ marginBottom: 16, marginTop: -8, fontSize: 12, color: 'gray' }}>
                    Outstanding Balance: <strong style={{ color: selectedSupplierBalance > 0 ? '#cf1322' : '#52c41a' }}>₹{selectedSupplierBalance.toFixed(2)}</strong>
                  </div>
                </Col>
              )}

              <Col xs={24} sm={12}>
                <Form.Item
                  label="Amount"
                  name="amount"
                  rules={[
                    { required: true, message: 'Please enter amount' },
                    {
                      validator: (_, value) => {
                        if (value && selectedSupplierBalance !== null) {
                          const maxAllowed = editingId
                            ? selectedSupplierBalance + initialEditAmount
                            : selectedSupplierBalance;

                          if (value > maxAllowed) {
                            return Promise.reject(
                              new Error(`Amount cannot exceed outstanding balance (₹${maxAllowed.toFixed(2)})`)
                            );
                          }
                        }
                        return Promise.resolve();
                      },
                    },
                  ]}
                >
                  <InputNumber
                    // disabled={!!editingId}
                    style={{ width: '100%' }}
                    min={0.01}
                    step={0.01}
                    placeholder="0.00"
                  />
                </Form.Item>
              </Col>
              <Col xs={24} sm={12}>
                <Form.Item
                  label="Payment Mode"
                  name="paymentMode"
                  rules={[{ required: true, message: 'Please select payment mode' }]}
                >
                  <Select
                    placeholder="Select payment mode"
                    options={paymentModes}
                  />
                </Form.Item>
              </Col>

              <Col xs={24} sm={24}>
                <Form.Item label="Reference No" name="referenceNo">
                  <Input placeholder="e.g. Transaction ID, Cheque No" />
                </Form.Item>
              </Col>

              <Col xs={24} sm={24}>
                <Form.Item label="Remarks" name="remarks">
                  <Input.TextArea rows={2} />
                </Form.Item>
              </Col>
            </Row>
          </Form>
        </Modal>

        {/* View Modal */}
        <Modal
          title={`${ENTITY_LABEL} Details`}
          open={viewOpen}
          onCancel={() => {
            setViewOpen(false);
            setViewRecord(null);
          }}
          footer={
            <Button onClick={() => { setViewOpen(false); setViewRecord(null); }}>
              Close
            </Button>
          }
          width={600}
        >
          <Spin spinning={viewLoading}>
            {viewRecord && (
              <Descriptions column={2} bordered size="small">
                <Descriptions.Item label="Payment Date">
                  {viewRecord.paymentDate ? dayjs(viewRecord.paymentDate).format('DD MMM YYYY') : '-'}
                </Descriptions.Item>
                <Descriptions.Item label="Supplier">
                  {viewRecord.supplier?.name || '-'}
                </Descriptions.Item>
                <Descriptions.Item label="Amount">
                  ₹{Number(viewRecord.amount ?? 0).toFixed(2)}
                </Descriptions.Item>
                <Descriptions.Item label="Payment Mode">
                  <Tag color={paymentModeColor(viewRecord.paymentMode)}>
                    {viewRecord.paymentMode || '-'}
                  </Tag>
                </Descriptions.Item>
                <Descriptions.Item label="Reference No" span={2}>
                  {viewRecord.referenceNo || '-'}
                </Descriptions.Item>
                <Descriptions.Item label="Remarks" span={2}>
                  {viewRecord.remarks || '-'}
                </Descriptions.Item>
                <Descriptions.Item label="Created At" span={2}>
                  {viewRecord.createdAt ? dayjs(viewRecord.createdAt).format('DD MMM YYYY, hh:mm A') : '-'}
                </Descriptions.Item>
              </Descriptions>
            )}
          </Spin>
        </Modal>
      </Spin>
    </div>
  );
};

export default SupplierPayments;
