import { useEffect, useMemo, useState } from 'react';
import { ChevronDown, ChevronLeft, ChevronRight, Clock, Download } from 'lucide-react';
import { formatIdr } from '@/lib/currencyFormat';
import { pageList } from '@/lib/paginate';
import { agingInfo } from './arProblems';

const SECTION_CARD = 'flex flex-col overflow-visible rounded-xl border border-border bg-card shadow-sm';
const PAGE_SIZE = 10;
const NAV_BTN = 'grid size-8 place-items-center rounded-lg border border-border/60 bg-card text-muted-foreground transition-colors hover:border-primary/50 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:border-border/60 disabled:hover:text-muted-foreground';

// "Credit on Delivery · 90 Days" → heading + sub-line. NetSuite hands the term over as ONE
// string; when it carries no separator the sub-line is simply absent rather than invented.
function splitTerm(term) {
    const parts = String(term ?? '').split('·').map((s) => s.trim()).filter(Boolean);
    return { name: parts[0] || '—', detail: parts.slice(1).join(' · ') };
}

const csvCell = (v) => `"${String(v ?? '').replace(/"/g, '""')}"`;


const AR_TABLE = "w-full min-w-[640px] border-collapse [&_th]:whitespace-nowrap [&_th]:border-b [&_th]:border-border [&_th]:px-3.5 [&_th]:py-2.5 [&_th]:text-left [&_th]:text-[10px] [&_th]:font-extrabold [&_th]:uppercase [&_th]:tracking-[0.04em] [&_th]:text-muted-foreground [&_tbody_td]:whitespace-nowrap [&_tbody_td]:border-b [&_tbody_td]:border-border/60 [&_tbody_td]:px-3.5 [&_tbody_td]:py-3 [&_tbody_td]:text-left";

/** Invoice rows — identical markup whether the table is the merged one or a per-customer one. */
function InvoiceRows({ rows }) {
    return rows.map((inv, i) => {
        const ag = agingInfo(inv.agingDays);
        // Row tint ONLY for aging > 60 days (user decision 2026-07-27).
        const overdue60 = (inv.agingDays ?? 0) > 60;
        return (
            <tr key={i} className={overdue60 ? '[&_td]:!bg-danger/8 hover:[&_td]:!bg-danger/15' : 'hover:[&_td]:bg-secondary/40'}>
                <td className={`font-semibold text-card-foreground ${overdue60 ? 'border-l-2 border-l-danger !pl-3' : ''}`}>{inv.no}</td>
                <td className="text-muted-foreground">{inv.invoiceDate ?? '—'}</td>
                <td className={overdue60 ? 'font-medium text-danger-text' : 'text-muted-foreground'}>{inv.dueDate ?? '—'}</td>
                <td className="!text-right font-medium text-card-foreground [font-variant-numeric:tabular-nums]">{formatIdr(inv.remaining)}</td>
                <td>
                    <span className={`inline-flex items-center rounded-full px-2.5 py-1 text-[10px] font-bold ${ag.pill}`}>{ag.label}</span>
                </td>
            </tr>
        );
    });
}



/**
 * Customer Outstanding (List) — Quotation Create.
 *
 * Layout follows the design the user supplied 2026-08-03: the payment term and credit limit ride
 * in the CARD HEADER (not as stat cards above the table), an aging legend, then the invoice table,
 * then a summary strip carrying overdue count / oldest overdue / freshness / CSV export.
 *
 * ONE deliberate departure from that design, at the user's request: Total AR and Past Due are NOT
 * a free-floating band under the table. They are `<tfoot>` rows, so each figure sits directly
 * under the AMOUNT column it totals — which is where the eye already is, and how a ledger reads.
 *
 * @param {{ data: object|null, loading: boolean }} props
 */
