import { useEffect, useMemo, useRef, useState } from 'react';
import { TOOLBAR_GEAR, TOOLBAR_FILTERS } from '@/Components/Table';
import { router } from '@inertiajs/react';
import { ArrowDown, ArrowUp, ChevronsUpDown, RotateCcw, Search, Settings } from 'lucide-react';
import AppLayout from '@/Layouts/AppLayout';
import { ListFooter } from '@/Components/Table/ListFooter';
import { CreateActionButton } from '@/Components/Table/CreateActionButton';
import { SelectPill } from '@/Components/MenuQuotations/QuotationListPage/QuotationListPills';
import { ExportButton } from '@/lib/excel/ExportButton';
import { CustomizeColumnsModal } from '@/Components/Proto/Modals/CustomizeColumnsModal';
import { useResizableColumns, ColumnResizeGrip } from '@/lib/useResizableColumns';
import { cn } from '@/lib/utils';

// ─────────────────────────────────────────────────────────────────────────────
// View Stock Sample PM (legacy listbarangspm.php, menu 123). Option 2: the All Stock
// table LOOK but per-BARANG rows — Principal · Kode · Nama · Stock · Pending SO ·
// Remarks — scoped to the user's head-division principals (server-side). Read-only.
// Two exports: Product (listbarangviewexportpm) + Req vs Stock (listsampledetailsvsstock…).
// Rendered from StockSampleController@pm { rows, filters, options }.
// ─────────────────────────────────────────────────────────────────────────────

// Column catalogue — `groupId` buckets the column inside the Customize Columns modal.
// Kode Barang is the row's identity, so it stays `required` (and there is no separate
// row-number column: an identity column makes "No" redundant — see CLAUDE.md).
const COLUMN_GROUPS = [
    { id: 'product', label: 'Product' },
    { id: 'stock', label: 'Stock' },
];
const COLUMN_DEFS = [
    { id: 'kode', label: 'Kode Barang', groupId: 'product', required: true },
    { id: 'principal', label: 'Principal Name', groupId: 'product' },
    { id: 'nama', label: 'Nama Barang', groupId: 'product' },
    { id: 'stock', label: 'Stock', groupId: 'stock' },
    { id: 'pending', label: 'Pending SO', numeric: true, groupId: 'stock' },
    { id: 'remarks', label: 'Remarks', groupId: 'product' },
];
const SORTABLE = new Set(['principal', 'kode', 'nama', 'stock', 'pending']);
const COL_W = { principal: 200, kode: 120, nama: 240, stock: 200, pending: 110, remarks: 220 };
const COL_W_FALLBACK = 160;

// Column state = ordered [{id, visible}] — order AND visibility both persist.
const defaultColumnState = () => COLUMN_DEFS.map((d) => ({ id: d.id, visible: true }));
function loadColumnState(storageKey) {
    try {
        const raw = localStorage.getItem(storageKey);
        if (!raw) return defaultColumnState();
        const parsed = JSON.parse(raw).filter((c) => c && COLUMN_DEFS.some((d) => d.id === c.id));
        COLUMN_DEFS.forEach((d, i) => { if (!parsed.some((c) => c.id === d.id)) parsed.splice(i, 0, { id: d.id, visible: true }); });
        return parsed.map((c) => (COLUMN_DEFS.find((d) => d.id === c.id)?.required ? { ...c, visible: true } : c));
    } catch {
        return defaultColumnState();
    }
}

const EMPTY_PAGINATOR = { data: [], current_page: 1, last_page: 1, per_page: 10, from: 0, to: 0, total: 0 };
const dash = (v) => (v === null || v === undefined || v === '') ? <span className="text-muted-foreground/40">-</span> : v;

function lotsSummary(lots) {
    return (lots || []).map((l) => `${l.lot || '—'} (${l.stock} ${l.satuan}${l.expiry ? ' / ' + l.expiry : ''})`).join(', ');
}

