import { useMemo, useState } from 'react';
import { Link, router } from '@inertiajs/react';
import { ChevronRight, RotateCcw, Settings } from 'lucide-react';
import { StatusBadge } from '@/Components/Proto/UI/StatusBadge';
import { CustomizeColumnsModal } from '@/Components/Proto/Modals/CustomizeColumnsModal';
import { HistoryPopover } from '@/Components/MenuQuotations/QuotationDetailPage/HistoryPopover';
import { CreditCeilingHistory } from './CreditCeilingHistory';
import { useServerSortNav, SortButton } from '@/lib/ServerSort';
import { useResizableColumns, ColumnResizeGrip } from '@/lib/useResizableColumns';

const fmt = (n) => Number(n || 0).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });

// Design-system table shell: rounded pill header (bg-secondary/50 — the /proto/visit-report
// reference tone), 13px body cells, hover rows. History = clock-chip popover (hover previews,
// click pins it open).
const TH = 'whitespace-nowrap bg-secondary/50 px-3.5 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-muted-foreground first:rounded-l-full first:pl-7 last:rounded-r-full last:pr-5';
const TD = 'whitespace-nowrap overflow-hidden text-ellipsis border-b border-border/60 px-3.5 py-[16px] align-middle text-[12px] text-card-foreground first:pl-7 last:pr-5';

// Default column widths for the resizable table-fixed layout (house pattern).
const COL_W = {
    id: 80, details: 90, company: 220, sales: 160, who: 140,
    proposedCC: 130, proposedTerm: 140, proposedTOP: 120,
    approvedCC: 130, approvedTerm: 140, approvedTOP: 130, addTOP: 110,
    special: 200, history: 100,
};

// Column catalogue — `who` is the Status/Creator slot; `sales` only exists on showSales
// views. ID + Details + Company stay locked (row anchor + the only way into the record).
// `groupId` buckets the column inside the Customize Columns modal (hide + reorder).
export const CC_COLUMN_GROUPS = [
    { id: 'identifiers', label: 'Identifiers' },
    { id: 'proposed', label: 'Proposed' },
    { id: 'approved', label: 'Approved' },
    { id: 'meta', label: 'Meta' },
];
const ccColumns = ({ showSales = false, showCreator = false } = {}) => [
    { id: 'id', label: 'ID', required: true, groupId: 'identifiers' },
    { id: 'details', label: 'Details', required: true, groupId: 'identifiers' },
    { id: 'company', label: 'Company', required: true, groupId: 'identifiers' },
    ...(showSales ? [{ id: 'sales', label: 'Sales', groupId: 'identifiers' }] : []),
    { id: 'who', label: showCreator ? 'Creator' : 'Status', groupId: 'identifiers' },
    { id: 'proposedCC', label: 'ProposedCC', right: true, groupId: 'proposed' },
    { id: 'proposedTerm', label: 'Payment Term', groupId: 'proposed' },
    { id: 'proposedTOP', label: 'ProposedTOP', right: true, groupId: 'proposed' },
    { id: 'approvedCC', label: 'ApprovedCC', right: true, groupId: 'approved' },
    { id: 'approvedTerm', label: 'Approved Term', groupId: 'approved' },
    { id: 'approvedTOP', label: 'ApprovedTOP', right: true, groupId: 'approved' },
    { id: 'addTOP', label: 'Add. TOP', right: true, groupId: 'approved' },
    { id: 'special', label: 'Special Condition', groupId: 'meta' },
    { id: 'history', label: 'History', center: true, groupId: 'meta' },
];

