import { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from 'react';
import Link from 'next/link';
import { flexRender } from '@tanstack/react-table';
import type { SortingState } from '@tanstack/table-core';
import { getCoreRowModel, useLegacyTable, type LegacyColumnDef } from '@tanstack/react-table/legacy';

import type { DateRange } from '@/lib/abandoned-cart-stats-date';
import type { AcquisitionActiveFilters } from './AcquisitionTable';
import StatsCompareBadge from '@/components/AbandonedCart/StatsCompareBadge';
import CompareTrendArrow from '@/components/AbandonedCart/CompareTrendArrow';
import styles from './purchase-orders-table.module.css';

export type PurchaseOrderProduct = {
    name: string;
    sku: string;
    qty: number;
    url: string;
    is_free_item?: boolean;
};

export type PurchaseOrderRow = {
    id: string;
    order_id: string;
    order_status: string;
    order_date?: string | null;
    payment_date?: string | null;
    checkout_to_pay_ms?: number | null;
    revenue: number;
    item_qty: number;
    sku_count: number;
    products: PurchaseOrderProduct[];
    product_name?: string;
    product_sku?: string;
    product_url?: string;
    qty?: number;
};

export type PurchaseOrdersSummary = {
    total_revenue: number;
    total_transactions: number;
    total_items: number;
    aov: number;
    avg_checkout_to_pay_ms: number | null;
    avg_checkout_to_pay_sample: number;
};

type Grain = 'order' | 'item';
type StatusFilter = 'all' | 'Processing' | 'InDelivery' | 'Completed';
type SortKey = 'order_date' | 'revenue' | 'item_qty';

const DEFAULT_PAGE_SIZE = 25;
const PAGE_SIZE_OPTIONS = [10, 25, 50, 100];
const DEFAULT_SORTING: SortingState = [{ id: 'order_date', desc: true }];

function formatRp(value: number) {
    return `Rp ${Math.round(Number(value) || 0).toLocaleString('id-ID')}`;
}

function formatDateTime(value?: string | null) {
    if (!value) return '—';
    const date = new Date(value);
    if (Number.isNaN(date.getTime())) return '—';
    return date.toLocaleString('id-ID', {
        day: '2-digit',
        month: 'short',
        year: 'numeric',
        hour: '2-digit',
        minute: '2-digit',
    });
}

function SummaryCard({
    label,
    value,
    note,
    compareEnabled = false,
    current,
    previous = null,
}: {
    label: ReactNode;
    value: string | number;
    note?: string;
    compareEnabled?: boolean;
    current?: number | null;
    previous?: number | null;
}) {
    return (
        <div className="rounded border border-gray-100 shadow-md bg-white p-3 text-[#0e1726] dark:border-[#334155] dark:bg-[#0e1726] dark:text-white">
            <p className="text-xs text-gray-500 mb-2 dark:text-slate-400">{label}</p>
            <div className="text-3xl font-bold flex items-center mb-2">
                {value}
                {compareEnabled && current != null && previous != null ? (
                    <CompareTrendArrow current={current} previous={previous} />
                ) : null}
            </div>
            {note ? <p className="text-xs text-gray-700 mt-1 dark:text-slate-500">{note}</p> : null}
            {compareEnabled && current != null && previous != null ? (
                <StatsCompareBadge current={current} previous={previous} compareEnabled />
            ) : null}
        </div>
    );
}

function productHref(url?: string) {
    const raw = String(url || '').trim();
    if (!raw) return '';
    if (raw.startsWith('http://') || raw.startsWith('https://')) return raw;
    const slug = raw.replace(/^\/+/, '').replace(/^product\//, '');
    return `https://theaurumlab.com/product/${slug}`;
}

function ProductsCell({ products }: { products: PurchaseOrderProduct[] }) {
    const [open, setOpen] = useState(false);
    const wrapRef = useRef<HTMLDivElement | null>(null);

    useEffect(() => {
        if (!open) return;
        const onDoc = (event: MouseEvent) => {
            if (!wrapRef.current?.contains(event.target as Node)) setOpen(false);
        };
        document.addEventListener('mousedown', onDoc);
        return () => document.removeEventListener('mousedown', onDoc);
    }, [open]);

    if (!products.length) return <span className="text-xs text-gray-400">—</span>;
    if (products.length === 1) {
        const item = products[0];
        const href = productHref(item.url);
        const label = `${item.name}${item.qty > 1 ? ` ×${item.qty}` : ''}`;
        return href ? (
            <a href={href} target="_blank" rel="noreferrer" className={`${styles.productOne} text-primary underline`}>
                {label}
            </a>
        ) : (
            <span className={styles.productOne}>{label}</span>
        );
    }

    return (
        <div className={styles.productsCell} ref={wrapRef}>
            <button type="button" className={styles.productToggle} onClick={() => setOpen((prev) => !prev)}>
                {products.length} produk {open ? '▴' : '▾'}
            </button>
            {open ? (
                <div className={styles.productMenu}>
                    {products.map((item, index) => {
                        const href = productHref(item.url);
                        return (
                            <div key={`${item.sku || item.name}-${index}`} className={styles.productMenuItem}>
                                {href ? (
                                    <a href={href} target="_blank" rel="noreferrer" className="text-primary underline">
                                        {item.name}
                                    </a>
                                ) : (
                                    <span>{item.name}</span>
                                )}
                                <span className="text-[11px] text-gray-500">
                                    {item.qty} pcs{item.sku ? ` · ${item.sku}` : ''}
                                    {item.is_free_item ? ' · free' : ''}
                                </span>
                            </div>
                        );
                    })}
                </div>
            ) : null}
        </div>
    );
}

function OrderCell({ order_id, order_status }: { order_id: string; order_status: string }) {
    return (
        <div>
            <Link href={`/orders/edit/${order_id}`} className="text-primary underline">
                #{order_id}
            </Link>
            <div className="text-[11px] text-gray-500">{order_status || '—'}</div>
        </div>
    );
}

function sortKeyFromSorting(sorting: SortingState): SortKey {
    const id = sorting[0]?.id;
    if (id === 'revenue' || id === 'item_qty') return id;
    return 'order_date';
}

function thClass(columnId: string, sortable: boolean) {
    const parts = [styles.th];
    if (sortable) parts.push(styles.thSortable);
    if (columnId === 'order_id') parts.push(styles.thFrozen);
    if (columnId === 'revenue' || columnId === 'item_qty' || columnId === 'qty') parts.push(styles.thMetric);
    if (columnId === 'order_date') parts.push(styles.thDate);
    return parts.join(' ');
}

function tdClass(columnId: string) {
    const parts = [styles.td];
    if (columnId === 'order_id') parts.push(styles.tdFrozen);
    if (columnId === 'revenue' || columnId === 'item_qty' || columnId === 'qty') parts.push(styles.tdMetric);
    if (columnId === 'order_date') parts.push(styles.tdDate);
    if (columnId === 'products' || columnId === 'product_name') parts.push(styles.tdProduct);
    return parts.join(' ');
}

type Props = {
    dateRange: DateRange;
    compareEnabled?: boolean;
    compareRange?: DateRange | null;
    acquisitionFilters?: AcquisitionActiveFilters;
};

const PurchaseOrdersTable = ({
    dateRange,
    compareEnabled = false,
    compareRange = null,
    acquisitionFilters,
}: Props) => {
    const [grain, setGrain] = useState<Grain>('order');
    const [status, setStatus] = useState<StatusFilter>('all');
    const [searchInput, setSearchInput] = useState('');
    const [searchQ, setSearchQ] = useState('');
    const [sorting, setSorting] = useState<SortingState>(DEFAULT_SORTING);
    const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: DEFAULT_PAGE_SIZE });
    const [rows, setRows] = useState<PurchaseOrderRow[]>([]);
    const [total, setTotal] = useState(0);
    const [summary, setSummary] = useState<PurchaseOrdersSummary | null>(null);
    const [compareSummary, setCompareSummary] = useState<PurchaseOrdersSummary | null>(null);
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState('');
    const fetchSeq = useRef(0);

    const sort = sortKeyFromSorting(sorting);
    const sortDir = sorting[0]?.desc === false ? 'asc' : 'desc';
    const page = pagination.pageIndex + 1;

    useEffect(() => {
        const timer = window.setTimeout(() => {
            const next = searchInput.trim();
            setSearchQ((prev) => {
                if (prev !== next) {
                    setPagination((p) => ({ ...p, pageIndex: 0 }));
                }
                return next;
            });
        }, 350);
        return () => window.clearTimeout(timer);
    }, [searchInput]);

    const buildParams = useCallback(
        (range: DateRange, extra: Record<string, string> = {}) => {
            const params = new URLSearchParams({
                date_from: range.from,
                date_to: range.to,
                exclude_bots: '1',
                grain,
                status,
                page: String(page),
                per_page: String(pagination.pageSize),
                sort,
                sort_dir: sortDir,
                ...extra,
            });
            if (searchQ) params.set('q', searchQ);
            if (acquisitionFilters?.channel_group) params.set('channel_group', acquisitionFilters.channel_group);
            if (acquisitionFilters?.utm_source) params.set('utm_source', acquisitionFilters.utm_source);
            if (acquisitionFilters?.utm_campaign) params.set('utm_campaign', acquisitionFilters.utm_campaign);
            return params;
        },
        [acquisitionFilters, grain, page, pagination.pageSize, searchQ, sort, sortDir, status]
    );

    useEffect(() => {
        const fetchId = ++fetchSeq.current;
        const load = async () => {
            setLoading(true);
            setError('');
            try {
                const api_url = process.env.API_URL;
                const res = await fetch(`${api_url}api/journey/purchase-orders?${buildParams(dateRange)}`, {
                    credentials: 'include',
                });
                const json = await res.json();
                if (fetchId !== fetchSeq.current) return;
                if (!res.ok) throw new Error(json?.message || 'Gagal memuat purchase orders');
                setRows(Array.isArray(json?.data) ? json.data : []);
                setTotal(Number(json?.pagination?.total) || 0);
                setSummary(json?.summary || null);

                if (compareEnabled && compareRange) {
                    const compareRes = await fetch(
                        `${api_url}api/journey/purchase-orders?${buildParams(compareRange, { page: '1' })}`,
                        { credentials: 'include' }
                    );
                    const compareJson = await compareRes.json();
                    if (fetchId !== fetchSeq.current) return;
                    setCompareSummary(compareRes.ok ? compareJson?.summary || null : null);
                } else {
                    setCompareSummary(null);
                }
            } catch (err: any) {
                if (fetchId !== fetchSeq.current) return;
                setError(err?.message || 'Gagal memuat purchase orders');
                setRows([]);
                setTotal(0);
                setSummary(null);
            } finally {
                if (fetchId === fetchSeq.current) setLoading(false);
            }
        };
        load();
    }, [buildParams, compareEnabled, compareRange, dateRange]);

    const exportCsv = async () => {
        try {
            const api_url = process.env.API_URL;
            const res = await fetch(`${api_url}api/journey/purchase-orders/export?${buildParams(dateRange, { page: '1' })}`, {
                credentials: 'include',
            });
            if (!res.ok) throw new Error('Gagal export CSV');
            const blob = await res.blob();
            const url = window.URL.createObjectURL(blob);
            const link = document.createElement('a');
            link.href = url;
            link.download = `purchase-orders-${dateRange.from}_${dateRange.to}.csv`;
            document.body.appendChild(link);
            link.click();
            link.remove();
            window.URL.revokeObjectURL(url);
        } catch {
            setError('Gagal export CSV');
        }
    };

    const resetPage = () => setPagination((prev) => ({ ...prev, pageIndex: 0 }));

    const columns = useMemo<LegacyColumnDef<PurchaseOrderRow>[]>(() => {
        const orderCol: LegacyColumnDef<PurchaseOrderRow> = {
            accessorKey: 'order_id',
            header: 'Order',
            enableSorting: false,
            cell: ({ row }) => <OrderCell order_id={row.original.order_id} order_status={row.original.order_status} />,
        };
        const revenueCol: LegacyColumnDef<PurchaseOrderRow> = {
            accessorKey: 'revenue',
            header: 'Revenue',
            enableSorting: true,
            cell: ({ getValue }) => formatRp(Number(getValue()) || 0),
        };
        const dateCol: LegacyColumnDef<PurchaseOrderRow> = {
            accessorKey: 'order_date',
            header: 'Order date',
            enableSorting: true,
            cell: ({ getValue }) => formatDateTime(getValue() as string | null),
        };

        if (grain === 'item') {
            return [
                orderCol,
                {
                    accessorKey: 'product_name',
                    header: 'Produk',
                    enableSorting: false,
                    cell: ({ row }) => {
                        const href = productHref(row.original.product_url);
                        return (
                            <div>
                                {href ? (
                                    <a href={href} target="_blank" rel="noreferrer" className="text-primary underline">
                                        {row.original.product_name || '—'}
                                    </a>
                                ) : (
                                    <span>{row.original.product_name || '—'}</span>
                                )}
                                {row.original.product_sku ? (
                                    <div className="text-[11px] text-gray-500">{row.original.product_sku}</div>
                                ) : null}
                            </div>
                        );
                    },
                },
                {
                    accessorKey: 'qty',
                    header: 'Qty',
                    enableSorting: false,
                    cell: ({ row }) => row.original.qty ?? 0,
                },
                revenueCol,
                dateCol,
            ];
        }

        return [
            orderCol,
            {
                accessorKey: 'products',
                header: 'Produk',
                enableSorting: false,
                cell: ({ row }) => <ProductsCell products={row.original.products || []} />,
            },
            {
                accessorKey: 'item_qty',
                header: 'Qty',
                enableSorting: true,
                cell: ({ getValue }) => Number(getValue()) || 0,
            },
            revenueCol,
            dateCol,
        ];
    }, [grain]);

    const pageCount = Math.max(Math.ceil(total / pagination.pageSize), 1);

    const table = useLegacyTable({
        data: rows,
        columns,
        pageCount,
        manualPagination: true,
        manualSorting: true,
        autoResetPageIndex: false,
        state: {
            sorting,
            pagination,
        },
        onSortingChange: (updater) => {
            setSorting((prev) => (typeof updater === 'function' ? updater(prev) : updater));
            resetPage();
        },
        onPaginationChange: (updater) => {
            setPagination((prev) => {
                const next = typeof updater === 'function' ? updater(prev) : updater;
                if (next.pageSize !== prev.pageSize) {
                    return { ...next, pageIndex: 0 };
                }
                return next;
            });
        },
        getCoreRowModel: getCoreRowModel(),
    });

    const prev = compareEnabled ? compareSummary : null;
    const from = total === 0 ? 0 : pagination.pageIndex * pagination.pageSize + 1;
    const to = Math.min((pagination.pageIndex + 1) * pagination.pageSize, total);

    return (
        <div className="space-y-4">
            <div className="grid grid-cols-2 xl:grid-cols-4 gap-3">
                <SummaryCard
                    label="Total purchase revenue"
                    value={formatRp(summary?.total_revenue || 0)}
                    note="Sub total order sukses"
                    compareEnabled={compareEnabled}
                    current={summary?.total_revenue || 0}
                    previous={prev ? prev.total_revenue : null}
                />
                <SummaryCard
                    label="Total transaksi"
                    value={(summary?.total_transactions || 0).toLocaleString('id-ID')}
                    compareEnabled={compareEnabled}
                    current={summary?.total_transactions || 0}
                    previous={prev ? prev.total_transactions : null}
                />
                <SummaryCard
                    label="Total barang keluar"
                    value={(summary?.total_items || 0).toLocaleString('id-ID')}
                    note="Qty dari order items"
                    compareEnabled={compareEnabled}
                    current={summary?.total_items || 0}
                    previous={prev ? prev.total_items : null}
                />
                <SummaryCard
                    label="AOV (Average Order Value)"
                    value={formatRp(summary?.aov || 0)}
                    compareEnabled={compareEnabled}
                    current={summary?.aov || 0}
                    previous={prev ? prev.aov : null}
                />
            </div>

            <div className={styles.toolbar}>
                <div className="flex flex-wrap items-center gap-2">
                    <select
                        className="form-select w-40"
                        value={grain}
                        onChange={(e) => {
                            const next = e.target.value as Grain;
                            setGrain(next);
                            if (next === 'item' && sort === 'item_qty') {
                                setSorting(DEFAULT_SORTING);
                            }
                            resetPage();
                        }}
                    >
                        <option value="order">Grain: Order</option>
                        <option value="item">Grain: Item</option>
                    </select>
                    <select
                        className="form-select w-40"
                        value={status}
                        onChange={(e) => {
                            setStatus(e.target.value as StatusFilter);
                            resetPage();
                        }}
                    >
                        <option value="all">Semua Status</option>
                        <option value="Processing">Processing</option>
                        <option value="InDelivery">InDelivery</option>
                        <option value="Completed">Completed</option>
                    </select>
                    <input
                        className="form-input w-56"
                        placeholder="Cari order_id / produk"
                        value={searchInput}
                        onChange={(e) => setSearchInput(e.target.value)}
                    />
                </div>
                <button type="button" className="btn btn-sm btn-outline-primary" onClick={exportCsv}>
                    Export CSV
                </button>
            </div>

            {error ? <p className="text-sm text-danger">{error}</p> : null}

            <div className={styles.wrapper}>
                <div className={styles.tableScroll}>
                    <table className={styles.table}>
                        <thead className={styles.thead}>
                            {table.getHeaderGroups().map((headerGroup) => (
                                <tr key={headerGroup.id}>
                                    {headerGroup.headers.map((header) => {
                                        const sortable = header.column.getCanSort();
                                        return (
                                            <th
                                                key={header.id}
                                                className={thClass(header.column.id, sortable)}
                                                onClick={sortable ? header.column.getToggleSortingHandler() : undefined}
                                            >
                                                {flexRender(header.column.columnDef.header, header.getContext())}
                                                {sortable
                                                    ? {
                                                          asc: <span className={styles.sortIcon}>▲</span>,
                                                          desc: <span className={styles.sortIcon}>▼</span>,
                                                      }[header.column.getIsSorted() as string] ?? null
                                                    : null}
                                            </th>
                                        );
                                    })}
                                </tr>
                            ))}
                        </thead>
                        <tbody>
                            {table.getRowModel().rows.length === 0 ? (
                                <tr>
                                    <td colSpan={columns.length} className={styles.empty}>
                                        {loading ? 'Memuat data...' : 'Belum ada order sukses di rentang ini'}
                                    </td>
                                </tr>
                            ) : (
                                table.getRowModel().rows.map((row) => (
                                    <tr key={row.id} className={styles.tr}>
                                        {row.getVisibleCells().map((cell) => (
                                            <td key={cell.id} className={tdClass(cell.column.id)}>
                                                {flexRender(cell.column.columnDef.cell, cell.getContext())}
                                            </td>
                                        ))}
                                    </tr>
                                ))
                            )}
                        </tbody>
                    </table>
                </div>

                <div className={styles.footer}>
                    <div className="flex items-center gap-2">
                        <span>Rows per page:</span>
                        <select
                            className={styles.select}
                            value={pagination.pageSize}
                            onChange={(e) => table.setPageSize(Number(e.target.value))}
                        >
                            {PAGE_SIZE_OPTIONS.map((n) => (
                                <option key={n} value={n}>
                                    {n}
                                </option>
                            ))}
                        </select>
                        <span>
                            {from}-{to} of {total.toLocaleString('id-ID')}
                        </span>
                    </div>
                    <div className={styles.footerBtns}>
                        <button
                            type="button"
                            className={styles.pageBtn}
                            onClick={() => table.setPageIndex(0)}
                            disabled={!table.getCanPreviousPage()}
                        >
                            ⟨⟨
                        </button>
                        <button
                            type="button"
                            className={styles.pageBtn}
                            onClick={() => table.previousPage()}
                            disabled={!table.getCanPreviousPage()}
                        >
                            ⟨ Prev
                        </button>
                        <button
                            type="button"
                            className={styles.pageBtn}
                            onClick={() => table.nextPage()}
                            disabled={!table.getCanNextPage()}
                        >
                            Next ⟩
                        </button>
                        <button
                            type="button"
                            className={styles.pageBtn}
                            onClick={() => table.setPageIndex(table.getPageCount() - 1)}
                            disabled={!table.getCanNextPage()}
                        >
                            ⟩⟩
                        </button>
                    </div>
                </div>

                {loading ? (
                    <div className={styles.refreshOverlay} aria-busy="true">
                        <span className={styles.refreshSpinner} />
                    </div>
                ) : null}
            </div>
        </div>
    );
};

export default PurchaseOrdersTable;