// Per-column cell renderer — markup identical to the previous hardcoded <td>s.
function renderCell(r, colId) {
    switch (colId) {
        case 'kode': return <span className="whitespace-nowrap tabular-nums text-muted-foreground">{dash(r.kode)}</span>;
        case 'principal': return <span className="whitespace-nowrap font-semibold text-card-foreground">{dash(r.principal)}</span>;
        case 'nama': return <span className="font-semibold text-card-foreground">{dash(r.nama)}</span>;
        case 'stock': return (
            <span title={lotsSummary(r.lots) || undefined}>
                <span className="font-bold tabular-nums text-foreground">{r.totalStock}</span>
                <span className="ml-1 text-[11px] text-muted-foreground">({r.lotCount} lot)</span>
            </span>
        );
        case 'pending': return (
            <span className={cn('inline-flex min-w-[28px] items-center justify-center rounded-full px-2 py-0.5 text-[11px] font-bold tabular-nums',
                r.pendingSo > 0 ? 'bg-warning-bg text-warning-text' : 'bg-secondary text-muted-foreground')}>
                {r.pendingSo}
            </span>
        );
        case 'remarks': return <span className="block max-w-[220px] truncate text-muted-foreground" title={r.remarks || undefined}>{dash(r.remarks)}</span>;
        default: return null;
    }
}