// Column state = ordered [{id, visible}] — order AND visibility both persist.
// Key bumped to _v2: the old _v1 payload was a flat visible-id array (no ordering).
const defaultColumnState = (defs) => defs.map((d) => ({ id: d.id, visible: true }));
function loadColumnState(defs, key) {
    try {
        const raw = localStorage.getItem(key);
        if (!raw) return defaultColumnState(defs);
        const parsed = JSON.parse(raw).filter((c) => c && defs.some((d) => d.id === c.id));
        defs.forEach((d, i) => { if (!parsed.some((c) => c.id === d.id)) parsed.splice(i, 0, { id: d.id, visible: true }); });
        // A required column can never end up hidden, whatever the stored payload says.
        return parsed.map((c) => (defs.find((d) => d.id === c.id)?.required ? { ...c, visible: true } : c));
    } catch {
        return defaultColumnState(defs);
    }
}

/**
 * Column show/hide + reorder for a credit-ceiling list, persisted per view in localStorage.
 * Pages pass the returned object to BOTH <CreditCeilingColumnsButton> (the ⚙ toolbar button
 * + its modal) and <CreditCeilingTable columns={…}>.
 */
export function useCreditCeilingColumns(view, opts = {}) {
    const { showSales = false, showCreator = false } = opts;
    // Deps are primitives — `opts` is a fresh object literal on every render.
    const defs = useMemo(() => ccColumns({ showSales, showCreator }), [showSales, showCreator]);
    const key = `ccListColumns_${view}_v2`;

    const [columnState, setColumnState] = useState(() => loadColumnState(defs, key));
    const [customizeOpen, setCustomizeOpen] = useState(false);

    const defById = useMemo(() => new Map(defs.map((d) => [d.id, d])), [defs]);
    const visibleCols = useMemo(
        () => columnState.filter((c) => c.visible).map((c) => defById.get(c.id)).filter(Boolean),
        [columnState, defById],
    );
    const isDefaultOrder = columnState.length === defs.length
        && columnState.every((c, i) => c.id === defs[i].id && c.visible);

    const persist = (next) => { try { localStorage.setItem(key, JSON.stringify(next)); } catch { /* private mode */ } };
    const apply = (next) => { setColumnState(next); persist(next); };
    // Returns the default state so the modal's Reset can seed its draft with it.
    const reset = () => {
        const next = defaultColumnState(defs);
        setColumnState(next);
        try { localStorage.removeItem(key); } catch { /* private mode */ }
        return next;
    };

    return { defs, columnState, visibleCols, isDefaultOrder, apply, reset, customizeOpen, setCustomizeOpen };
}

/** ⚙ toolbar button + the shared Customize Columns modal (hide + drag-reorder). */
export function CreditCeilingColumnsButton({ columns }) {
    const { defs, columnState, isDefaultOrder, apply, reset, customizeOpen, setCustomizeOpen } = columns;
    return (
        <div className="ml-auto inline-flex items-center gap-2">
            {!isDefaultOrder && (
                <button type="button" onClick={reset} title="Reset column order"
                    className="inline-flex h-8 items-center gap-1.5 rounded-full px-2.5 text-[12px] font-bold text-muted-foreground transition-colors hover:text-primary">
                    <RotateCcw className="size-3.5" /> Reset
                </button>
            )}
            <button type="button" onClick={() => setCustomizeOpen(true)}
                title="Customize columns (hide & reorder)" aria-label="Customize columns"
                className="grid size-7 place-items-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-primary">
                <Settings aria-hidden="true" className="size-3.5" strokeWidth={2.5} />
            </button>

            <CustomizeColumnsModal
                open={customizeOpen}
                onClose={() => setCustomizeOpen(false)}
                groups={CC_COLUMN_GROUPS}
                definitions={defs}
                state={columnState}
                onApply={apply}
                onReset={reset}
            />
        </div>
    );
}