export function CustomerArList({ data, loading }) {
    const [collapsed, setCollapsed] = useState(false);
    const [page, setPage] = useState(1);
    const [fetchedAt, setFetchedAt] = useState(null);

    const customers = data?.customers ?? [];

    // ONE CUSTOMER PER VIEW. `company.NSCustomerID` can hold several comma-separated NetSuite
    // codes, and this panel used to merge them: one table with no Customer column, a header
    // naming customers[0] as if it spoke for all, and a COMBINED credit limit. That combination
    // could show "38% terpakai" while one of the customers was individually over its own limit.
    //
    // Now the extra customers become TABS. Every figure below — header, table, totals, footer,
    // CSV — is scoped to the selected one, so nothing on screen is ever an average of two
    // different credit agreements.
    const split = customers.length > 1;
    const [activeNs, setActiveNs] = useState(null);
    const active = split
        ? (customers.find((c) => String(c.nsCode) === String(activeNs)) ?? customers[0])
        : customers[0];

    const totalAr = split ? (active?.subtotal ?? 0) : (data?.totalAr ?? 0);
    const totalCreditLimit = split ? (active?.creditLimit ?? 0) : (data?.totalCreditLimit ?? 0);
    // Per-customer verdict in tab mode; the server's company-wide one when there is only one.
    const overLimit = split
        ? ((active?.creditLimit ?? 0) > 0 && (active?.subtotal ?? 0) > (active?.creditLimit ?? 0))
        : (data?.overLimit ?? false);
    const usedPct = totalCreditLimit > 0 ? Math.min(100, Math.round((totalAr / totalCreditLimit) * 100)) : 0;
    const headerName = active?.customer ?? '—';
    const term = splitTerm(active?.paymentTerm);

    // Invoices in view = the selected customer's (tab mode) or every one (single customer).
    const invoices = useMemo(
        () => (split ? [active] : customers)
            .filter(Boolean)
            .flatMap((c) => (c.invoices ?? []).map((inv) => ({ ...inv, customer: c.customer }))),
        [customers, split, active],
    );

    // Past due = aging past the due date (agingDays > 0; ≤0 is not due yet / Future).
    const overdue = useMemo(() => invoices.filter((inv) => (inv.agingDays ?? 0) > 0), [invoices]);
    const overdueCount = overdue.length;
    const overdueTotal = overdue.reduce((s, inv) => s + (inv.remaining || 0), 0);
    const overduePct = invoices.length > 0 ? Math.round((overdueCount / invoices.length) * 100) : 0;
    // Oldest overdue = the largest aging, and the due date it has been running from.
    const oldest = useMemo(
        () => overdue.reduce((worst, inv) => ((inv.agingDays ?? 0) > (worst?.agingDays ?? 0) ? inv : worst), null),
        [overdue],
    );

    const totalPages = Math.max(1, Math.ceil(invoices.length / PAGE_SIZE));
    const current = Math.min(page, totalPages);
    const shown = invoices.slice((current - 1) * PAGE_SIZE, current * PAGE_SIZE);
    const from = invoices.length === 0 ? 0 : (current - 1) * PAGE_SIZE + 1;
    const to = Math.min(current * PAGE_SIZE, invoices.length);

    // A new company's AR replaces the old one: go back to page 1, and stamp the freshness line.
    // The stamp is the moment THIS panel received the rows — the payload carries no server
    // timestamp, and inventing one on a credit screen would be worse than showing none.
    useEffect(() => {
        setPage(1);
        // Land on the first customer, not on a code left over from the previous company.
        setActiveNs(data?.customers?.[0]?.nsCode ?? null);
        setFetchedAt(data ? new Date() : null);
    }, [data]);

    // No company chosen yet → render nothing at all. A panel whose only possible sentence is
    // "no outstanding invoices" costs ~270px of a form the user has barely started filling in
    // (locked rule: .claude/rules/ui-conventions.md, form-page grammar).
    if (!data && !loading) return null;

    const lastUpdated = fetchedAt
        ? `${fetchedAt.toLocaleDateString('id-ID', { day: 'numeric', month: 'long', year: 'numeric' })}, ${fetchedAt.toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit' })}`
        : null;

    const exportCsv = () => {
        const head = ['Customer', 'Invoice No', 'Invoice Date', 'Due Date', 'Amount (IDR)', 'Aging (days)', 'Status'];
        const body = invoices.map((inv) => [
            inv.customer, inv.no, inv.invoiceDate ?? '', inv.dueDate ?? '',
            inv.remaining ?? 0, inv.agingDays ?? '', agingInfo(inv.agingDays).label,
        ]);
        // ﻿ so Excel opens the file as UTF-8 instead of mangling the customer names.
        const csv = '﻿' + [head, ...body].map((r) => r.map(csvCell).join(',')).join('\r\n');
        const url = URL.createObjectURL(new Blob([csv], { type: 'text/csv;charset=utf-8;' }));
        const a = document.createElement('a');
        a.href = url;
        a.download = `customer-outstanding-${(headerName || 'customer').replace(/[^\w.-]+/g, '-').toLowerCase()}.csv`;
        document.body.appendChild(a);
        a.click();
        a.remove();
        URL.revokeObjectURL(url);
    };

    return (
        <section className={`${SECTION_CARD} ${collapsed ? '[&>*:not(header)]:hidden' : ''}`}>
            {/* Header carries the two figures an approver reads first: the term and the limit —
                both of the SELECTED customer. That is what makes them safe to show again: with
                tabs the panel never describes more than one credit agreement at a time. */}
            <header className="flex flex-wrap items-start justify-between gap-x-6 gap-y-4 border-b border-border p-[18px_24px]">
                <div className="min-w-0 flex-1">
                    <p className="m-0 mb-[3px] text-[10px] font-extrabold uppercase tracking-[0.025em] text-muted-foreground">Customer Outstanding</p>
                    <h2 className="m-0 text-[22px] font-extrabold leading-[1.2] tracking-[-0.01em] text-card-foreground">{headerName}</h2>
                </div>

                <div className="flex flex-wrap items-start gap-6">
                    <div className="min-w-[150px]">
                        <p className="m-0 mb-1 text-[10px] font-extrabold uppercase tracking-[0.05em] text-muted-foreground">Payment Term</p>
                        <strong className="block text-[15px] font-extrabold leading-tight text-card-foreground">{term.name}</strong>
                        {term.detail && <span className="mt-0.5 block text-[12px] font-medium text-muted-foreground">{term.detail}</span>}
                    </div>
                    <div className="min-w-[220px] border-l border-border pl-6">
                        <p className="m-0 mb-1 text-[10px] font-extrabold uppercase tracking-[0.05em] text-muted-foreground">Credit Limit</p>
                        <strong className={`block text-[15px] font-extrabold leading-tight [font-variant-numeric:tabular-nums] ${overLimit ? 'text-danger-text' : 'text-card-foreground'}`}>{formatIdr(totalCreditLimit)}</strong>
                        <div className="mt-2 h-1.5 overflow-hidden rounded-full bg-secondary">
                            <div className={`h-full rounded-full ${overLimit ? 'bg-danger' : 'bg-primary'}`} style={{ width: `${usedPct}%` }} />
                        </div>
                        <span className={`mt-1 block text-[11px] font-medium ${overLimit ? 'text-danger-text' : 'text-muted-foreground'}`}>
                            <strong className={`font-extrabold ${overLimit ? 'text-danger-text' : 'text-primary'}`}>{usedPct}%</strong> terpakai
                        </span>
                    </div>
                    <button type="button" aria-label="Collapse Customer Outstanding" aria-expanded={!collapsed} onClick={() => setCollapsed((v) => !v)}
                        className="inline-grid size-7.5 shrink-0 place-items-center rounded-full text-muted-foreground transition-colors hover:bg-secondary hover:text-card-foreground">
                        <ChevronDown aria-hidden="true" size={16} className={`transition-transform ${collapsed ? '' : 'rotate-180'}`} />
                    </button>
                </div>
            </header>

            <div className="flex-1 p-6 pb-0">
                {/* Demo-data badge REMOVED from this panel by user decision 2026-08-05 ("delete
                    aja tulisan itu") — an explicit carve-out from the issue-#187 convention.
                    NOTE: while a NETSUITE_*_FIXTURE flag is on, the figures here are still
                    fabricated; they just no longer announce it. */}

                <div className="mb-3 flex flex-wrap gap-3.5">
                    <span className="inline-flex items-center gap-1.5 text-[11px] font-medium text-muted-foreground"><i className="inline-block size-[9px] rounded-full bg-warning" />1–30</span>
                    <span className="inline-flex items-center gap-1.5 text-[11px] font-medium text-muted-foreground"><i className="inline-block size-[9px] rounded-full bg-stat-orange-text" />31–60</span>
                    <span className="inline-flex items-center gap-1.5 text-[11px] font-medium text-muted-foreground"><i className="inline-block size-[9px] rounded-full bg-danger" />&gt; 60</span>
                    <span className="inline-flex items-center gap-1.5 text-[11px] font-medium text-muted-foreground"><i className="inline-block size-[9px] rounded-full bg-primary-hover" />FUTURE</span>
                </div>

                {/* One tab per NetSuite customer. Only rendered when there IS a choice to make. */}
                {split && (
                    <div role="tablist" aria-label="NetSuite customer" className="mb-3.5 flex flex-wrap gap-1.5 border-b border-border">
                        {customers.map((c) => {
                            const on = String(c.nsCode) === String(active?.nsCode);
                            const cOver = c.creditLimit > 0 && c.subtotal > c.creditLimit;
                            return (
                                <button
                                    key={c.nsCode ?? c.customer}
                                    type="button"
                                    role="tab"
                                    aria-selected={on}
                                    onClick={() => { setActiveNs(c.nsCode); setPage(1); }}
                                    className={`-mb-px inline-flex items-center gap-2 border-b-2 px-3 py-2 text-[12px] font-bold transition-colors ${
                                        on
                                            ? 'border-primary text-primary'
                                            : 'border-transparent text-muted-foreground hover:text-card-foreground'
                                    }`}
                                >
                                    <span className="max-w-[220px] truncate">{c.customer || c.nsCode}</span>
                                    {/* A tab the user has NOT opened still has to be able to say
                                        "look at me" — otherwise an over-limit customer is one
                                        un-clicked tab away from being invisible again. */}
                                    {cOver && (
                                        <span className="inline-flex items-center rounded-full bg-danger-bg px-1.5 py-0.5 text-[9px] font-bold text-danger-text">
                                            Over limit
                                        </span>
                                    )}
                                </button>
                            );
                        })}
                    </div>
                )}

                {/* White header: this panel lives on a FORM page, so it follows the detail-table
                    treatment (border only, no grey band) — see .claude/rules/ui-conventions.md. */}
                <div className="overflow-x-auto">
                    <table className={AR_TABLE}>
                        <thead>
                            <tr>
                                <th>Invoice No</th>
                                <th>Invoice Date</th>
                                <th>Due Date</th>
                                <th className="!text-right [font-variant-numeric:tabular-nums]">Amount (IDR)</th>
                                <th>Status</th>
                            </tr>
                        </thead>
                        <tbody>
                            {loading && (
                                <tr><td colSpan={5} className="!whitespace-normal !px-3 !py-6 !text-center italic text-muted-foreground">Memuat AR…</td></tr>
                            )}
                            {!loading && invoices.length === 0 && (
                                <tr><td colSpan={5} className="!whitespace-normal !px-3 !py-6 !text-center italic text-muted-foreground">No outstanding invoices</td></tr>
                            )}
                            {!loading && <InvoiceRows rows={shown} />}
                        </tbody>
                        {/* Totals as tfoot — each figure sits under the column it totals, instead of
                            floating in a band beside the table (the placement the user flagged). */}
                        {!loading && invoices.length > 0 && (
                            <tfoot className="[&_td]:px-3.5 [&_td]:py-2.5">
                                <tr>
                                    <td colSpan={3} className="border-t border-border">
                                        <span className="text-[10px] font-extrabold uppercase tracking-[0.05em] text-muted-foreground">Total AR</span>
                                        <span className="ml-2 text-[11px] font-medium text-muted-foreground"><strong className="font-extrabold text-card-foreground">{invoices.length}</strong> invoices</span>
                                    </td>
                                    <td className="border-t border-border text-right text-[15px] font-extrabold text-primary [font-variant-numeric:tabular-nums]">{formatIdr(totalAr)}</td>
                                    <td className="border-t border-border" />
                                </tr>
                                <tr>
                                    <td colSpan={3}>
                                        <span className="text-[10px] font-extrabold uppercase tracking-[0.05em] text-muted-foreground">Past Due</span>
                                        <span className="ml-2 text-[11px] font-medium text-muted-foreground"><strong className={`font-extrabold ${overdueCount > 0 ? 'text-danger-text' : 'text-card-foreground'}`}>{overdueCount}</strong> lewat due date</span>
                                    </td>
                                    <td className={`text-right text-[15px] font-extrabold [font-variant-numeric:tabular-nums] ${overdueCount > 0 ? 'text-danger-text' : 'text-card-foreground'}`}>{formatIdr(overdueTotal)}</td>
                                    <td />
                                </tr>
                            </tfoot>
                        )}
                    </table>
                </div>

                {invoices.length > 0 && (
                    <div className="flex flex-wrap items-center justify-between gap-3 border-t border-border/60 py-3 text-xs text-muted-foreground">
                        <span className="tabular-nums">Showing {from} to {to} of {invoices.length} invoices</span>
                        {/* Page window comes from the shared pageList() — the one windowing rule. */}
                        <nav className="inline-flex shrink-0 items-center gap-1.5" aria-label="Pagination">
                            <button type="button" disabled={current === 1} onClick={() => setPage(Math.max(1, current - 1))} className={NAV_BTN} aria-label="Previous page">
                                <ChevronLeft className="size-3.5" />
                            </button>
                            {pageList(current, totalPages).map((p, i) => p === '…' ? (
                                <span key={`gap-${i}`} className="grid size-8 place-items-center text-muted-foreground/60">…</span>
                            ) : (
                                <button key={p} type="button" onClick={() => setPage(p)} aria-current={p === current ? 'page' : undefined}
                                    className={`grid size-8 place-items-center rounded-lg text-xs tabular-nums ${p === current ? 'border border-transparent bg-linear-to-br from-violet-500 to-primary font-bold text-white shadow-sm transition-[filter] hover:brightness-105' : 'border border-border/60 bg-card font-medium text-muted-foreground transition-colors hover:border-primary/50 hover:text-foreground'}`}>
                                    {p}
                                </button>
                            ))}
                            <button type="button" disabled={current === totalPages} onClick={() => setPage(Math.min(totalPages, current + 1))} className={NAV_BTN} aria-label="Next page">
                                <ChevronRight className="size-3.5" />
                            </button>
                        </nav>
                    </div>
                )}
            </div>

            {/* Summary strip: the three facts that decide whether this AR blocks the quotation. */}
            {!loading && invoices.length > 0 && (
                <footer className="flex flex-wrap items-center gap-x-6 gap-y-3 border-t border-border px-6 py-3.5">
                    <span className="inline-grid size-8 shrink-0 place-items-center rounded-full bg-secondary text-muted-foreground" aria-hidden="true">
                        <Clock className="size-4" />
                    </span>
                    <div className="min-w-[120px]">
                        <p className="m-0 text-[11px] font-medium text-muted-foreground">Overdue invoices</p>
                        <strong className={`text-[13px] font-extrabold [font-variant-numeric:tabular-nums] ${overdueCount > 0 ? 'text-danger-text' : 'text-card-foreground'}`}>
                            {overdueCount} ({overduePct}%)
                        </strong>
                    </div>
                    <div className="min-w-[140px]">
                        <p className="m-0 text-[11px] font-medium text-muted-foreground">Oldest overdue</p>
                        {oldest ? (
                            <>
                                <strong className="text-[13px] font-extrabold text-danger-text [font-variant-numeric:tabular-nums]">{Math.round(oldest.agingDays)} days</strong>
                                {oldest.dueDate && <span className="ml-2 text-[11px] font-medium text-muted-foreground">Sejak {oldest.dueDate}</span>}
                            </>
                        ) : (
                            <strong className="text-[13px] font-extrabold text-card-foreground">—</strong>
                        )}
                    </div>
                    {lastUpdated && (
                        <span className="inline-flex items-center gap-1.5 text-[11px] font-medium text-muted-foreground">
                            <Clock className="size-3.5" aria-hidden="true" /> Last updated: {lastUpdated} WIB
                        </span>
                    )}
                    <button type="button" onClick={exportCsv}
                        className="ml-auto inline-flex h-9 items-center justify-center gap-1.5 rounded-lg border border-input bg-card px-4 text-xs font-bold text-primary transition-colors hover:border-primary hover:bg-accent">
                        <Download className="size-3.5" /> Export CSV
                    </button>
                </footer>
            )}
        </section>
    );
}
