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,
    EditOutlined,
    DeleteOutlined,
} from '@ant-design/icons';
import dayjs, { Dayjs } from 'dayjs';
import { AppContainer } from '../../components/AppContainer';
import jwtAxios from '../../api/axiosInstance';
import { ENDPOINTS } from '../../api/endpoints';
import SummaryCard from '../../components/SummaryCard';

const ENTITY_LABEL = 'Expense';
const ENTITY_ENDPOINT = ENDPOINTS.EXPENSES;
const ENTITY_EXPORT = ENDPOINTS.EXPENSES_EXPORT;

interface DataRecord {
    key: string;
    id: string;
    category: string;
    amount: string;
    paymentMode: string;
    expenseDate: string;
    remarks: string;
    createdAt?: string;
    updatedAt?: string;
}

const Expenses = () => {
    const [form] = Form.useForm();
    const [open, setOpen] = useState(false);
    const [editingId, setEditingId] = useState<string | null>(null);
    const [searchText, setSearchText] = useState('');
    const [filterDate, setFilterDate] = useState<[Dayjs, Dayjs] | null>(null);
    const [data, setData] = useState<DataRecord[]>([]);
    const [loading, setLoading] = useState<boolean>(false);
    const [exportLoading, setExportLoading] = useState<boolean>(false);
    const [paymentModes, setPaymentModes] = useState<{ label: string; value: string }[]>([]);

    const [viewOpen, setViewOpen] = useState(false);
    const [viewLoading, setViewLoading] = useState(false);
    const [viewRecord, setViewRecord] = useState<any>(null);
    const [totalExpenses, setTotalExpenses] = useState<number>(0);
    const [totalRecords, setTotalRecords] = useState<number>(0);

    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;
        }
        setExportLoading(true);
        try {
            const params = new URLSearchParams();
            if (searchText) {
                params.append('search', searchText);
            }
            if (filterDate && filterDate.length === 2 && filterDate[0] && filterDate[1]) {
                params.append('startDate', filterDate[0].format('YYYY-MM-DD'));
                params.append('endDate', filterDate[1].format('YYYY-MM-DD'));
            }

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

            const disposition = response.headers['content-disposition'];

            let fileName = 'expenses.pdf';

            if (disposition) {
                const match = disposition.match(/filename="?([^"]+)"?/);

                if (match) {
                    fileName = match[1];
                }
            }

            const url = window.URL.createObjectURL(response.data);

            const link = document.createElement('a');
            link.href = url;
            link.download = fileName;

            document.body.appendChild(link);
            link.click();
            link.remove();

            window.URL.revokeObjectURL(url);

            message.success('Expenses exported successfully');
        } catch (err: any) {
            message.error(err.response?.data?.message || 'Failed to export expenses');
        } finally {
            setExportLoading(false);
        }
    };

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

    const handleView = async (id: string) => {
        setViewLoading(true);
        setViewOpen(true);
        try {
            const res = await jwtAxios.get(`${ENTITY_ENDPOINT}/${id}`);
            const record = res.data?.data ?? 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 res = await jwtAxios.get(`${ENTITY_ENDPOINT}/${id}`);
            const record = res.data?.data ?? res.data?.result ?? res.data;

            form.setFieldsValue({
                category: record.category,
                amount: Number(record.amount) || 0,
                paymentMode: record.paymentMode,
                expenseDate: record.expenseDate ? dayjs(record.expenseDate) : undefined,
                remarks: record.remarks ?? undefined,
            });

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

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

            const res = await jwtAxios.get(url);
            const records = res.data?.result?.data || [];
            const totalAmount = res.data?.result?.amountSum || 0;
            const totalCount = res.data?.result?.meta?.total || 0;

            setTotalExpenses(totalAmount);
            setTotalRecords(totalCount);
            const metaInfo = res.data?.result?.meta || {};

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

            // message.success(res?.data?.message || 'Expenses fetched successfully');

            setData(formattedData);
            setPagination((prev) => ({
                ...prev,
                current: metaInfo.page || page,
                pageSize: metaInfo.limit || pageSize,
                total: metaInfo.total || 0,
                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(() => {
        fetchData(1, pagination.pageSize, '');
        fetchPaymentModes();
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

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

    const handleDateChange = (dates: any) => {
        setFilterDate(dates);
        fetchData(1, pagination.pageSize, searchText, dates);
    };

    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, filterDate);
        } 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 = {
                category: values.category,
                amount: values.amount,
                paymentMode: values.paymentMode,
                expenseDate: values.expenseDate?.format('YYYY-MM-DD'),
                remarks: values.remarks ?? undefined,
            };

            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, filterDate);
        } 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 paymentModeColor = (mode: string) => {
        switch (mode) {
            case 'CASH': return 'green';
            case 'BANK': return 'blue';
            case 'UPI': return 'purple';
            default: return 'default';
        }
    };

    const columns = [
        {
            title: 'Expense Date',
            dataIndex: 'expenseDate',
            render: (date: string) => (date ? dayjs(date).format('DD MMM YYYY') : '-'),
        },
        {
            title: 'Category',
            dataIndex: 'category',
            render: (category: string) => category || '-',
        },
        {
            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: '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 expense?"
                        okText="Delete"
                        cancelText="Cancel"
                        okButtonProps={{ danger: true }}
                        onConfirm={() => handleDelete(record.id)}
                    >
                        <Button danger type="link" icon={<DeleteOutlined />} />
                    </Popconfirm>
                </Space>
            ),
        },
    ];

    return (
        <div>
            <Spin spinning={loading}>
                <AppContainer
                    title={`${ENTITY_LABEL}`}
                    headerAction={
                        <Space>
                            <Button
                                icon={<DownloadOutlined />}
                                loading={exportLoading}
                                style={{ color: '#52c41a', borderColor: '#52c41a' }}
                                onClick={handleExport}
                            >
                                Export
                            </Button>
                            <Button
                                type="primary"
                                icon={<PlusOutlined />}
                                onClick={handleAdd}
                                className="bg-green-600"
                            >
                                Add Expense
                            </Button>
                        </Space>
                    }
                >
                    {/* Summary Cards */}
                    <Row gutter={[16, 16]} style={{ marginBottom: 20 }}>
                        <Col xs={24} md={12}>
                            <SummaryCard
                                label="Total Expenses"
                                value={totalExpenses}
                                color="#f5222d"

                                icon={<span style={{ fontSize: 20 }}>📈</span>}
                            />
                        </Col>
                        <Col xs={24} md={12}>
                            <SummaryCard
                                label="No. of Records"
                                value={totalRecords}
                                color="#1677ff"
                                showCurrency={false}
                                icon={<span style={{ fontSize: 20 }}>💰</span>}
                            />
                        </Col>
                    </Row>

                    {/* Search boxes and Table */}
                    <div className="flex justify-between items-center mb-4 pb-4 border-b border-gray-200">
                        <Space>
                            <DatePicker.RangePicker
                                value={filterDate}
                                onChange={handleDateChange}
                                placeholder={['Start Date', 'End Date']}
                                allowClear
                            />
                            <Input.Search
                                placeholder="Search category, remarks, amount..."
                                value={searchText}
                                onChange={(e) => setSearchText(e.target.value)}
                                onSearch={handleSearch}
                                allowClear
                                style={{ width: 260 }}
                            />
                        </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, filterDate);
                        }}
                    />
                    <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"
                    width={600}
                >
                    <Form form={form} layout="vertical" onFinish={handleSubmit}>
                        <Row gutter={16}>
                            <Col xs={24} sm={12}>
                                <Form.Item
                                    label="Expense Date"
                                    name="expenseDate"
                                    rules={[
                                        { required: true, message: 'Please select expense date' },
                                        {
                                            validator: (_, value) => {
                                                if (value && value.isAfter(dayjs(), 'day')) {
                                                    return Promise.reject(new Error('Future date is not allowed for expense date'));
                                                }
                                                return Promise.resolve();
                                            },
                                        },
                                    ]}
                                >
                                    <DatePicker
                                        style={{ width: '100%' }}
                                        disabledDate={(current) => current && current > dayjs().endOf('day')}
                                    />
                                </Form.Item>
                            </Col>
                            <Col xs={24} sm={12}>
                                <Form.Item
                                    label="Category"
                                    name="category"
                                    rules={[{ required: true, message: 'Category cannot be empty' }]}
                                >
                                    <Input placeholder="e.g. Tea, Fuel, Stationery" />
                                </Form.Item>
                            </Col>

                            <Col xs={24} sm={12}>
                                <Form.Item
                                    label="Amount"
                                    name="amount"
                                    rules={[{ required: true, message: 'Amount must be greater than or equal to 0' }]}
                                >
                                    <InputNumber style={{ width: '100%' }} min={0} step={0.01} />
                                </Form.Item>
                            </Col>
                            <Col xs={24} sm={12}>
                                <Form.Item
                                    label="Payment Mode"
                                    name="paymentMode"
                                    rules={[{ required: true, message: 'Please select a payment mode' }]}
                                >
                                    <Select placeholder="Select payment mode" options={paymentModes} />
                                </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="Expense Date">
                                    {viewRecord.expenseDate ? dayjs(viewRecord.expenseDate).format('DD MMM YYYY') : '-'}
                                </Descriptions.Item>
                                <Descriptions.Item label="Category">
                                    {viewRecord.category || '-'}
                                </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="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 Expenses;