// Per-column cell renderer — markup identical to the previous hardcoded <td>s.
// `ctx` carries the per-view bits the cells need (Creator-vs-Status, the row links).
function renderCell(r, colId, ctx) {
    switch (colId) {
        case 'id': return <span className="font-semibold tabular-nums text-primary">#{r.id}</span>;
        // Row-into-record link — same grammar as the Complaint queues (Review/Complete Index):
        // label + ChevronRight that slides 2px on hover, so the affordance reads as "go there"
        // instead of a bare underline.
        case 'details': return ctx.reviseRoute && r.statusId === 6
            ? (
                <Link href={route(ctx.reviseRoute, r.id)} className="group/link inline-flex items-center gap-1 text-[12px] font-bold text-warning-text transition-colors hover:underline">
                    Revise <ChevronRight className="size-3.5 transition-transform duration-200 group-hover/link:translate-x-0.5" aria-hidden="true" />
                </Link>
            )
            : (
                <Link href={route(ctx.detailRoute, r.id)} className="group/link inline-flex items-center gap-1 text-[12px] font-bold text-primary transition-colors hover:underline">
                    Details <ChevronRight className="size-3.5 transition-transform duration-200 group-hover/link:translate-x-0.5" aria-hidden="true" />
                </Link>
            );
        case 'company': return <span className="block max-w-[220px] truncate text-[12px] font-semibold text-foreground" title={r.company || ''}>{r.company}</span>;
        case 'sales': return <span className="block max-w-[160px] truncate">{r.sales || '—'}</span>;
        case 'who': return ctx.showCreator ? (r.creator || '—') : <StatusBadge tone="neutral">{r.status}</StatusBadge>;
        case 'proposedCC': return fmt(r.proposedCC);
        case 'proposedTerm': return r.proposedTerm || '—';
        case 'proposedTOP': return <>{r.proposedTOP} <span className="text-muted-foreground">days</span></>;
        case 'approvedCC': return fmt(r.approvedCC);
        case 'approvedTerm': return r.approvedTerm || '—';
        case 'approvedTOP': return <>{r.approvedTOP} <span className="text-muted-foreground">days</span></>;
        case 'addTOP': return <>{r.approvedAdditionalTOP} <span className="text-muted-foreground">days</span></>;
        case 'special': return <span className="block max-w-[200px] truncate text-muted-foreground" title={r.specialCondition || ''}>{r.specialCondition || '—'}</span>;
        case 'history': return (
            <HistoryPopover count={(r.history || []).length} title="History" width={400}>
                <CreditCeilingHistory items={r.history} compact />
            </HistoryPopover>
        );
        default: return null;
    }
}