export default function StockSamplePm({ rows = EMPTY_PAGINATOR, filters = {}, options = {}, canCreate = false }) {
    const data = rows.data;
    const pageSize = filters.per_page || 10;
    const currentPage = rows.current_page;
    const totalPages = rows.last_page;
    const sortKey = filters.sort || 'nama';
    const sortDir = filters.dir || 'asc';

    const [quickQuery, setQuickQuery] = useState(filters.search || '');
    const [openPill, setOpenPill] = useState(null);
    const filterBarRef = useRef(null);
    const searchDebounce = useRef(null);

    useEffect(() => {
        if (!openPill) return undefined;
        const onDoc = (e) => { if (filterBarRef.current && !filterBarRef.current.contains(e.target)) setOpenPill(null); };
        document.addEventListener('mousedown', onDoc);
        return () => document.removeEventListener('mousedown', onDoc);
    }, [openPill]);

    const buildParams = (overrides = {}) => {
        const params = {};
        const val = (k, def) => overrides[k] ?? filters[k] ?? def ?? '';
        const search = overrides.search ?? quickQuery;
        if (search) params.search = search;
        ['principal', 'category', 'name'].forEach((k) => { const v = val(k); if (v) params[k] = v; });
        const sort = val('sort', 'nama');
        const dir = val('dir', 'asc');
        if (sort !== 'nama') params.sort = sort;
        if (dir !== 'asc') params.dir = dir;
        const perPage = overrides.per_page ?? pageSize;
        if (perPage && Number(perPage) !== 10) params.per_page = perPage;
        const page = overrides.page ?? currentPage;
        if (page && Number(page) !== 1) params.page = page;
        return params;
    };
    // only: — see Index.jsx.
    const go = (overrides) => router.get(route('stock-samples.pm'), buildParams(overrides), {
        only: ['rows', 'filters'],
        preserveState: true, preserveScroll: true, replace: true,
    });
    const onSearchChange = (v) => {
        setQuickQuery(v);
        clearTimeout(searchDebounce.current);
        searchDebounce.current = setTimeout(() => go({ search: v, page: 1 }), 300);
    };
    const setFilter = (key, value) => { setOpenPill(null); go({ [key]: value, page: 1 }); };
    const onSort = (key) => go({ sort: key, dir: sortKey === key && sortDir === 'asc' ? 'desc' : 'asc', page: 1 });
    const anyFilter = quickQuery || filters.principal || filters.category || filters.name;
    const clearFilters = () => { setQuickQuery(''); setOpenPill(null); go({ search: '', principal: '', category: '', name: '', page: 1 }); };

    // Both exports mirror the on-screen list; empties are dropped by the export hook.
    const exportParams = { search: filters.search, principal: filters.principal, category: filters.category, name: filters.name };

    // Column show/hide + reorder, persisted per user.
    const storageKey = 'stockSamplePmColumns_v1';
    const colDefById = useMemo(() => new Map(COLUMN_DEFS.map((d) => [d.id, d])), []);
    const [columnState, setColumnState] = useState(() => loadColumnState(storageKey));
    const [customizeOpen, setCustomizeOpen] = useState(false);
    const visibleCols = useMemo(() => columnState.filter((c) => c.visible).map((c) => colDefById.get(c.id)).filter(Boolean), [columnState, colDefById]);
    const isDefaultOrder = columnState.length === COLUMN_DEFS.length && columnState.every((c, i) => c.id === COLUMN_DEFS[i].id && c.visible);

    const persistCols = (next) => { try { localStorage.setItem(storageKey, JSON.stringify(next)); } catch { /* ignore */ } };
    const handleApplyColumns = (next) => { setColumnState(next); persistCols(next); };
    const resetCols = () => {
        const next = defaultColumnState();
        setColumnState(next);
        try { localStorage.removeItem(storageKey); } catch { /* ignore */ }
        return next;
    };
    // Direct header drag-to-reorder (LwrListPage pattern) — splices columnState and
    // persists via persistCols; resizeRef bails out so a grip drag never starts a column drag.
    const [dragColId, setDragColId] = useState(null);
    const [dragOverColId, setDragOverColId] = useState(null);
    const reorderCols = (fromId, toId) => {
        if (!fromId || !toId || fromId === toId) return;
        setColumnState((prev) => {
            const from = prev.findIndex((c) => c.id === fromId);
            const to = prev.findIndex((c) => c.id === toId);
            if (from < 0 || to < 0) return prev;
            const next = [...prev];
            const [moved] = next.splice(from, 1);
            next.splice(to, 0, moved);
            persistCols(next);
            return next;
        });
    };
    const dragProps = (id) => ({
        draggable: true,
        onDragStart: (e) => { if (resizeRef.current) { e.preventDefault(); return; } setDragColId(id); },
        onDragOver: (e) => { e.preventDefault(); setDragOverColId(id); },
        onDrop: () => { reorderCols(dragColId, id); setDragColId(null); setDragOverColId(null); },
        onDragEnd: () => { setDragColId(null); setDragOverColId(null); },
        title: 'Drag to reorder · drag right edge to resize',
    });
    const dragClass = (id) => cn('cursor-grab select-none active:cursor-grabbing', dragColId === id && 'opacity-40', dragOverColId === id && dragColId !== id && 'bg-accent text-primary');

    const { widthOf, startResize, resizingId, resizeRef } = useResizableColumns(COL_W, COL_W_FALLBACK);
    const tableWidth = useMemo(() => visibleCols.reduce((s, c) => s + widthOf(c.id), 0), [visibleCols, widthOf]);

    const SortIcon = ({ col }) => {
        if (sortKey !== col) return <ChevronsUpDown className="size-3 opacity-40" />;
        return sortDir === 'asc' ? <ArrowUp className="size-3" /> : <ArrowDown className="size-3" />;
    };

    return (
        <section className="flex min-w-0 flex-col gap-[18px]">
            <header>
                <p className="m-0 mb-1.5 flex items-center gap-2 text-xs font-semibold text-muted-foreground">
                    <span>Stock Sample</span>
                    <span aria-hidden="true">›</span>
                    <span className="text-foreground">View Stock Sample PM</span>
                </p>
                <div className="flex items-start justify-between gap-4">
                    <h1 className="m-0 text-xl font-bold leading-[1.2] text-card-foreground">View Stock Sample PM</h1>
                    <CreateActionButton canCreate={canCreate} label="Insert Sample" href={route('stock-samples.create')} />
                </div>
            </header>

            <article className="overflow-hidden rounded-2xl border border-border bg-card shadow-sm">
                <div ref={filterBarRef} className="flex flex-wrap items-center gap-2.5 border-b border-border/50 px-5 py-4">
                    <label className="relative inline-flex h-8 w-[240px] items-center gap-2 rounded-full border border-transparent bg-muted/60 px-3.5 text-muted-foreground transition-colors hover:bg-muted focus-within:border-primary/40 focus-within:bg-card">
                        <Search aria-hidden="true" className="size-3.5 shrink-0" />
                        <input type="search" placeholder="Search principal, product, code…" autoComplete="off"
                            value={quickQuery} onChange={(e) => onSearchChange(e.target.value)}
                            className="min-w-0 flex-1 bg-transparent text-[12.5px] font-medium text-foreground outline-none placeholder:text-muted-foreground/70" />
                    </label>
                    {/* ⚙ on line ONE: DOM position, not `order` — a flex line is filled in order
                        sequence and TOOLBAR_FILTERS is w-full. See TOOLBAR_ROW in Components/Table. */}
                    <button type="button" onClick={() => setCustomizeOpen(true)} title="Customize columns" aria-label="Customize columns"
                        className={TOOLBAR_GEAR}>
                        <Settings className="size-3.5" strokeWidth={2.5} />
                    </button>
                    <div className={TOOLBAR_FILTERS}>

                    <SelectPill label="Principal" value={filters.principal || ''} options={options.principals || []}
                        open={openPill === 'principal'} onToggle={() => setOpenPill(openPill === 'principal' ? null : 'principal')} onPick={(v) => setFilter('principal', v)} />
                    <SelectPill label="Category" value={filters.category || ''} options={options.categories || []}
                        open={openPill === 'category'} onToggle={() => setOpenPill(openPill === 'category' ? null : 'category')} onPick={(v) => setFilter('category', v)} />

                    {anyFilter && (
                        <button type="button" onClick={clearFilters}
                            title="Reset all active filters"
                            className="inline-flex h-8 cursor-pointer items-center gap-1.5 rounded-full px-2.5 text-[12.5px] font-semibold text-muted-foreground transition-colors hover:bg-danger/10 hover:text-danger-text">
                            <RotateCcw className="size-3.5" />
                            <span>Reset filters</span>
                        </button>
                    )}

                    <div className="ml-auto flex items-center gap-2">
                        <ExportButton specKey="stockPmProductExport" url={route('stock-samples.pm.export-data')} params={exportParams} label="Export (Product)" className="h-8 px-3 text-xs" />
                        <ExportButton specKey="stockPmReqVsStockExport" url={route('stock-samples.pm.req-vs-stock-export-data')} params={exportParams} label="Export (Req vs Stock)" className="h-8 px-3 text-xs" />
                        {!isDefaultOrder && (
                            <button type="button" onClick={resetCols} 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>
                        )}
                    </div>
                    </div>
                </div>

                <div className="px-5 pb-5 pt-4">
                    <div className="overflow-x-auto rounded-xl border border-border/40">
                        <table style={{ minWidth: tableWidth }} className="w-full table-fixed border-collapse [&_tbody_td]:overflow-hidden">
                            <colgroup>
                                {visibleCols.map((c) => <col key={c.id} style={{ width: widthOf(c.id) }} />)}
                            </colgroup>
                            <thead>
                                <tr className="border-b border-border [&_th]:whitespace-nowrap [&_th]:bg-secondary/50 [&_th]:px-3.5 [&_th]:py-3 [&_thead_th:first-child]:rounded-l-full [&_thead_th:first-child]:pl-7 [&_thead_th:last-child]:rounded-r-full [&_thead_th:last-child]:pr-5 [&_th]:text-left [&_th]:text-[11px] [&_th]:font-semibold [&_th]:uppercase [&_th]:tracking-wide [&_th]:text-muted-foreground">
                                    {visibleCols.map(({ id, label, numeric }) => (
                                        <th key={id} {...dragProps(id)} className={cn('group/col relative', numeric && '!text-right', dragClass(id))}>
                                            {SORTABLE.has(id) ? (
                                                <button type="button" onClick={() => onSort(id)}
                                                    className={cn('inline-flex items-center gap-1 uppercase tracking-wide hover:text-foreground', numeric && 'flex-row-reverse', sortKey === id && 'text-foreground')}>
                                                    {label}<SortIcon col={id} />
                                                </button>
                                            ) : label}
                                            <ColumnResizeGrip onMouseDown={(e) => startResize(e, id)} active={resizingId === id} />
                                        </th>
                                    ))}
                                </tr>
                            </thead>
                            <tbody className="[&_td]:border-b [&_td]:border-border/60 [&_td]:px-3.5 [&_td]:py-[16px] [&_tbody_td:first-child]:pl-7 [&_tbody_td:last-child]:pr-5 [&_td]:align-middle [&_td]:text-[12px] [&_td]:text-foreground [&_tr:nth-child(even)_td]:bg-secondary/25 [&_tr:hover_td]:bg-secondary/60 [&_tr:last-child_td]:border-b-0">
                                {data.length === 0 ? (
                                    <tr><td colSpan={visibleCols.length} className="!bg-transparent px-4 py-12 text-center text-[13px] text-muted-foreground">No barang under your head-division principals.</td></tr>
                                ) : data.map((r) => (
                                    <tr key={r.id}>
                                        {visibleCols.map((c) => (
                                            <td key={c.id} className={cn(c.numeric && '!text-right')}>
                                                {renderCell(r, c.id)}
                                            </td>
                                        ))}
                                    </tr>
                                ))}
                            </tbody>
                        </table>
                    </div>
                </div>

                <ListFooter
                    page={currentPage} totalPages={totalPages} onPage={(p) => go({ page: p })}
                    pageSize={Number(pageSize)} onPageSize={(n) => go({ per_page: n, page: 1 })} pageSizeOptions={[10, 25, 50, 100]}
                    total={rows.total} itemLabel="barang" />
            </article>

            <CustomizeColumnsModal
                open={customizeOpen}
                onClose={() => setCustomizeOpen(false)}
                groups={COLUMN_GROUPS}
                definitions={COLUMN_DEFS}
                state={columnState}
                onApply={handleApplyColumns}
                onReset={resetCols}
            />
        </section>
    );
}

StockSamplePm.layout = [AppLayout];
