import { useEffect, useMemo, useState } from 'react';
import { TOOLBAR_GEAR, TOOLBAR_FILTERS } from '@/Components/Table';
import { router } from '@inertiajs/react';
import { ArrowDown, ArrowUp, ChevronDown, ChevronRight as Caret, ChevronsUpDown, Eye, RotateCcw, Search, Settings } from 'lucide-react';
import AppLayout from '@/Layouts/AppLayout';
import { cn } from '@/lib/utils';
import { ListFooter } from '@/Components/Table/ListFooter';
import { StatusBadge } from '@/Components/Proto/UI/StatusBadge';
import { SelectPill, DateRangePill } from '@/Components/MenuQuotations/QuotationListPage/QuotationListPills';
import { HistoryPopover } from '@/Components/MenuQuotations/QuotationDetailPage/HistoryPopover';
import { CustomizeColumnsModal } from '@/Components/Proto/Modals/CustomizeColumnsModal';
import { ExportButton } from '@/lib/excel/ExportButton';
import { useResizableColumns, ColumnResizeGrip } from '@/lib/useResizableColumns';
import { useStickyColShadow } from '@/lib/useStickyColShadow';

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 tone = (s) => STATUS_TONES[s] || 'neutral';
const NA = () => <span className="font-normal text-muted-foreground/55">-</span>;
const orNA = (v) => (v === null || v === undefined || v === '') ? <NA /> : v;
const num = (v) => (v === null || v === undefined || v === '') ? <NA /> : Number(v).toLocaleString('en-US');

// Quotation-style table shell (mirrors QuotationListPage): sticky header, sticky first
// column, zebra striping, rounded pill corners, horizontal scroll shadow.
const TABLE_CLASS = 'w-full table-fixed border-separate border-spacing-0 [&_tbody_td]:overflow-hidden [&_td]:whitespace-nowrap [&_td]:px-3.5 [&_td]:py-[16px] [&_td]:text-left [&_td]:text-[13px] [&_th]:whitespace-nowrap [&_th]:px-3.5 [&_th]:py-3 [&_th]:text-left [&_th]:text-[11px] [&_th.col-name]:sticky [&_th.col-name]:left-0 [&_th.col-name]:z-3 [&_thead_th]:sticky [&_thead_th]:top-0 [&_thead_th]:z-2 [&_thead_th]:bg-[color-mix(in_srgb,var(--color-secondary)_50%,var(--color-card))] [&_thead_th]:text-[11px] [&_thead_th]:font-semibold [&_thead_th]:uppercase [&_thead_th]:tracking-wide [&_thead_th]:text-muted-foreground [&_thead_tr:first-child_th:first-child]:rounded-l-full [&_thead_tr:first-child_th:first-child]:pl-7 [&_thead_tr:first-child_th:last-child]:rounded-r-full [&_thead_tr:first-child_th:last-child]:pr-5 [&_tbody_td]:border-b [&_tbody_td]:border-border/60 [&_tbody_td:last-child]:pr-5 [&_tbody_td]:px-3.5 [&_tbody_td]:py-[16px] [&_tbody_td]:align-middle [&_tbody_td]:text-[12px] [&_tbody_td]:text-card-foreground [&_tbody_td.col-name]:sticky [&_tbody_td.col-name]:left-0 [&_tbody_td.col-name]:z-1 [&_tbody_td.col-name]:bg-card [&_tbody_td.col-name]:font-semibold [&_tbody_td.col-name]:text-card-foreground [&_tbody_td:first-child]:pl-7 [&_tbody_tr:hover_td]:bg-secondary/60 [&_tbody_tr:hover_td.col-name]:bg-secondary [&_tbody_tr:nth-child(even)_td]:bg-secondary/25 [&_tbody_tr:nth-child(even)_td.col-name]:bg-[color-mix(in_srgb,var(--color-secondary)_50%,var(--color-card))]';
const SCROLL_SHADOW = 'overflow-x-auto rounded-xl [background:linear-gradient(to_right,var(--card)_30%,transparent),linear-gradient(to_right,transparent,var(--card)_70%)_right,radial-gradient(farthest-side_at_0_50%,rgba(0,0,0,0.12),transparent),radial-gradient(farthest-side_at_100%_50%,rgba(0,0,0,0.12),transparent)_right] [background-attachment:local,local,scroll,scroll] [background-repeat:no-repeat] [background-size:40px_100%,40px_100%,14px_100%,14px_100%]';

