import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Link, router } from '@inertiajs/react';
import { ArrowDown, ArrowUp, ChevronDown, ChevronsUpDown, Package, Search, Settings, Pin } from 'lucide-react';
import AppLayout from '@/Layouts/AppLayout';
import { cn } from '@/lib/utils';
import { CreateActionButton } from '@/Components/Table/CreateActionButton';
import { Input } from '@/Components/ui/input';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/Components/ui/table';
import { ListFooter } from '@/Components/Table/ListFooter';
import { StatusBadge } from '@/Components/Proto/UI/StatusBadge';
import { CustomizeColumnsModal } from '@/Components/Proto/Modals/CustomizeColumnsModal';
import { sampleOrderViewMeta } from '@/lib/sampleOrderViews';
import { statusTone } from '@/lib/sampleOrderStatusTones';
import { SelectPill, DateRangePill } from '@/Components/MenuQuotations/QuotationListPage/QuotationListPills';
import { useResizableColumns, ColumnResizeGrip } from '@/lib/useResizableColumns';

// Filter pills shown above the list — server-side selects (Quotation-list format).
const ALL_PILLS = [
    { key: 'status', label: 'Status', opt: 'statuses' },
    { key: 'division', label: 'Division', opt: 'divisions' },
    { key: 'industry', label: 'Industry', opt: 'industries' },
    { key: 'priority', label: 'Priority', opt: 'priorities' },
    { key: 'delivery', label: 'Delivery', opt: 'deliveries' },
    { key: 'sales', label: 'Sales', opt: 'sales' },
    { key: 'creator', label: 'Creator', opt: 'creators' },
];
// Only the Request view hides the Sales + Creator pills (user decision 2026-06-30);
// every other view (head, sm, all, …) keeps them. All views share the Project search +
// Tanggal date-range filters.
// Sample List cell — a compact "N samples" chip that reveals the full list on hover
// (click toggles/pins), so one row never towers over the rest. Same pattern as the
// Netsuite Approval CEO "Product List" column.
/**
 * Two ways to read the same lines (user request 2026-08-20):
 *
 *   'compact' — a "N samples" pill; hover previews, click pins. Keeps the row one line tall,
 *               which is what makes a 16-column list scannable.
 *   'full'    — every product printed in the cell. Costs row height, but answers "what is in
 *               these orders" without touching anything.
 *
 * The choice lives in the ⚙ Customize columns modal, beside the column it affects.
 */