// Review queues (single-status) show the Creator column; view queues show Status.
// `reviseRoute` (optional): rows at status 6 (Revise) link to the creator revise form instead of Details.
// `columns` (from useCreditCeilingColumns) drives which columns render and in what order;
// omit it to show every column in the default order.
export function CreditCeilingTable({ rows = [], filters = {}, showCreator = false, showSales = false, detailRoute = 'credit-ceilings.show', reviseRoute = null, columns = null }) {
    const fallback = useMemo(() => ccColumns({ showSales, showCreator }), [showSales, showCreator]);
    const cols = columns?.visibleCols ?? fallback;
    const ctx = { showCreator, detailRoute, reviseRoute };

    // C4/rule-26: this list is SERVER-paginated, so it must be SERVER-sorted — re-sorting only the
    // rows on the visible page (the old useClientSort) is the banned pattern. Header id → the
    // controller's SORT_COLUMNS key (null = column not sortable). `who` shows Status (server-sortable)
    // on non-review screens and Creator on review queues; Creator + Sales + the two payment-term NAMES
    // are joined columns and are intentionally NOT sortable — sorting by a joined name makes the
    // lookup the driving table (list-pagination.md rule 1). sort/dir travel to the server via
    // useServerSortNav (current path, since this one table serves review-cs / view-request / view-all)
    // and come back on the `filters` prop; the server returns `rows` already ordered.
    const serverSortKey = useMemo(() => ({
        id: 'id',
        company: 'company',
        who: showCreator ? null : 'status',
        proposedCC: 'proposedCC',
        proposedTOP: 'proposedTOP',
        approvedCC: 'approvedCC',
        approvedTOP: 'approvedTOP',
        addTOP: 'addTOP',
        special: 'special',
    }), [showCreator]);
    const { sortKey, sortDir, toggleSort } = useServerSortNav(null, filters);

    // Resize (grip at each header's right edge) + direct header drag-to-reorder.
    const { widthOf, startResize, resizingId, resizeRef } = useResizableColumns(COL_W);
    const [dragColId, setDragColId] = useState(null);
    const [dragOverColId, setDragOverColId] = useState(null);
    const reorderCols = (fromId, toId) => {
        if (!columns || !fromId || !toId || fromId === toId) return;
        const state = columns.columnState;
        const from = state.findIndex((c) => c.id === fromId);
        const to = state.findIndex((c) => c.id === toId);
        if (from < 0 || to < 0) return;
        const next = [...state];
        const [moved] = next.splice(from, 1);
        next.splice(to, 0, moved);
        columns.apply(next);
    };
    const tableWidth = cols.reduce((s, c) => s + widthOf(c.id), 0);

    return (
        <div className="overflow-x-auto">
            <table style={{ minWidth: tableWidth }} className="w-full table-fixed border-separate border-spacing-0">
                <colgroup>
                    {cols.map((c) => <col key={c.id} style={{ width: widthOf(c.id) }} />)}
                </colgroup>
                <thead>
                    <tr>
                        {cols.map((h) => (
                            <th key={h.id}
                                {...(columns ? {
                                    draggable: true,
                                    onDragStart: (e) => { if (resizeRef.current) { e.preventDefault(); return; } setDragColId(h.id); },
                                    onDragOver: (e) => { e.preventDefault(); setDragOverColId(h.id); },
                                    onDrop: () => { reorderCols(dragColId, h.id); setDragColId(null); setDragOverColId(null); },
                                    onDragEnd: () => { setDragColId(null); setDragOverColId(null); },
                                    title: 'Drag to reorder · drag right edge to resize',
                                } : {})}
                                className={`${TH} group/col relative select-none ${h.right ? 'text-right' : h.center ? 'text-center' : ''} ${columns ? 'cursor-grab active:cursor-grabbing' : ''} ${dragColId === h.id ? 'opacity-40' : ''} ${dragOverColId === h.id && dragColId !== h.id ? '!bg-accent !text-primary' : ''}`}>
                                {serverSortKey[h.id]
                                    ? <SortButton id={serverSortKey[h.id]} label={h.label} sortKey={sortKey} sortDir={sortDir} onToggle={toggleSort} />
                                    : h.label}
                                <ColumnResizeGrip onMouseDown={(e) => startResize(e, h.id)} active={resizingId === h.id} />
                            </th>
                        ))}
                    </tr>
                </thead>
                <tbody className="[&_tr:nth-child(even)_td]:bg-secondary/25 [&_tr:hover_td]:bg-secondary/60 [&_tr:last-child_td]:border-b-0">
                    {rows.length === 0 && (
                        <tr><td colSpan={cols.length} className="px-4 py-10 text-center text-[13px] italic text-muted-foreground">Tidak ada data.</td></tr>
                    )}
                    {rows.map((r) => (
                        <tr key={r.id} className="cursor-pointer"
                            onClick={(e) => { if (e.target.closest('a,button,input,label')) return; router.visit(route(ctx.reviseRoute && r.statusId === 6 ? ctx.reviseRoute : ctx.detailRoute, r.id)); }}>
                            {cols.map((c) => (
                                <td key={c.id} className={`${TD} ${c.right ? 'text-right tabular-nums' : c.center ? 'text-center' : ''}`}>
                                    {renderCell(r, c.id, ctx)}
                                </td>
                            ))}
                        </tr>
                    ))}
                </tbody>
            </table>
        </div>
    );
}