// Columns mirror the legacy listlwrdetailsview*.php header. `numeric` drives sort + align.
const COLUMN_GROUPS = [
    { id: 'identifiers', label: 'Identifiers' },
    { id: 'metadata', label: 'Metadata' },
    { id: 'product', label: 'Product' },
];
const COLUMN_DEFS = [
    { id: 'lwrNo', label: 'LWR No', sticky: true , groupId: 'identifiers', required: true},
    { id: 'company', label: 'Company' , groupId: 'identifiers'},
    { id: 'status', label: 'Status' , groupId: 'identifiers'},
    { id: 'feedbackStatus', label: 'Feedback Status' , groupId: 'identifiers'},
    { id: 'projectTitle', label: 'Project Title' , groupId: 'identifiers'},
    { id: 'tanggal', label: 'Tanggal' , groupId: 'metadata'},
    { id: 'productFrom', label: 'Product From' , groupId: 'metadata'},
    { id: 'companyCategory', label: 'Company Category' , groupId: 'metadata'},
    { id: 'division', label: 'Division' , groupId: 'metadata'},
    { id: 'industry', label: 'Industry' , groupId: 'metadata'},
    { id: 'address', label: 'Address' , groupId: 'metadata'},
    { id: 'creator', label: 'Creator' , groupId: 'metadata'},
    { id: 'sales', label: 'Sales' , groupId: 'metadata'},
    { id: 'principal', label: 'Principal' , groupId: 'product'},
    { id: 'productName', label: 'Product Name' , groupId: 'product'},
    { id: 'colour', label: 'Colour' , groupId: 'product'},
    { id: 'typeForm', label: 'Type/Form' , groupId: 'product'},
    { id: 'volume', label: 'Volume Test', numeric: true , groupId: 'product'},
    { id: 'unitPriceUsd', label: 'Unit Price USD', numeric: true , groupId: 'product'},
    { id: 'potentialVolume', label: 'Potential Volume', numeric: true , groupId: 'product'},
    { id: 'potentialValue', label: 'Potential Value', numeric: true , groupId: 'product'},
    { id: 'productRemark', label: 'Product Remark' , groupId: 'product'},
    { id: 'remarkPm', label: 'Remark PM', sortable: false , groupId: 'product'},
    { id: 'history', label: 'History', sortable: false, cellClass: 'align-middle text-center' , groupId: 'metadata'},
];

// Default per-column pixel widths for the resizable table-fixed layout (overridable by drag).
const COL_W = {
    no: 70, lwrNo: 110, company: 200, status: 150, feedbackStatus: 150, projectTitle: 220,
    tanggal: 130, productFrom: 140, companyCategory: 170, division: 130, industry: 150,
    address: 220, creator: 130, sales: 130, principal: 150, productName: 200, colour: 130,
    typeForm: 140, volume: 130, unitPriceUsd: 150, potentialVolume: 160, potentialValue: 150,
    productRemark: 240, remarkPm: 220, history: 110, __action: 110,
};
const COL_W_FALLBACK = 150;

// Fields that get a filter pill (string select); options derive from the loaded rows.
const PILL_FIELDS = [
    { key: 'status', label: 'Status' }, { key: 'company', label: 'Company' },
    { key: 'division', label: 'Division' }, { key: 'industry', label: 'Industry' },
    { key: 'sales', label: 'Sales' }, { key: 'creator', label: 'Creator' },
    { key: 'principal', label: 'Principal' }, { key: 'productName', label: 'Product' },
];