function SampleListCell({ items, mode = 'compact' }) {
    const [pos, setPos] = useState(null);
    const [pinned, setPinned] = useState(false);
    const ref = useRef(null);
    const pinnedRef = useRef(false);
    const timer = useRef(null);
    
    pinnedRef.current = pinned;

    useEffect(() => () => { if (timer.current) clearTimeout(timer.current); }, []);

    useEffect(() => {
        if (!pinned) return undefined;
        const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) { setPinned(false); setPos(null); } };
        const onEsc = (e) => { if (e.key === 'Escape') { setPinned(false); setPos(null); } };
        document.addEventListener('mousedown', onDoc);
        document.addEventListener('keydown', onEsc);
        return () => { document.removeEventListener('mousedown', onDoc); document.removeEventListener('keydown', onEsc); };
    }, [pinned]);

    if (!items?.length) return <span className="text-muted-foreground">—</span>;

    if (mode === 'full') {
        // Every item is EXACTLY two truncated lines separated by a hairline. Letting the text
        // wrap freely made each row a different height and broke names mid-word
        // ("CRAYVALLAC / EXTRA", "0.01 gram · / Foundation"), so a three-item cell read as six
        // ragged fragments. The full text stays reachable in `title`.
        return (
            <ul className="m-0 flex list-none flex-col divide-y divide-border/40 p-0">
                {items.map((p, i) => {
                    const meta = [
                        [p.qty, p.satuan].filter(Boolean).join(' '),
                        p.application,
                    ].filter(Boolean).join(' · ');

                    return (
                        <li key={i} className="min-w-0 py-1 leading-snug first:pt-0 last:pb-0">
                            <span className="block truncate text-[12px] font-semibold text-foreground" title={p.productName}>
                                {p.productName}
                            </span>
                            {meta && (
                                <span className="block truncate text-[11px] text-muted-foreground" title={meta}>{meta}</span>
                            )}
                        </li>
                    );
                })}
            </ul>
        );
    }


    const width = 300;
    const computePos = (el) => {
        const r = el.getBoundingClientRect();
        const left = Math.max(8, Math.min(r.left, window.innerWidth - width - 8));
        const spaceBelow = window.innerHeight - r.bottom - 12;
        const spaceAbove = r.top - 12;
        if (spaceBelow < 260 && spaceAbove > spaceBelow) {
            return { left, bottom: window.innerHeight - r.top + 6, maxH: Math.max(140, Math.min(320, spaceAbove)) };
        }
        return { left, top: r.bottom + 6, maxH: Math.max(140, Math.min(320, spaceBelow)) };
    };

    const cancelClose = () => { if (timer.current) { clearTimeout(timer.current); timer.current = null; } };
    const scheduleClose = () => { cancelClose(); timer.current = setTimeout(() => { if (!pinnedRef.current) setPos(null); }, 150); };
    const onEnter = (e) => { cancelClose(); if (!pinnedRef.current) setPos(computePos(e.currentTarget)); };
    const onClick = (e) => {
        e.stopPropagation();
        cancelClose();
        if (pinned) { setPinned(false); setPos(null); return; }
        const next = computePos(e.currentTarget);
        setPinned(true);
        setPos(next);
    };

    return (
        <div ref={ref} className="relative flex items-center gap-2">
            <button type="button" onMouseEnter={onEnter} onMouseLeave={scheduleClose} onClick={onClick}
                className={`inline-flex shrink-0 items-center gap-1.5 rounded-full border px-2.5 py-0.5 text-[11px] font-semibold tabular-nums transition-colors ${pos ? 'border-primary text-primary' : 'border-border bg-card text-muted-foreground hover:border-primary hover:text-primary'}`}>
                <Package className="size-3" aria-hidden="true" /> {items.length} sample{items.length !== 1 ? 's' : ''}
                <ChevronDown className={`size-3 transition-transform ${pos ? 'rotate-180' : ''}`} aria-hidden="true" />
            </button>
            {pos && (
                <div onMouseEnter={cancelClose} onMouseLeave={scheduleClose} onClick={(e) => e.stopPropagation()}
                    className="fixed z-[100] rounded-lg border border-border bg-card p-2.5 text-left shadow-modal"
                    style={{ left: pos.left, top: pos.top, bottom: pos.bottom, width, maxWidth: '85vw' }}>
                    <div className="mb-1.5 flex items-center justify-between gap-2 border-b border-border/60 pb-1.5">
                        <span className="text-[10px] font-bold uppercase tracking-wide text-muted-foreground">Sample List ({items.length})</span>
                        {pinned && (
                            <span className="inline-flex items-center gap-0.5 text-[9px] font-semibold text-primary">
                                <Pin className="size-2.5" aria-hidden="true" />Pinned
                            </span>
                        )}
                    </div>
                    <ul className="m-0 flex flex-col gap-2 overflow-y-auto pr-1" style={{ maxHeight: pos.maxH }}>
                        {items.map((p, i) => (
                            <li key={i} className="border-b border-border/50 pb-2 leading-snug last:border-b-0 last:pb-0">
                                <p className="m-0 text-[12px] font-bold text-foreground">{p.productName}</p>
                                <p className="m-0 text-[11px] text-muted-foreground">Qty: {p.qty}{p.satuan ? ` ${p.satuan}` : ''}{p.application ? ` · ${p.application}` : ''}</p>
                            </li>
                        ))}
                    </ul>
                </div>
            )}
        </div>
    );
}

const pillsForView = (view) => view === 'request'
    ? ALL_PILLS.filter((p) => p.key !== 'sales' && p.key !== 'creator')
    : ALL_PILLS;

