import { useEffect, useMemo, useState } from 'react';
import { router } from '@inertiajs/react';
import { Eye, RotateCcw, Search } from 'lucide-react';
import { StatusBadge } from '@/Components/Proto/UI/StatusBadge';
import { htmlToText } from '@/lib/utils';
// Reuse the quotation list's filter pills so the toolbar matches the other lists.
import { DateRangePill } from '@/Components/MenuQuotations/QuotationListPage/QuotationListPills';
import { FilterPill } from '@/Components/ui/filter-pill';
import { useResizableColumns, ColumnResizeGrip } from '@/lib/useResizableColumns';
import { useClientSort, SortButton } from '@/lib/ClientSort';
import { ListFooter } from '@/Components/Table/ListFooter';

// Sortable columns — id → row value (alphabetical A→Z on first click).
const SORT_GETTERS = {
    lwr: (r) => r.id,
    status: (r) => r.status,
    date: (r) => r.tanggal,
    company: (r) => r.company,
    project: (r) => r.projectTitle,
    creator: (r) => r.creator,
    feedbackStatus: (r) => r.feedbackStatus,
};

// Stable per-column widths (px) for the resizable header. Keyed by the stable
// string ids used on each <th> grip + the <colgroup>. The Action column is a
// fixed trailing column (literal width, not resizable).
const COL_W = {
    lwr: 100,
    status: 140,
    date: 130,
    company: 200,
    project: 220,
    creator: 130,
    feedbackStatus: 140,
    product: 240,
    notes: 220,
    technicalRemark: 240,
};
const ACTION_W = 110;   // fixed trailing Action column

// Data columns (default order, left→right). The trailing Action column is pinned —
// not draggable and never a drop target. Header drag-to-reorder persists under one
// shared key (every consumer list shows the same columns).
// Column set mirrors the legacy list partials — listlwrviewall / …view / …headdeptview /
// …labview / …labgdview / …labworkgdview all render the SAME 14 headers, and the three queue
// partials (approvalsm / pengerjaanlab / feedback) a subset of them. Creator, Feedback Status
// and the header-level Technical Remark were the three the port never rendered; Sales /
// Division / Industry / CompanyCategory are not columns here on purpose — they ride the muted
// meta line under Company (companyMeta below), which is denser and shows the same four values.
const COL_IDS = ['lwr', 'status', 'date', 'company', 'project', 'creator', 'feedbackStatus', 'product', 'notes', 'technicalRemark'];
const COL_LABELS = {
    lwr: 'LWR No', status: 'Status', date: 'Date', company: 'Company', project: 'Project',
    creator: 'Creator', feedbackStatus: 'Feedback Status', product: 'Product Name',
    notes: 'Line Remark', technicalRemark: 'Technical Remark',
};
// Line-level columns carry the group divider (border-l) — it travels with the column.
const DIVIDED_COLS = new Set(['product', 'notes']);
const COL_STORAGE_KEY = 'lwrDenseColumns_v1';
const defaultOrder = () => [...COL_IDS];
function loadOrder() {
    try {
        const raw = localStorage.getItem(COL_STORAGE_KEY);
        if (!raw) return defaultOrder();
        const parsed = JSON.parse(raw).filter((id) => COL_IDS.includes(id));
        // Insert any column missing from the saved order at its default position.
        COL_IDS.forEach((id, i) => { if (!parsed.includes(id)) parsed.splice(i, 0, id); });
        return parsed;
    } catch {
        return defaultOrder();
    }
}

/**
 * High-density flat LWR table (Linear/Stripe style) for the View All list.
 * One row = ONE product line (LWRs are flattened), so Qty/Price/Principal/Product
 * stay single-valued and rows stay compact (~45px). LWR-level columns (Company,
 * LWR No, Status) render once on the first line of each LWR group; per-line columns
 * render on every row. All columns always visible, no collapse/expand — same as legacy,
 * which also renders its full 14-header set and lets the table scroll sideways.
 *
 *   Company · Product · Qty▸ · Price▸ ‖ Principal · Product Name(2ln) · LWR No ‖ Status · Notes · Detail
 */