const PER_PAGE_OPTIONS = [10, 15, 25, 50];

function renderCell(r, colId, rowNumber) {
    switch (colId) {
        case 'lwrNo': return <span className="font-semibold text-primary">#{r.lwrId}</span>;
        case 'company': return <span className="text-[12px] font-semibold text-foreground">{orNA(r.company)}</span>;
        case 'status': return r.status ? <StatusBadge tone={tone(r.status)}>{r.status}</StatusBadge> : <NA />;
        case 'feedbackStatus': return orNA(r.feedbackStatus);
        case 'projectTitle': return <span className="block max-w-[220px] truncate" title={r.projectTitle || ''}>{orNA(r.projectTitle)}</span>;
        case 'tanggal': return <span className="tabular-nums text-muted-foreground">{orNA(r.tanggal)}</span>;
        case 'productFrom': return orNA(r.productFrom);
        case 'companyCategory': return orNA(r.companyCategory);
        case 'division': return orNA(r.division);
        case 'industry': return orNA(r.industry);
        case 'address': return <span className="block max-w-[220px] truncate" title={r.address || ''}>{orNA(r.address)}</span>;
        case 'creator': return orNA(r.creator);
        case 'sales': return orNA(r.sales);
        case 'principal': return orNA(r.principal);
        case 'productName': return <span className="font-semibold text-card-foreground">{orNA(r.productName)}</span>;
        case 'colour': return orNA(r.colour);
        case 'typeForm': return orNA(r.typeForm);
        case 'volume': return <span className="tabular-nums">{num(r.volume)}{r.volumeUnit ? <span className="text-muted-foreground"> {r.volumeUnit}</span> : null}</span>;
        case 'unitPriceUsd': return <span className="tabular-nums">{num(r.unitPriceUsd)}{r.priceUnit ? <span className="text-muted-foreground"> /{r.priceUnit}</span> : null}</span>;
        case 'potentialVolume': return <span className="tabular-nums">{num(r.potentialVolume)}</span>;
        case 'potentialValue': return <span className="tabular-nums">{num(r.potentialValue)}</span>;
        case 'productRemark': return <span className="block max-w-[240px] whitespace-normal leading-snug text-muted-foreground">{orNA(r.productRemark)}</span>;
        case 'remarkPm': return (r.remarkPm || []).length === 0 ? <NA /> : (
            <div className="flex min-w-50 max-w-75 flex-col gap-1 whitespace-normal">
                {r.remarkPm.map((c, i) => (
                    <div key={i} className="leading-snug text-card-foreground">{c}</div>
                ))}
            </div>
        );
        case 'history': return (
            <HistoryPopover count={(r.history || []).length} title="History" width={340}>
                {(r.history || []).map((h, i) => (
                    <div key={i} className="text-[11px] leading-snug text-muted-foreground">
                        <span className="font-semibold text-foreground">{h.status || '—'}</span>
                        {h.tanggal ? <> · <span className="tabular-nums">{h.tanggal}</span></> : null}
                        {h.user ? ` · ${h.user}` : ''}
                    </div>
                ))}
            </HistoryPopover>
        );
        default: return null;
    }
}

// Column state = ordered [{id, visible}] — order AND visibility both persist.
// Key bumped to _v3: _v2 stored a flat id array (order only, no hide/show).
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();
    }
}