const COLUMN_GROUPS = [
    { id: 'identifiers', label: 'Identifiers' },
    { id: 'metadata', label: 'Metadata' },
    { id: 'order', label: 'Order & Dates' },
];
// Order = default display order: SO No leads (the row anchor people quote), then the
// working set; metadata columns exist but start hidden — Customize turns them on.
const COLUMN_DEFS = [
    { id: 'id', label: 'SO No', groupId: 'identifiers', required: true },
    { id: 'company', label: 'Company Name', groupId: 'identifiers', required: true },
    { id: 'status', label: 'SO Status', groupId: 'identifiers' },
    { id: 'sampleList', label: 'Sample List', groupId: 'order' },
    { id: 'project', label: 'Project', groupId: 'order' },
    { id: 'delivery', label: 'Delivery', groupId: 'order' },
    { id: 'feedback', label: 'Feedback Status', groupId: 'identifiers' },
    { id: 'tanggal', label: 'Tanggal', groupId: 'order' },
    { id: 'creator', label: 'Creator', groupId: 'metadata' },
    { id: 'sales', label: 'Sales', groupId: 'metadata' },
    { id: 'division', label: 'Division', groupId: 'metadata' },
    { id: 'industry', label: 'Industry', groupId: 'metadata' },
    { id: 'priority', label: 'Priority', groupId: 'metadata' },
    { id: 'sampleOrderBy', label: 'SO By', groupId: 'order' },
    { id: 'tanggalSOBy', label: 'Date SO By', groupId: 'order' },
    { id: 'comment', label: 'Comment', groupId: 'order' },
];
// Default per-column pixel widths for the resizable table-fixed layout (overridable by drag).
// Widths sized to typical content (2026-07-17 pass): delivery fits its most common
// value ("Along with Order Delivery") untruncated; date/name/pill columns trimmed to
// their real footprint. Users fine-tune by dragging a header's right edge.
const COL_W = {
    id: 90, company: 175, status: 130, feedback: 150,
    creator: 110, sales: 140, division: 100, industry: 175, priority: 100,
    tanggal: 110, sampleOrderBy: 130, tanggalSOBy: 120, delivery: 165,
    project: 170, comment: 190, sampleList: 120,
};
const COL_W_FALLBACK = 140;
// All 16 columns show by default (user decision 2026-07-17) — users hide their own via ⚙.
const DEFAULT_VISIBLE = new Set(COLUMN_DEFS.map((c) => c.id));
// Columns hidden by default for specific views only (other views keep them visible).
const HIDDEN_BY_VIEW = { sm: new Set(['feedback']) }; // 'sm' = the /sample-orders/view-sm route's view value
const isDefaultVisible = (id, view) => DEFAULT_VISIBLE.has(id) && !HIDDEN_BY_VIEW[view]?.has(id);
const defaultColumnState = (view) => COLUMN_DEFS.map((d) => ({ id: d.id, visible: isDefaultVisible(d.id, view) }));
const STORAGE_KEY = 'sampleOrderColumnsState_v4';
function loadStoredState(storageKey, view) {
    try {
        const raw = localStorage.getItem(storageKey);
        if (!raw)
            return defaultColumnState(view);
        const parsed = JSON.parse(raw);
        const ids = new Set(parsed.map((c) => c.id));
        COLUMN_DEFS.forEach((d) => { if (!ids.has(d.id))
            parsed.push({ id: d.id, visible: isDefaultVisible(d.id, view) }); });
        return parsed;
    }
    catch {
        return defaultColumnState(view);
    }
}

const SORTABLE = new Set(['id', 'company', 'status', 'feedback', 'creator', 'sales', 'division', 'industry', 'priority', 'tanggal', 'sampleOrderBy', 'tanggalSOBy', 'delivery', 'project', 'comment']);
const CELL = 'overflow-hidden whitespace-nowrap px-[14px] py-[16px] align-middle text-[12px] text-foreground first:pl-7 last:pr-5';

const isBlankDate = (v) => !v || v === '0000-00-00';

const EMPTY_PAGINATOR = { data: [], current_page: 1, last_page: 1, per_page: 10, from: 0, to: 0, total: 0 };