const STATUS_TONES = {
    'Request': 'warning',
    'Approval SM': 'primary',
    'Approval PM': 'primary',
    'Revise': 'warning',
    'Reject': 'danger',
    'Cancel': 'danger',
    'Print': 'success',
    'Feedback': 'primary',
    'Process': 'primary',
    'Lab Processing': 'primary',
    'Compiled': 'success',
    'Done': 'success',
};
const statusTone = (s) => STATUS_TONES[s] || 'neutral';

const NA = () => <span className="text-muted-foreground/40">—</span>;
const fmtDate = (d) => (d ? String(d).slice(0, 10) : null);   // YYYY-MM-DD

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';

export function LwrDenseTable({ title, breadcrumb = [], labWorkRequests = [], detailRouteName, headerActions }) {
    const [q, setQ] = useState('');
    const [earlyDate, setEarlyDate] = useState('');
    const [endDate, setEndDate] = useState('');
    // Multi-select (user decision 2026-08-20). Values are arrays of display NAMES — the same
    // strings the rows carry — so filtering stays a plain includes() and the export sends
    // `status[]=…`, never a comma-joined scalar (company names contain commas).
    const [fStatus, setFStatus] = useState([]);
    const [fCreator, setFCreator] = useState([]);
    const [fDivision, setFDivision] = useState([]);
    const [fIndustry, setFIndustry] = useState([]);
    const [fSales, setFSales] = useState([]);
    const [fCompany, setFCompany] = useState([]);
    const [activePill, setActivePill] = useState(null);
    const togglePill = (key) => setActivePill((cur) => (cur === key ? null : key));
    const [pageSize, setPageSize] = useState(10);
    const [page, setPage] = useState(1);

    // Distinct option lists derived from the loaded LWRs.
    const opts = useMemo(() => {
        const distinct = (key) => Array.from(new Set(labWorkRequests.map((r) => r[key]).filter(Boolean)))
            .sort((a, b) => String(a).localeCompare(String(b)));
        return {
            status: distinct('status'), creator: distinct('creator'), division: distinct('division'),
            industry: distinct('industry'), sales: distinct('sales'), company: distinct('company'),
        };
    }, [labWorkRequests]);

    // Boolean(): `('' || 0 || 0)` is the NUMBER 0, and `{0 && <x/>}` makes React print a
    // literal "0" in the toolbar. The old all-strings version collapsed to '' and rendered
    // nothing, so this only became reachable once the pills started holding arrays.
    const anyFilter = Boolean(q || earlyDate || endDate
        || fStatus.length || fCreator.length || fDivision.length || fIndustry.length || fSales.length || fCompany.length);
    const resetFilters = () => {
        setQ(''); setEarlyDate(''); setEndDate('');
        setFStatus([]); setFCreator([]); setFDivision([]); setFIndustry([]); setFSales([]); setFCompany([]);
    };

    const lwrs = useMemo(() => {
        const s = q.trim().toLowerCase();
        return labWorkRequests.filter((r) => {
            const d = (r.tanggal || '').slice(0, 10);                       // YYYY-MM-DD (ISO-comparable)
            if (earlyDate && (!d || d < earlyDate)) return false;
            if (endDate && (!d || d > endDate)) return false;
            if (fStatus.length && !fStatus.includes(r.status)) return false;
            if (fCreator.length && !fCreator.includes(r.creator)) return false;
            if (fDivision.length && !fDivision.includes(r.division)) return false;
            if (fIndustry.length && !fIndustry.includes(r.industry)) return false;
            if (fSales.length && !fSales.includes(r.sales)) return false;
            if (fCompany.length && !fCompany.includes(r.company)) return false;
            if (s) {
                const hay = `${r.id} ${r.company ?? ''} ${r.projectTitle ?? ''} ${r.sales ?? ''} ${r.creator ?? ''} ${(r.products ?? []).map((p) => `${p.principal ?? ''} ${p.productName ?? ''} ${p.competitor ?? ''}`).join(' ')}`.toLowerCase();
                if (!hay.includes(s)) return false;
            }
            return true;
        });
    }, [labWorkRequests, q, earlyDate, endDate, fStatus, fCreator, fDivision, fIndustry, fSales, fCompany]);

    // Only non-empty keys travel: the server treats absent and blank identically, and a clean
    // query string keeps the export URL readable when someone reports a wrong file.
    const exportParams = useMemo(() => Object.fromEntries(Object.entries({
        search: q.trim(),
        dateFrom: earlyDate,
        dateTo: endDate,
        status: fStatus,
        creator: fCreator,
        division: fDivision,
        industry: fIndustry,
        sales: fSales,
        company: fCompany,
    }).filter(([, v]) => (Array.isArray(v) ? v.length > 0 : v !== '' && v !== null && v !== undefined))),
    [q, earlyDate, endDate, fStatus, fCreator, fDivision, fIndustry, fSales, fCompany]);
    const { sorted: sortedLwrs, sortKey, sortDir, toggleSort } = useClientSort(lwrs, SORT_GETTERS);

    // Client-side pagination — paginate by LWR so a record's product lines stay
    // together on one page.
    const totalLwrs = lwrs.length;
    const totalPages = Math.max(1, Math.ceil(totalLwrs / pageSize));
    const safePage = Math.min(page, totalPages);
    useEffect(() => { setPage(1); }, [q, earlyDate, endDate, fStatus, fCreator, fDivision, fIndustry, fSales, fCompany, pageSize]);
    const pageLwrs = useMemo(
        () => sortedLwrs.slice((safePage - 1) * pageSize, (safePage - 1) * pageSize + pageSize),
        [sortedLwrs, safePage, pageSize],
    );

    // Flatten the current page to one row per product line; mark the first line of each LWR group.
    const rows = useMemo(() => {
        const out = [];
        for (const lwr of pageLwrs) {
            const products = (Array.isArray(lwr.products) && lwr.products.length) ? lwr.products : [null];
            products.forEach((p, idx) => out.push({ key: `${lwr.id}-${idx}`, lwr, p, isFirst: idx === 0 }));
        }
        return out;
    }, [pageLwrs]);

    const openDetail = (id) => router.visit(route(detailRouteName, id));

    // Resizable columns — drag a header cell's right edge to resize. Widths live
    // in component state (reset on reload). Table runs `table-fixed` + <colgroup>.
    const { widthOf, startResize, resizingId, resizeRef } = useResizableColumns(COL_W, 150);
    const tableWidth = useMemo(
        () => Object.keys(COL_W).reduce((sum, id) => sum + widthOf(id), 0) + ACTION_W,
        [widthOf],
    );

    // Header drag-to-reorder — drop one column title onto another; order persists
    // (mirrors LwrListPage). The Action column stays pinned on the right.
    const [order, setOrder] = useState(() => loadOrder());
    const [dragColId, setDragColId] = useState(null);
    const [dragOverColId, setDragOverColId] = useState(null);
    const isDefaultOrder = order.length === COL_IDS.length && order.every((id, i) => id === COL_IDS[i]);
    const persistOrder = (next) => { try { localStorage.setItem(COL_STORAGE_KEY, JSON.stringify(next)); } catch { /* ignore */ } };
    const reorderCols = (fromId, toId) => {
        if (!fromId || !toId || fromId === toId) return;
        setOrder((prev) => {
            const fi = prev.indexOf(fromId);
            const ti = prev.indexOf(toId);
            if (fi < 0 || ti < 0) return prev;
            const next = [...prev];
            const [moved] = next.splice(fi, 1);
            next.splice(ti, 0, moved);
            persistOrder(next);
            return next;
        });
    };
    const resetCols = () => { setOrder(defaultOrder()); try { localStorage.removeItem(COL_STORAGE_KEY); } catch { /* ignore */ } };

    return (
        <section className="flex min-w-0 flex-col gap-[18px]">
            <header className="flex flex-wrap items-center justify-between gap-4">
                <div>
                    <p className="m-0 mb-1.5 flex items-center gap-2 text-xs font-medium text-muted-foreground">
                        {breadcrumb.map((crumb, i) => (
                            <span key={i} className="flex items-center gap-2">
                                {i > 0 && <span aria-hidden="true">›</span>}
                                {crumb.href
                                    ? <a href={crumb.href} className="hover:text-foreground">{crumb.label}</a>
                                    : <span className={i === breadcrumb.length - 1 ? 'text-foreground' : ''}>{crumb.label}</span>}
                            </span>
                        ))}
                    </p>
                    <h1 className="m-0 text-2xl font-bold leading-[1.15] tracking-tight text-card-foreground">{title}</h1>
                </div>
                {/* `headerActions` may be a node OR a render function. The function form
                    hands it `exportParams` — this table's live filter state, keyed exactly as
                    LabWorkRequestController::applyLwrHeaderExportFilters() reads it — so the
                    Export button can ask the server for the SAME set the screen shows.
                    Legacy did the same: its Export link carried the search query string
                    (listlwrall.php:82). Sent as params rather than exported from the rows in
                    memory because the workbook needs 22 legacy columns, and the list payload
                    only carries the 14 the table renders. */}
                {headerActions && <div>{typeof headerActions === 'function' ? headerActions({ exportParams }) : headerActions}</div>}
            </header>

            {/* Click-away layer that closes any open filter pill. */}
            {activePill && <div className="fixed inset-0 z-40" onClick={() => setActivePill(null)} />}

            <article className="overflow-hidden rounded-2xl border border-border shadow-sm bg-card">
                <div className="flex flex-wrap items-center gap-2.5 border-b border-border/50 bg-card px-6 py-4">
                    {/* Search — far left, like the quotation list */}
                    <label className="relative inline-flex h-8 min-w-[200px] max-w-[320px] flex-1 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 LWR No, Company, Principal, Product…" autoComplete="off"
                            value={q} onChange={(e) => setQ(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>

                    {/* Filter pills */}
                    <div className="flex flex-wrap items-center gap-2.5">
                        <DateRangePill label="Tanggal" from={earlyDate} to={endDate} open={activePill === 'date'}
                            onToggle={() => togglePill('date')} onApply={(f, t) => { setEarlyDate(f); setEndDate(t); setActivePill(null); }} />
                        <FilterPill label="Status" value={fStatus} options={opts.status} onChange={setFStatus} />
                        <FilterPill label="Creator" value={fCreator} options={opts.creator} onChange={setFCreator} />
                        <FilterPill label="Division" value={fDivision} options={opts.division} onChange={setFDivision} />
                        <FilterPill label="Industry" value={fIndustry} options={opts.industry} onChange={setFIndustry} />
                        <FilterPill label="Sales" value={fSales} options={opts.sales} onChange={setFSales} />
                        <FilterPill label="Company" value={fCompany} options={opts.company} onChange={setFCompany} />
                    </div>

                    <div className="ml-auto inline-flex items-center gap-2">
                        {anyFilter && (
                            <button type="button" onClick={resetFilters} title="Reset semua filter"
                                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>
                        )}
                        {!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 columns
                            </button>
                        )}
                    </div>
                </div>

                <div className="overflow-x-auto pt-4">
                    <table className="w-full table-fixed border-separate border-spacing-0 [&_tbody_td]:overflow-hidden" style={{ minWidth: tableWidth }}>
                        <colgroup>
                            {order.map((id) => <col key={id} style={{ width: widthOf(id) }} />)}
                            <col style={{ width: ACTION_W }} />
                        </colgroup>
                        <thead>
                            <tr>
                                {order.map((id) => (
                                    <th key={id}
                                        draggable
                                        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"
                                        className={`${TH} group/col relative cursor-grab select-none active:cursor-grabbing ${DIVIDED_COLS.has(id) ? 'border-l border-border' : ''} ${dragColId === id ? 'opacity-40' : ''} ${dragOverColId === id && dragColId !== id ? '!bg-accent !text-primary' : ''}`}>
                                        {SORT_GETTERS[id]
                                            ? <SortButton id={id} label={COL_LABELS[id]} sortKey={sortKey} sortDir={sortDir} onToggle={toggleSort} />
                                            : COL_LABELS[id]}
                                        <ColumnResizeGrip onMouseDown={(e) => startResize(e, id)} active={resizingId === id} />
                                    </th>
                                ))}
                                <th className={`${TH} !text-right`}>Action</th>
                            </tr>
                        </thead>
                        <tbody>
                            {rows.length === 0 ? (
                                <tr>
                                    {/* +1 for the pinned Action column; hardcoding this broke
                                        the empty-state centring every time a column was added. */}
                                    <td colSpan={order.length + 1} className="px-4 py-14 text-center text-[13px] text-muted-foreground">
                                        {q ? 'No lab work requests match your search.' : 'No lab work requests found.'}
                                    </td>
                                </tr>
                            ) : (
                                rows.map(({ key, lwr, p, isFirst }, i) => {
                                    // Both remarks are CKEditor HTML; flatten to a plain-text preview.
                                    // They are SEPARATE columns: `notes` is the product line's own
                                    // labworkrequestdetails.TechnicalRemark, `technicalRemark` is the
                                    // header's. The cell used to fall back from one to the other, which
                                    // silently hid the header remark whenever a line had its own.
                                    const notes = htmlToText(p?.lineRemark);
                                    const headerRemark = htmlToText(lwr.technicalRemark);
                                    const companyMeta = [lwr.companyCategory, lwr.division, lwr.industry, lwr.sales ? `Sales: ${lwr.sales}` : null].filter(Boolean).join(' · ');
                                    // Product Name cell: main product (Colorindo or Competitor) + a muted line
                                    // carrying the category (Colorindo/Competitor) and, for a Colorindo line, its
                                    // competitor benchmark in parens.
                                    const prodPrimary = p?.productName || p?.competitor || null;
                                    const prodMeta = [p?.productFrom, (p?.productName && p?.competitor) ? `(${p.competitor})` : null].filter(Boolean).join(' · ');
                                    // Per-column cell renderer — cells follow the header drag `order`; markup
                                    // identical to the previous hardcoded <td>s. LWR-level cells (LWR No, Status,
                                    // Date, Company, Project) render once per LWR group; line-level cells
                                    // (Product Name, Notes) render on every row and carry the group divider.
                                    const renderCell = (id) => {
                                        switch (id) {
                                            case 'lwr': return (
                                                <td key="lwr" className="px-3.5 py-[13px] align-middle">
                                                    {isFirst
                                                        ? <span className="text-[12px] font-semibold tabular-nums text-primary">#{lwr.id}</span>
                                                        : null}
                                                </td>
                                            );
                                            case 'status': return (
                                                <td key="status" className="px-3.5 py-[13px] align-middle">
                                                    {isFirst
                                                        ? (lwr.status ? <StatusBadge tone={statusTone(lwr.status)}>{lwr.status}</StatusBadge> : <NA />)
                                                        : null}
                                                </td>
                                            );
                                            case 'date': return (
                                                <td key="date" className="px-3.5 py-[13px] align-middle">
                                                    {isFirst
                                                        ? <span className="text-[12px] tabular-nums text-foreground">{fmtDate(lwr.tanggal) || <NA />}</span>
                                                        : null}
                                                </td>
                                            );
                                            case 'company': return (
                                                <td key="company" className="px-3.5 py-[13px] align-middle">
                                                    {isFirst ? (
                                                        <div className="flex min-w-0 max-w-full flex-col leading-[1.15]">
                                                            <span className="truncate text-[12px] font-semibold text-foreground" title={lwr.company || ''}>{lwr.company || <NA />}</span>
                                                            {companyMeta
                                                                ? <span className="truncate text-[12px] text-muted-foreground cursor-help" title={companyMeta} onClick={(e) => e.stopPropagation()}>{companyMeta}</span>
                                                                : null}
                                                        </div>
                                                    ) : null}
                                                </td>
                                            );
                                            case 'project': return (
                                                <td key="project" className="px-3.5 py-[13px] align-middle">
                                                    {isFirst
                                                        ? <span className="block max-w-full truncate text-[12px] text-foreground">{lwr.projectTitle || <NA />}</span>
                                                        : null}
                                                </td>
                                            );
                                            case 'product': return (
                                                <td key="product" className="border-l border-border/40 px-3.5 py-[13px] align-middle">
                                                    <div className="flex min-w-0 max-w-full flex-col leading-[1.15]">
                                                        <span className="truncate text-[12px] font-semibold text-foreground">{prodPrimary || <NA />}</span>
                                                        {prodMeta
                                                            ? <span className="truncate text-[12px] text-muted-foreground">{prodMeta}</span>
                                                            : <span className="text-[12px] text-muted-foreground/40">—</span>}
                                                    </div>
                                                </td>
                                            );
                                            case 'notes': return (
                                                <td key="notes" className="border-l border-border/40 px-3.5 py-[13px] align-middle">
                                                    {notes
                                                        ? <span className="block max-w-full truncate text-[12px] text-muted-foreground" title={notes}>{notes}</span>
                                                        : <NA />}
                                                </td>
                                            );
                                            // LWR-level cells below — rendered once per group, like Company/Project.
                                            case 'creator': return (
                                                <td key="creator" className="px-3.5 py-[13px] align-middle">
                                                    {isFirst
                                                        ? <span className="block max-w-full truncate text-[12px] text-foreground" title={lwr.creator || ''}>{lwr.creator || <NA />}</span>
                                                        : null}
                                                </td>
                                            );
                                            case 'feedbackStatus': return (
                                                <td key="feedbackStatus" className="px-3.5 py-[13px] align-middle">
                                                    {isFirst
                                                        ? (lwr.feedbackStatus
                                                            ? <span className="block max-w-full truncate text-[12px] text-foreground" title={lwr.feedbackStatus}>{lwr.feedbackStatus}</span>
                                                            : <NA />)
                                                        : null}
                                                </td>
                                            );
                                            case 'technicalRemark': return (
                                                <td key="technicalRemark" className="px-3.5 py-[13px] align-middle">
                                                    {isFirst
                                                        ? (headerRemark
                                                            ? <span className="block max-w-full truncate text-[12px] text-muted-foreground" title={headerRemark}>{headerRemark}</span>
                                                            : <NA />)
                                                        : null}
                                                </td>
                                            );
                                            default: return null;
                                        }
                                    };
                                    return (
                                        <tr key={key} onClick={() => openDetail(lwr.id)}
                                            className={`group cursor-pointer bg-card transition-colors hover:bg-secondary/60 ${isFirst && i > 0 ? '[&>td]:border-t [&>td]:border-border/60' : ''}`}>
                                            {order.map(renderCell)}
                                            {/* Action — pinned trailing column */}
                                            <td className="px-3.5 py-[13px] text-right align-middle">
                                                <button type="button" onClick={(e) => { e.stopPropagation(); openDetail(lwr.id); }}
                                                    className="inline-flex items-center gap-1.5 rounded-md px-2 py-1 text-[11.5px] font-bold text-muted-foreground transition-colors hover:bg-primary/10 hover:text-primary">
                                                    <Eye className="size-3.5" /> Detail
                                                </button>
                                            </td>
                                        </tr>
                                    );
                                })
                            )}
                        </tbody>
                    </table>
                </div>

                <ListFooter
                    page={safePage}
                    totalPages={totalPages}
                    onPage={setPage}
                    pageSize={pageSize}
                    onPageSize={(n) => { setPageSize(n); setPage(1); }}
                    pageSizeOptions={[10, 25, 50, 100]}
                    total={totalLwrs}
                    itemLabel="LWRs"
                />
            </article>
        </section>
    );
}
