import { useEffect, useState } from 'react';
import {
    DatePicker,
    Input,
    Select,
    Space,
    Spin,
    Table,
    message,
    Tag,
    Button,
    Row,
    Col,
} from 'antd';

import { RedoOutlined, DownloadOutlined, FilePdfOutlined } 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 = 'Purchase Reports';
const ENTITY_ENDPOINT = ENDPOINTS.PURCHASE_REPORT; // e.g. '/api/purchases'

interface NamedOption {
    id: string;
    name: string;
}

interface DataRecord {
    key: string;
    id: string;
    purchaseDate: string;
    billNo: string;
    lotNo: string;
    unit: string;
    bags?: string;
    weightPerBag?: string | null;
    quantity: string;
    ratePerUnit: string;
    grandTotal: string;
    costPerUnit: string;
    advanceAmount: string;
    balanceAmount: string;
    remainingQuantity?: string;
    remainingBags?: string;
    supplierId: string;
    vegetableId: string;
    supplier?: { name: string };
    vegetable?: { name: string };
}

const { RangePicker } = DatePicker;

const PurchaseReport = () => {
    const [searchText, setSearchText] = useState('');
    const [dateRange, setDateRange] = useState<[Dayjs, Dayjs] | null>(null);
    // undefined = "All" (no supplierId/vegetableId param sent to backend)
    const [supplierId, setSupplierId] = useState<string | undefined>(undefined);
    const [vegetableId, setVegetableId] = useState<string | undefined>(undefined);

    const [data, setData] = useState<DataRecord[]>([]);
    const [loading, setLoading] = useState<boolean>(false);
    const [exportLoading, setExportLoading] = useState<boolean>(false);
    const [exportPdfLoading, setExportPdfLoading] = useState<boolean>(false);
    const [sum, setSum] = useState({ grand_total: 0, balance_amount: 0, outstanding_balance: 0 });

    const [suppliers, setSuppliers] = useState<NamedOption[]>([]);
    const [vegetables, setVegetables] = useState<NamedOption[]>([]);

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

    const unitColors: Record<string, string> = {
        KG: 'purple',
        BOX: 'blue',
        BAG: 'yellow',
    };

    // -----------------------------
    // Fetch meta (units + suppliers + vegetables) — ONLY ONCE on mount.
    // -----------------------------
    const fetchMeta = async () => {
        try {
            const res = await jwtAxios.get(ENDPOINTS.PURCHASE_META);
            const result = res.data?.result || {
                purchaseUnits: [],
                suppliers: [],
                vegetables: [],
            };

            setSuppliers(result.suppliers || []);
            setVegetables(result.vegetables || []);
        } catch (err: any) {
            message.error(err.response?.data?.message || 'Failed to fetch purchase meta');
            setSuppliers([]);
            setVegetables([]);
        }
    };

    // -----------------------------
    // Fetch list — runs on initial load, page change, page-size change,
    // and whenever a search or filter is triggered.
    // -----------------------------
    const fetchData = async (
        page: number = pagination.current,
        limit: number = pagination.pageSize,
        search: string = searchText,
        range: [Dayjs, Dayjs] | null = dateRange,
        supplier: string | null | undefined = supplierId,
        vegetable: string | null | undefined = vegetableId
    ) => {
        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')}`;
            }
            if (supplier) {
                url += `&supplierId=${supplier}`;
            }
            if (vegetable) {
                url += `&vegetableId=${vegetable}`;
            }

            const res = await jwtAxios.get(url);

            // Response shape: { message, result: { data: [...], meta: { total, page, limit, totalPages }, sum: {...} } }
            const records = res.data?.result?.data || [];
            const metaInfo = res.data?.result?.meta || {};
            const sumInfo = res.data?.result?.sum || {};

            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,
            }));
            setSum({
                grand_total: Number(sumInfo.grand_total ?? 0),
                balance_amount: Number(sumInfo.balance_amount ?? 0),
                outstanding_balance: Number(sumInfo.outstanding_balance ?? 0),
            });
        } catch (err: any) {
            message.error(err.response?.data?.message || 'Failed to fetch data');
            setData([]);
        } finally {
            setLoading(false);
        }
    };

    // Initial load: meta, suppliers, vegetables and first page of records.
    useEffect(() => {
        fetchMeta();
        fetchData(1, pagination.pageSize, '', null, undefined, undefined);
    }, []);

    const handleExport = async () => {
        if (!data || data.length === 0) {
            message.warning('No data available to export');
            return;
        }
        setExportLoading(true);
        try {
            // Build query string with all currently-active filters (no page/limit)
            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'));
            }
            if (supplierId) params.set('supplierId', supplierId);
            if (vegetableId) params.set('vegetableId', vegetableId);

            const url = `${ENDPOINTS.PURCHASE_EXPORT}${params.toString() ? '?' + params.toString() : ''}`;

            const response = await jwtAxios.get(url, { responseType: 'blob' });

            // Resolve filename from Content-Disposition header
            const disposition = response.headers['content-disposition'];
            let fileName = 'purchase-report.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('Purchase report exported successfully');
        } catch {
            message.error('Failed to export purchase report. Please try again.');
        } finally {
            setExportLoading(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'));
            }
            if (supplierId) params.set('supplierId', supplierId);
            if (vegetableId) params.set('vegetableId', vegetableId);

            const url = `${ENDPOINTS.PURCHASE_EXPORT_PDF}${params.toString() ? '?' + params.toString() : ''}`;

            const response = await jwtAxios.get(url, { responseType: 'blob' });

            const disposition = response.headers['content-disposition'];
            let fileName = `purchase-report-${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('Purchase report PDF exported successfully');
        } catch {
            message.error('Failed to export purchase report PDF. Please try again.');
        } finally {
            setExportPdfLoading(false);
        }
    };
    // -----------------------------
    // Search — onChange just updates the input text; onSearch (Enter / icon)
    // actually triggers the API call and resets to page 1.
    // -----------------------------
    const handleSearch = (value: string) => {
        fetchData(1, pagination.pageSize, value, dateRange, supplierId, vegetableId);
    };

    const handleReset = () => {
        setSearchText('');
        setDateRange(null);
        setSupplierId(undefined);
        setVegetableId(undefined);
        fetchData(1, pagination.pageSize, '', null, null, null);
    };

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

    // Supplier filter.
    const handleSupplierChange = (value: string | undefined) => {
        setSupplierId(value);
        fetchData(1, pagination.pageSize, searchText, dateRange, value ?? null, vegetableId);
    };

    // Vegetable filter.
    const handleVegetableChange = (value: string | undefined) => {
        setVegetableId(value);
        fetchData(1, pagination.pageSize, searchText, dateRange, supplierId, value ?? null);
    };


    const columns = [
        {
            title: 'S.No',
            dataIndex: 'sNo',
            render: (_: number, __: DataRecord, index: number) => index + 1,
        },
        {
            title: 'Lot No',
            dataIndex: 'lotNo',
        },
        {
            title: 'Supplier',
            dataIndex: 'supplier',
            render: (supplier: DataRecord['supplier'], record: any) =>
                supplier ? supplier.name : (record.cashSupplierName || record.supplierName || 'Cash Supplier'),
        },
        {
            title: 'Vegetable',
            dataIndex: 'vegetable',
            render: (vegetable: DataRecord['vegetable']) => (vegetable ? vegetable.name : '-'),
        },
        {
            title: 'Quantity',
            dataIndex: 'quantity',
            ellipsis: true,
            render: (quantity: string, record: DataRecord) => (
                <div className="flex items-center gap-2">
                    <Tag color="purple">{Number(quantity)} KG</Tag>
                    {record.weightPerBag ? (
                        <Tag color={unitColors[record.unit] || 'default'}>
                            {Number(record.bags ?? 0)} {record.unit}
                        </Tag>
                    ) : null}
                </div>
            ),
        },
        {
            title: "Bags",
            dataIndex: "bags",
            render: (bags: number | string | null, record: DataRecord) => {
                const value = Number(bags);

                return value > 0 ? (
                    <Tag color="blue">
                        {value} {record.unit}
                    </Tag>
                ) : (
                    <Tag color="red">-</Tag>
                );
            },
        },
        {
            title: "Remaining Stock",
            dataIndex: "remainingQuantity",
            render: (remainingQuantity: string, record: DataRecord) => {
                const remaining = Number(remainingQuantity);
                const total = Number(record.quantity);

                let color = "green";

                if (remaining === 0) {
                    color = "red";
                } else if (remaining <= total * 0.2) {
                    color = "orange";
                }

                return (
                    <div className="flex items-center gap-2">
                        <span className="font-medium">
                            <Tag color={color}>
                                {remaining} / {total} KG
                                {record.weightPerBag
                                    ? ` (${Number(record.remainingBags ?? 0)} / ${Number(record.bags ?? 0)} ${record.unit})`
                                    : ''}
                            </Tag>
                        </span>
                    </div>
                );
            },
        },
        {
            title: 'Rate/Input Unit',
            dataIndex: 'ratePerUnit',
            render: (rate: string) => Number(rate).toFixed(2),
        },
        {
            title: 'Grand Total',
            dataIndex: 'grandTotal',
            render: (total: string) => <Tag color="cyan">₹{Number(total).toFixed(2)}</Tag>,
        },
        {
            title: 'Cost/Kg',
            dataIndex: 'costPerUnit',
            render: (cost: string) => <Tag color="magenta">₹{Number(cost).toFixed(2)}</Tag>,
        },
        {
            title: 'Advance',
            dataIndex: 'advanceAmount',
            render: (amount: string) => Number(amount).toFixed(2),
        },
        {
            title: 'Balance',
            dataIndex: 'balanceAmount',
            render: (amount: string) => Number(amount).toFixed(2),
        },
    ];

    return (
        <div>
            <Spin spinning={loading}>
                <AppContainer title={`${ENTITY_LABEL}`}
                    headerAction={
                        <Space wrap>
                            <Button
                                icon={<DownloadOutlined />}
                                style={{ color: '#52c41a', borderColor: '#52c41a' }}
                                loading={exportLoading}
                                onClick={handleExport}
                            >
                                Export Excel
                            </Button>
                            <Button
                                icon={<FilePdfOutlined />}
                                danger
                                loading={exportPdfLoading}
                                onClick={handleExportPdf}
                            >
                                Export PDF
                            </Button>
                        </Space>
                    }
                >
                    {/* Summary Cards */}
                    <Row gutter={[16, 16]} style={{ marginBottom: 20 }}>
                        <Col xs={24} sm={12} md={8}>
                            <SummaryCard
                                label="Grand Total"
                                value={sum.grand_total}
                                color="#1677ff"
                                icon={<span style={{ fontSize: 20 }}>📈</span>}
                            />
                        </Col>
                        <Col xs={24} sm={12} md={8}>
                            <SummaryCard
                                label="Purchase Balance"
                                value={sum.balance_amount}
                                color="#f522ab"
                                icon={<span style={{ fontSize: 20 }}>💰</span>}
                            />
                        </Col>
                        <Col xs={24} sm={12} md={8}>
                            <SummaryCard
                                label="Outstanding Balance"
                                value={sum.outstanding_balance}
                                color="#f5222d"
                                icon={<span style={{ fontSize: 20 }}>💰</span>}
                            />
                        </Col>
                    </Row>
                    {/* Toolbar Section */}
                    <div className="flex justify-between items-center mb-4 pb-4 border-b border-gray-200">
                        <Space wrap>
                            <RangePicker value={dateRange as any} onChange={handleDateRangeChange} />
                            <Select
                                allowClear
                                showSearch
                                placeholder="Filter by supplier"
                                style={{ width: 200 }}
                                value={supplierId}
                                onChange={handleSupplierChange}
                                optionFilterProp="label"
                                filterOption={(input, option) =>
                                    (option?.label ?? '').toLowerCase().includes(input.toLowerCase())
                                }
                                options={suppliers.map((s) => ({ label: s.name, value: s.id }))}
                            />
                            <Select
                                allowClear
                                showSearch
                                placeholder="Filter by vegetable"
                                style={{ width: 200 }}
                                value={vegetableId}
                                onChange={handleVegetableChange}
                                optionFilterProp="label"
                                filterOption={(input, option) =>
                                    (option?.label ?? '').toLowerCase().includes(input.toLowerCase())
                                }
                                options={vegetables.map((v) => ({ label: v.name, value: v.id }))}
                            />
                            <Input.Search
                                placeholder="Search..."
                                value={searchText}
                                onChange={(e) => {
                                    const val = e.target.value;
                                    setSearchText(val);
                                    if (!val) {
                                        handleSearch('');
                                    }
                                }}
                                onSearch={handleSearch}
                                allowClear
                                style={{ width: 200 }}
                            />
                            <Button
                                icon={<RedoOutlined />}
                                onClick={handleReset}
                            >
                                Reset
                            </Button>
                        </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, dateRange, supplierId, vegetableId);
                        }}
                    />
                    <div className="text-center mt-2">
                        <Tag color="cyan">
                            Page {pagination.current} of {pagination.totalPages}
                        </Tag>
                    </div>
                </AppContainer>
            </Spin>
        </div>
    );
};

export default PurchaseReport;