export default function LwrViewDetailsList({ details = [], title = 'View Details', drillIn = true, view = '' }) {
    // The five View Details menus each had their own legacy export file. Four are identical
    // in layout and differ only in filename — and SM/Head Dept even share that (legacy's own
    // duplication, kept deliberately).
    const EXPORT_SPEC = {
        '': 'lwrDetailsExport',
        pm: 'lwrDetailsPmExport',
        sm: 'lwrDetailsSmExport',
        mm: 'lwrDetailsMmExport',
        'head-dept': 'lwrDetailsHeadDeptExport',
    }[view] ?? 'lwrDetailsExport';
    const exportUrl = view === '' ? route('lwrs.export.details') : route('lwrs.export.details', view);

    const [q, setQ] = useState('');
    const [pillVals, setPillVals] = useState({});
    const [activePill, setActivePill] = useState(null);
    const [sort, setSort] = useState({ key: null, dir: 'asc' });
    const [perPage, setPerPage] = useState(15);
    const [page, setPage] = useState(1);

    const colDefById = useMemo(() => new Map(COLUMN_DEFS.map((d) => [d.id, d])), []);
    const storageKey = 'lwrViewDetailsColumns_v3';
    const [columnState, setColumnState] = useState(() => loadColumnState(storageKey));
    const [customizeOpen, setCustomizeOpen] = useState(false);
    const [dragColId, setDragColId] = useState(null);
    const [dragOverColId, setDragOverColId] = useState(null);
    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);

    // Resizable columns — drag a header's right edge (matches the quotation feedback list).
    const { widthOf, startResize, resizingId, resizeRef } = useResizableColumns(COL_W, COL_W_FALLBACK);
    const tableWidth = useMemo(() => visibleCols.reduce((s, c) => s + widthOf(c.id), 0) + (drillIn ? widthOf('__action') : 0), [visibleCols, widthOf, drillIn]);

    const persist = (next) => { try { localStorage.setItem(storageKey, JSON.stringify(next)); } catch { /* ignore */ } };
    const handleApplyColumns = (next) => { setColumnState(next); persist(next); };
    const reorderCols = (fromId, toId) => {
        if (!fromId || fromId === toId) return;
        setColumnState((prev) => {
            const fi = prev.findIndex((c) => c.id === fromId); const ti = prev.findIndex((c) => c.id === toId);
            if (fi < 0 || ti < 0) return prev;
            const next = [...prev];
            const [moved] = next.splice(fi, 1);
            next.splice(ti, 0, moved);
            persist(next);
            return next;
        });
    };
    const resetCols = () => {
        const next = defaultColumnState();
        setColumnState(next);
        try { localStorage.removeItem(storageKey); } catch { /* ignore */ }
        return next;
    };

    const options = useMemo(() => {
        const out = {};
        for (const { key } of PILL_FIELDS) {
            out[key] = [...new Set(details.map((r) => r[key]).filter((v) => v !== null && v !== undefined && v !== ''))].sort((a, b) => String(a).localeCompare(String(b)));
        }
        return out;
    }, [details]);

    const rows = useMemo(() => {
        let out = details;
        const s = q.trim().toLowerCase();
        if (s) {
            out = out.filter((r) => `${r.lwrId} ${r.company ?? ''} ${r.principal ?? ''} ${r.productName ?? ''} ${r.status ?? ''} ${r.creator ?? ''} ${r.sales ?? ''} ${r.projectTitle ?? ''} ${r.colour ?? ''}`.toLowerCase().includes(s));
        }
        for (const { key } of PILL_FIELDS) {
            if (pillVals[key]) out = out.filter((r) => String(r[key] ?? '') === String(pillVals[key]));
        }
        if (pillVals.dateFrom) out = out.filter((r) => r.tanggal && r.tanggal >= pillVals.dateFrom);
        if (pillVals.dateTo) out = out.filter((r) => r.tanggal && r.tanggal <= pillVals.dateTo);
        if (sort.key) {
            const def = colDefById.get(sort.key);
            out = [...out].sort((a, b) => {
                if (def?.numeric) return sort.dir === 'asc' ? (Number(a[sort.key]) || 0) - (Number(b[sort.key]) || 0) : (Number(b[sort.key]) || 0) - (Number(a[sort.key]) || 0);
                const av = String(a[sort.key] ?? '').toLowerCase(); const bv = String(b[sort.key] ?? '').toLowerCase();
                return sort.dir === 'asc' ? av.localeCompare(bv) : bv.localeCompare(av);
            });
        }
        return out;
    }, [details, q, pillVals, sort, colDefById]);

    // The same filter state, keyed as LabWorkRequestController::applyLwrDetailExportFilters()
    // reads it, so the workbook covers what the table covers. `pillVals` already uses the
    // server's key names (status/company/division/industry/sales/creator/principal/
    // productName/dateFrom/dateTo), so it passes straight through — only blanks are dropped.
    const exportParams = useMemo(() => Object.fromEntries(Object.entries({
        ...pillVals,
        search: q.trim(),
    }).filter(([, v]) => v !== '' && v !== null && v !== undefined)), [pillVals, q]);

    // Client-side pagination over the filtered/sorted set; reset to page 1 on any change.
    useEffect(() => { setPage(1); }, [q, pillVals, sort, perPage]);
    const totalPages = Math.max(1, Math.ceil(rows.length / perPage));
    const currentPage = Math.min(page, totalPages);
    const pageRows = useMemo(() => rows.slice((currentPage - 1) * perPage, currentPage * perPage), [rows, currentPage, perPage]);

    const onSort = (colId) => setSort((prev) => prev.key === colId ? { key: colId, dir: prev.dir === 'asc' ? 'desc' : 'asc' } : { key: colId, dir: 'asc' });
    const setPill = (key, val) => { setPillVals((p) => ({ ...p, [key]: val })); setActivePill(null); };
    const setDates = (from, to) => { setPillVals((p) => ({ ...p, dateFrom: from, dateTo: to })); setActivePill(null); };
    const togglePill = (key) => setActivePill(activePill === key ? null : key);
    // Drill into THIS variant's detail route so the server re-checks this report's own
    // menu grant + scope (lwrs.show gates on /lwrs + owner and 403s report readers).
    const open = (lwrId) => router.visit(route('lwrs.view-details.show', { id: lwrId, view }));

    // Sticky-column divider appears only while scrolled horizontally.

    const { scrollRef, shadowClass } = useStickyColShadow();

    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>Lab Work Request</span><span aria-hidden="true">›</span><span className="text-foreground">{title}</span>
                </p>
                <h1 className="m-0 text-xl font-bold leading-[1.2] text-card-foreground">{title}</h1>
            </header>

            {activePill && <div className="fixed inset-0 z-49" onClick={() => setActivePill(null)} />}

            <article className="overflow-hidden rounded-2xl border border-border bg-card shadow-sm">
                <div 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 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, Status…" 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>
                    {/* ⚙ 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}>

                    <div className="flex flex-wrap items-center gap-2.5">
                        {PILL_FIELDS.map((f) => (
                            <SelectPill key={f.key} label={f.label} value={pillVals[f.key] || ''} options={options[f.key] || []}
                                open={activePill === f.key} onToggle={() => togglePill(f.key)} onPick={(v) => setPill(f.key, v)} />
                        ))}
                        <DateRangePill label="Tanggal" from={pillVals.dateFrom} to={pillVals.dateTo}
                            open={activePill === 'dateRange'} onToggle={() => togglePill('dateRange')} onApply={setDates} />
                        {(q || Object.values(pillVals).some(Boolean)) && (
                            <button type="button" onClick={() => { setQ(''); setPillVals({}); setActivePill(null); }}
                                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>

                    <div className="ml-auto inline-flex items-center gap-2">
                        <ExportButton specKey={EXPORT_SPEC} url={exportUrl} params={exportParams} 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 ref={scrollRef} className={cn(SCROLL_SHADOW, 'max-h-[62vh] overflow-y-auto')}>
                        <table style={{ width: tableWidth }} className={cn(TABLE_CLASS, shadowClass)}>
                            <colgroup>
                                {visibleCols.map((col) => <col key={col.id} style={{ width: widthOf(col.id) }} />)}
                                {drillIn && <col style={{ width: widthOf('__action') }} />}
                            </colgroup>
                            <thead>
                                <tr>
                                    {visibleCols.map((col) => {
                                        const sortable = col.sortable !== false;
                                        return (
                                            <th key={col.id} draggable
                                                onDragStart={(e) => { if (resizeRef.current) { e.preventDefault(); return; } setDragColId(col.id); }}
                                                onDragOver={(e) => { e.preventDefault(); setDragOverColId(col.id); }}
                                                onDrop={() => { reorderCols(dragColId, col.id); setDragColId(null); setDragOverColId(null); }}
                                                onDragEnd={() => { setDragColId(null); setDragOverColId(null); }}
                                                className={cn(col.sticky && 'col-name', col.numeric && 'text-right', dragColId === col.id && 'opacity-45',
                                                    dragOverColId === col.id && dragColId !== col.id && 'bg-accent text-primary',
                                                    'group/col relative cursor-grab select-none active:cursor-grabbing')}>
                                                {sortable ? (
                                                    <button type="button" onClick={() => onSort(col.id)} className="inline-flex items-center gap-1 border-none bg-transparent p-0 text-left font-[inherit] text-[inherit]">
                                                        <span>{col.label}</span>
                                                        {sort.key === col.id
                                                            ? (sort.dir === 'asc' ? <ArrowUp className="size-3 text-muted-foreground" /> : <ArrowDown className="size-3 text-muted-foreground" />)
                                                            : <ChevronsUpDown className="size-3 opacity-40" />}
                                                    </button>
                                                ) : <span className="align-middle">{col.label}</span>}
                                                <ColumnResizeGrip onMouseDown={(e) => startResize(e, col.id)} active={resizingId === col.id} />
                                            </th>
                                        );
                                    })}
                                    {drillIn && (
                                        <th className="group/col relative !text-right">
                                            Action
                                            <ColumnResizeGrip onMouseDown={(e) => startResize(e, '__action')} active={resizingId === '__action'} />
                                        </th>
                                    )}
                                </tr>
                            </thead>
                            <tbody>
                                {rows.length === 0 ? (
                                    <tr><td colSpan={visibleCols.length + (drillIn ? 1 : 0)} className="py-10 !text-center text-[13px] text-muted-foreground">{q ? 'No detail lines match your filters.' : 'No detail lines found.'}</td></tr>
                                ) : pageRows.map((r, i) => (
                                    <tr key={r.detailId} onClick={drillIn ? () => open(r.lwrId) : undefined} className={cn(drillIn && 'cursor-pointer')}>
                                        {visibleCols.map((col) => (
                                            <td key={col.id} className={cn(col.sticky && 'col-name', col.numeric && '!text-right tabular-nums', col.cellClass)}>
                                                {renderCell(r, col.id, (currentPage - 1) * perPage + i + 1)}
                                            </td>
                                        ))}
                                        {drillIn && (
                                            <td className="!text-right">
                                                <button type="button" onClick={(e) => { e.stopPropagation(); open(r.lwrId); }}
                                                    className="group/link inline-flex items-center gap-1 text-[12px] font-bold text-primary transition-colors hover:underline">
                                                    Details <Caret className="size-3.5 transition-transform duration-200 group-hover/link:translate-x-0.5" aria-hidden="true" />
                                                </button>
                                            </td>
                                        )}
                                    </tr>
                                ))}
                            </tbody>
                        </table>
                    </div>

                    <ListFooter page={currentPage} totalPages={totalPages} onPage={setPage}
                        pageSize={perPage} onPageSize={(n) => { setPerPage(n); setPage(1); }}
                        pageSizeOptions={PER_PAGE_OPTIONS} total={rows.length} itemLabel="entries"
                        className="border-t-0" />
                </div>
            </article>

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

LwrViewDetailsList.layout = [AppLayout];