export default function SampleOrdersList({ sampleOrders = EMPTY_PAGINATOR, filters = {}, filterOptions = {}, view = 'all', canCreate = true, canCreateSalesAdmin = false }) {
    const meta = sampleOrderViewMeta(view);
    // Per-view column customization — 'all' keeps the original key (back-compat).
    const storageKey = view === 'all' ? STORAGE_KEY : `${STORAGE_KEY}_${view}`;
    const filterPills = pillsForView(view);
    const rows = sampleOrders.data;
    const sortKey = filters.sort || 'id';
    const sortDir = filters.dir || 'desc';
    const pageSize = filters.per_page || 10;

    const [quickQuery, setQuickQuery] = useState(filters.search || '');
    const [columnState, setColumnState] = useState(() => loadStoredState(storageKey, view));
    const [customizeOpen, setCustomizeOpen] = useState(false);

    // Persisted beside the column prefs it belongs to, and read lazily so the first paint is
    // already right. try/catch: private mode makes localStorage throw, not return null.
    const [sampleListMode, setSampleListMode] = useState(() => {
        try { return localStorage.getItem('sampleListMode_v1') === 'full' ? 'full' : 'compact'; }
        catch { return 'compact'; }
    });
    const applySampleListMode = (m) => {
        setSampleListMode(m);
        try { localStorage.setItem('sampleListMode_v1', m); } catch { /* private mode */ }
    };
    const [dragColIdx, setDragColIdx] = useState(null);
    const [dragOverColIdx, setDragOverColIdx] = useState(null);
    const searchDebounce = useRef(null);
    const projectDebounce = useRef(null);
    const [projectQuery, setProjectQuery] = useState(filters.project || '');
    const [dateStart, setDateStart] = useState(filters.date_start || '');
    const [dateEnd, setDateEnd] = useState(filters.date_end || '');

    const visibleCols = useMemo(() => columnState
        .filter((c) => c.visible)
        .map((c) => COLUMN_DEFS.find((d) => d.id === c.id))
        .filter(Boolean), [columnState]);

    // Resizable columns — drag a header's right edge (matches approval-pm quotation).
    const { widthOf, startResize, resizingId, resizeRef } = useResizableColumns(COL_W, COL_W_FALLBACK);
    // Full mode prints product names, so the 120px compact width truncates almost everything.
    // Math.max, not a replacement: a column the user dragged wider must stay where they put it.
    // useResizableColumns snapshots its defaults on first render, so the floor is applied here
    // rather than by swapping the COL_W map.
    const colWidth = useCallback(
        (id) => (id === 'sampleList' && sampleListMode === 'full' ? Math.max(widthOf(id), 210) : widthOf(id)),
        [widthOf, sampleListMode],
    );
    const tableWidth = useMemo(() => visibleCols.reduce((s, c) => s + colWidth(c.id), 0), [visibleCols, colWidth]);

    const buildParams = (overrides = {}) => {
        const search = overrides.search ?? quickQuery;
        const sort = overrides.sort ?? sortKey;
        const dir = overrides.dir ?? sortDir;
        const perPage = overrides.per_page ?? pageSize;
        const page = overrides.page ?? sampleOrders.current_page;
        const project = overrides.project ?? projectQuery;
        const dateS = overrides.date_start ?? dateStart;
        const dateE = overrides.date_end ?? dateEnd;
        const params = {};
        if (search) params.search = search;
        if (sort && sort !== 'id') params.sort = sort;
        if (dir && dir !== 'desc') params.dir = dir;
        if (perPage && Number(perPage) !== 10) params.per_page = perPage;
        if (page && Number(page) !== 1) params.page = page;
        filterPills.forEach(({ key }) => {
            const v = overrides[key] ?? filters[key] ?? '';
            if (v) params[key] = v;
        });
        if (project) params.project = project;
        if (dateS) params.date_start = dateS;
        if (dateE) params.date_end = dateE;
        return params;
    };
    // only: — without it the server still evaluates the filterOptions closure, re-running
    // its seven DISTINCT scans on every keystroke and every page click. `filters` MUST be
    // in the list: sort arrows and rows-per-page read it, not local state.
    const go = (overrides) => router.get(route(meta.indexRoute), buildParams(overrides), {
        only: ['sampleOrders', 'filters'],
        preserveState: true, preserveScroll: true, replace: true,
    });

    // Filter pills (quotation-list format): one open at a time, click-outside closes.
    const [openPill, setOpenPill] = useState(null);
    const filterBarRef = 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 setFilter = (key, value) => { setOpenPill(null); go({ [key]: value, page: 1 }); };
    const activeFilterCount = filterPills.reduce((n, { key }) => n + (filters[key] ? 1 : 0), 0)
        + (filters.project ? 1 : 0)
        + ((filters.date_start || filters.date_end) ? 1 : 0);
    const clearFilters = () => {
        setOpenPill(null);
        setProjectQuery('');
        setDateStart('');
        setDateEnd('');
        go(Object.fromEntries([
            ...filterPills.map(({ key }) => [key, '']),
            ['project', ''], ['date_start', ''], ['date_end', ''], ['page', 1],
        ]));
    };

    const onSearchChange = (val) => {
        setQuickQuery(val);
        clearTimeout(searchDebounce.current);
        searchDebounce.current = setTimeout(() => go({ search: val, page: 1 }), 300);
    };

    const onProjectChange = (val) => {
        setProjectQuery(val);
        clearTimeout(projectDebounce.current);
        projectDebounce.current = setTimeout(() => go({ project: val, page: 1 }), 350);
    };
    const onDateChange = (which, val) => {
        if (which === 'start') setDateStart(val);
        else setDateEnd(val);
        go({ [which === 'start' ? 'date_start' : 'date_end']: val, page: 1 });
    };

    const onSort = (key) => {
        let dir;
        if (sortKey === key)
            dir = sortDir === 'asc' ? 'desc' : 'asc';
        else
            dir = key === 'id' ? 'desc' : 'asc';
        go({ sort: key, dir, page: 1 });
    };

    const handleApplyColumns = (next) => {
        setColumnState(next);
        try {
            localStorage.setItem(storageKey, JSON.stringify(next));
        }
        catch { }
    };
    const handleResetColumns = () => {
        const def = defaultColumnState(view);
        try {
            localStorage.removeItem(storageKey);
        }
        catch { }
        // "Reset to default" must reset EVERYTHING the modal owns, and it now owns the Sample
        // List display mode too. Leaving the mode behind made the button lie: the columns went
        // back to default while the cells stayed in Show-all.
        applySampleListMode('compact');
        return def;
    };
    const reorderColumns = (fromIdx, toIdx) => {
        if (fromIdx === null || fromIdx === toIdx) return;
        const fromId = visibleCols[fromIdx]?.id;
        const toId   = visibleCols[toIdx]?.id;
        if (!fromId || !toId) return;
        setColumnState(prev => {
            const next = [...prev];
            const fi = next.findIndex(c => c.id === fromId);
            const ti = next.findIndex(c => c.id === toId);
            const [moved] = next.splice(fi, 1);
            next.splice(ti, 0, moved);
            try { localStorage.setItem(storageKey, JSON.stringify(next)); } catch {}
            return next;
        });
    };

    const renderCell = (so, colId) => {
        switch (colId) {
            case 'id': return <strong className="font-bold text-primary tabular-nums">#{so.id}</strong>;
            case 'company': return so.company ? <span className="font-semibold text-foreground">{so.company}</span> : '—';
            case 'status': return so.status ? <StatusBadge tone={statusTone(so.status)}>{so.status}</StatusBadge> : '—';
            case 'division': return so.division ? <span className="inline-flex items-center rounded-full bg-secondary px-2 py-0.5 text-[10px] font-bold uppercase text-muted-foreground">{so.division}</span> : '—';
            case 'feedback': return so.feedback ? <span className="text-muted-foreground">{so.feedback}</span> : '—';
            case 'creator': return so.creator || '—';
            case 'sales': return so.sales || '—';
            case 'industry': return so.industry ? <span className="text-muted-foreground">{so.industry}</span> : '—';
            case 'priority': return so.priority ? <span className="text-muted-foreground">{so.priority}</span> : '—';
            case 'tanggal': return isBlankDate(so.tanggal) ? '—' : <span className="tabular-nums text-muted-foreground">{so.tanggal}</span>;
            case 'sampleOrderBy': return so.sampleOrderBy || '—';
            case 'tanggalSOBy': return isBlankDate(so.tanggalSOBy) ? '—' : <span className="tabular-nums text-muted-foreground">{so.tanggalSOBy}</span>;
            case 'delivery': return so.delivery ? <span className="text-muted-foreground" title={so.delivery}>{so.delivery}</span> : '—';
            case 'project': return so.project ? <span title={so.project}>{so.project}</span> : '—';
            case 'comment': return so.comment ? <span className="text-muted-foreground" title={so.comment}>{so.comment}</span> : '—';
            case 'sampleList': return <SampleListCell items={so.sampleList || []} mode={sampleListMode} />;
            default: return '—';
        }
    };

    const totalPages = sampleOrders.last_page;
    const currentPage = sampleOrders.current_page;

    return (
        <section className="flex min-w-0 flex-col gap-[18px]">
            <header className="flex items-center justify-between gap-4">
                <div>
                    <p className="mb-1.5 flex items-center gap-2 text-xs font-semibold text-muted-foreground">
                        <Link href={route(meta.indexRoute)} className="no-underline hover:text-primary">Sample Orders</Link>
                        <span aria-hidden="true">›</span>
                        <span className="text-foreground">{meta.label}</span>
                    </p>
                    <h1 className="text-xl font-bold leading-tight text-foreground">{meta.label}</h1>
                </div>
                <CreateActionButton
                    canCreate={canCreate}
                    label="New sample order"
                    href={route('sample-orders.create')}
                    variants={[{ key: 'salesadmin', label: 'Sales Admin', can: canCreateSalesAdmin, href: route('sample-orders.create-sales-admin') }]}
                />
            </header>

            <div className="rounded-2xl border border-border bg-card px-5 pt-[18px] shadow-sm">
                {/* Toolbar (matches the Quotation list): search far left, then filter
                    pills, then Customize on the right. */}
                <div ref={filterBarRef} className="flex flex-wrap items-center gap-2.5 -mx-5 border-b border-border/50 px-5 pb-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" aria-label="Search sample orders">
                        <Search aria-hidden="true" className="size-3.5 shrink-0" />
                        <input
                            type="search"
                            placeholder="Search SO No, company, project…"
                            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>
                    {filterPills.map(({ key, label, opt }) => (
                        <SelectPill
                            key={key}
                            label={label}
                            value={filters[key] || ''}
                            options={filterOptions[opt] || []}
                            open={openPill === key}
                            onToggle={() => setOpenPill(openPill === key ? null : key)}
                            onPick={(v) => setFilter(key, v)}
                        />
                    ))}
                    <DateRangePill
                        label="Tanggal"
                        from={dateStart}
                        to={dateEnd}
                        open={openPill === 'dates'}
                        onToggle={() => setOpenPill(openPill === 'dates' ? null : 'dates')}
                        onApply={(from, to) => { setDateStart(from); setDateEnd(to); setOpenPill(null); go({ date_start: from, date_end: to, page: 1 }); }}
                    />
                    {activeFilterCount > 0 && (
                        <button type="button" onClick={clearFilters} className="text-[12px] font-semibold text-primary hover:underline">Clear all</button>
                    )}
                    <button
                        type="button"
                        onClick={() => setCustomizeOpen(true)}
                        title="Customize columns"
                        aria-label="Customize columns"
                        className="ml-auto grid size-7 place-items-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
                    >
                        <Settings aria-hidden="true" className="size-3.5" strokeWidth={2.5} />
                    </button>
                </div>

                {/* Table */}
                <Table className="w-full table-fixed mt-4" style={{ minWidth: tableWidth }}>
                    <colgroup>
                        {visibleCols.map((col) => <col key={col.id} style={{ width: colWidth(col.id) }} />)}
                    </colgroup>
                    <TableHeader className="[&_tr]:border-b-0">
                        <TableRow className="border-0 hover:bg-transparent">
                            {visibleCols.map((col, i) => {
                                const k = SORTABLE.has(col.id) ? col.id : null;
                                const isDragging = dragColIdx === i;
                                const isDragOver = dragOverColIdx === i && dragColIdx !== i;
                                return (
                                    <TableHead
                                        key={col.id}
                                        draggable
                                        onDragStart={(e) => { if (resizeRef.current) { e.preventDefault(); return; } setDragColIdx(i); }}
                                        onDragOver={(e) => { e.preventDefault(); setDragOverColIdx(i); }}
                                        onDrop={() => { reorderColumns(dragColIdx, i); setDragColIdx(null); setDragOverColIdx(null); }}
                                        onDragEnd={() => { setDragColIdx(null); setDragOverColIdx(null); }}
                                        className={cn(
                                            'group/col relative h-auto cursor-grab select-none whitespace-nowrap bg-secondary/50 py-2.5 pl-3.5 pr-[22px] text-[11px] font-semibold uppercase tracking-wide text-muted-foreground transition-colors first:rounded-l-full first:pl-7 last:rounded-r-full last:pr-5 active:cursor-grabbing',
                                            isDragging && 'opacity-45',
                                            isDragOver && 'bg-secondary text-foreground',
                                        )}
                                    >
                                        {k ? (
                                            <button type="button" onClick={() => onSort(k)} className="inline-flex items-center gap-1 bg-transparent p-0 align-middle font-[inherit] text-[inherit] uppercase">
                                                <span>{col.label}</span>
                                                {sortKey === k
                                                    ? (sortDir === '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} />
                                    </TableHead>
                                );
                            })}
                        </TableRow>
                    </TableHeader>
                    <TableBody>
                        {rows.length === 0 && (
                            <TableRow className="hover:bg-transparent">
                                <TableCell colSpan={visibleCols.length} className="px-7 py-10 text-center text-xs italic text-muted-foreground">No sample orders found.</TableCell>
                            </TableRow>
                        )}
                        {rows.map((so) => (
                            <TableRow
                                key={so.id}
                                onClick={() => router.visit(route(meta.showRoute, so.id))}
                                className="cursor-pointer border-b border-border/60 even:bg-secondary/25 hover:bg-secondary/60"
                            >
                                {visibleCols.map((col) => (
                                    <TableCell
                                        key={col.id}
                                        className={cn(CELL, col.id === 'sampleList' && 'overflow-visible text-foreground', col.id === 'sampleList' && sampleListMode === 'full' && '!whitespace-normal !align-top')}
                                    >
                                        {renderCell(so, col.id)}
                                    </TableCell>
                                ))}
                            </TableRow>
                        ))}
                    </TableBody>
                </Table>

                <ListFooter page={currentPage} totalPages={totalPages} onPage={(p) => go({ page: p })}
                    pageSize={Number(sampleOrders.per_page)} onPageSize={(n) => go({ per_page: n, page: 1 })}
                    pageSizeOptions={[5, 10, 15, 20]} total={sampleOrders.total} itemLabel="entries"
                    className="-mx-5 rounded-b-2xl border-t-0" />
            </div>

            <CustomizeColumnsModal open={customizeOpen} onClose={() => setCustomizeOpen(false)} groups={COLUMN_GROUPS} definitions={COLUMN_DEFS} state={columnState} onApply={handleApplyColumns} onReset={handleResetColumns}
                renderOption={(def) => def.id !== 'sampleList' ? null : (
                    <div className="flex items-center gap-1.5 rounded-md bg-secondary/50 p-1">
                        {[['compact', 'Compact (hover)'], ['full', 'Show all items']].map(([m, label]) => (
                            <button key={m} type="button" onClick={() => applySampleListMode(m)}
                                aria-pressed={sampleListMode === m}
                                className={cn(
                                    'flex-1 rounded px-2 py-1 text-[11px] font-bold transition-colors',
                                    sampleListMode === m
                                        ? 'bg-card text-primary shadow-sm'
                                        : 'text-muted-foreground hover:text-foreground',
                                )}>
                                {label}
                            </button>
                        ))}
                    </div>
                )} />
        </section>
    );
}

SampleOrdersList.layout = [AppLayout];
