import { useMemo, useState } from 'react';
import { TOOLBAR_GEAR, TOOLBAR_FILTERS } from '@/Components/Table';
import { Eye, Check, X, Search, Settings, HelpCircle, FolderKanban, Package, Users, FileText, Coins } from 'lucide-react';
import AppLayout from '@/Layouts/AppLayout';
import { CheckBox } from '@/Components/Proto/UI/CheckBox';
import { ListFooter } from '@/Components/Table/ListFooter';
import { AddFilterMenu, FilterPill } from '@/Components/ui/filter-pill';
import { CustomizeColumnsModal } from '@/Components/Proto/Modals/CustomizeColumnsModal';
import { Button } from '@/Components/ui/button';
import { router } from '@inertiajs/react';
import { STATUS_GUIDE, STATUS_FILTERS } from '@/Proto/companyProjectData';
import { NativeSelect } from '@/Components/ui/native-select';
import { useClientSort, SortButton } from '@/lib/ClientSort';
import { useToast } from '@/Components/Toast';
import { useResizableColumns, ColumnResizeGrip } from '@/lib/useResizableColumns';
import { SELECTED_TD, SELECTED_HOVER_TD } from '@/lib/rowTint';
import { DecisionBar } from '@/Components/MenuSampleOrders/DecisionBar';

const money = (n) => (Number(n) || 0).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
// Status dot colours — mirrors the Company Project Board legend (semantic:
// Exploring = neutral white, Sample = amber, Lab Testing = orange, Approved =
// green, Quotation = brand violet, Failed = red, Commercialized = green).
const STATUS_DOT = { Created: '#9ca3af', Exploring: '#ffffff', Sample: 'var(--color-warning)', 'Lab Testing': '#f97316', Approved: 'var(--color-success)', Quotation: 'var(--color-primary)', Failed: 'var(--color-danger)', Commercialized: '#16a34a' };
// Faint inner ring so a white/light dot stays visible on white surfaces (Board pattern).
const DOT_RING = 'inset 0 0 0 1px color-mix(in srgb, var(--color-card-foreground) 22%, transparent)';
// Priority accent colours (High/Important = amber, Very = red, else neutral).
const priorityDot = (p = '') => {
    const s = p.toLowerCase();
    if (s.includes('very')) return 'var(--color-danger)';
    if (s.includes('high') || s.includes('important')) return 'var(--color-warning)';
    return 'var(--color-muted-foreground)';
};
const CARD = 'rounded-2xl border border-border bg-card shadow-sm';
const TABLE = 'w-full border-separate border-spacing-0 text-foreground [&_thead_th]:whitespace-nowrap [&_thead_th]:bg-[color-mix(in_srgb,var(--color-secondary)_50%,var(--color-card))] [&_thead_th]:px-3.5 [&_thead_th]:py-2.5 [&_thead_th]:text-left [&_thead_th]:text-[11px] [&_thead_th]:font-semibold [&_thead_th]:uppercase [&_thead_th]:tracking-wide [&_thead_th]:text-muted-foreground [&_thead_th:first-child]:rounded-l-full [&_thead_th:first-child]:pl-4 [&_thead_th:last-child]:rounded-r-full [&_thead_th:last-child]:pr-4 [&_tbody_td]:overflow-hidden [&_tbody_td]:whitespace-nowrap [&_tbody_td]:border-b [&_tbody_td]:border-border/60 [&_tbody_td:first-child]:pl-4 [&_tbody_td:last-child]:pr-4 [&_tbody_td]:px-3.5 [&_tbody_td]:py-[16px] [&_tbody_td]:text-[12px] [&_tbody_tr:last-child_td]:border-b-0 [&_tbody_tr:nth-child(even)_td]:bg-secondary/25 [&_tbody_tr:hover_td]:bg-secondary/60';
const EMPTY_PILLS = { company: [], division: [], status: [], priority: [], industry: [], principal: [], product: [], application: [], creator: [] };

// Sortable columns — id → raw row value (house ClientSort pattern); ids match COLUMN_DEFS.
const SORT_GETTERS = {
    id: (l) => l.id,
    priority: (l) => l.priority,
    company: (l) => l.company,
    product: (l) => l.product,
    target: (l) => l.targetValue,
    status: (l) => l.status,
};
// Resizable-column default widths (table-fixed layout) — 'check'/'action' bracket the data cols.
const COL_W = { check: 48, id: 110, priority: 130, company: 220, product: 230, target: 170, status: 140, action: 120 };

// Data-driven columns (list grammar) — hide/reorder via the ⚙ Customize Columns modal.
const COLUMN_GROUPS = [{ id: 'main', label: 'Columns' }];
const COLUMN_DEFS = [
    { id: 'id', label: 'Project ID', groupId: 'main', required: true },
    { id: 'priority', label: 'Priority', groupId: 'main' },
    { id: 'company', label: 'Company / Division', groupId: 'main' },
    { id: 'product', label: 'Product / Principal', groupId: 'main' },
    { id: 'target', label: 'Target Value / Date', groupId: 'main' },
    { id: 'status', label: 'Status', groupId: 'main' },
];
const COLUMN_STORAGE_KEY = 'companyProjectApprovalPmColumns_v1';
const defaultColumnState = () => COLUMN_DEFS.map((d) => ({ id: d.id, visible: true }));
function loadColumnState() {
    try {
        const raw = localStorage.getItem(COLUMN_STORAGE_KEY);
        if (!raw) return defaultColumnState();
        const parsed = JSON.parse(raw).filter((c) => COLUMN_DEFS.some((d) => d.id === c.id));
        const ids = new Set(parsed.map((c) => c.id));
        COLUMN_DEFS.forEach((d) => { if (!ids.has(d.id)) parsed.push({ id: d.id, visible: true }); });
        return parsed;
    } catch {
        return defaultColumnState();
    }
}

// Coloured status/priority pill — tinted bg + accent text + dot (matches the guide colours).
function Pill({ color, children }) {
    const accent = color === '#ffffff' ? 'var(--color-muted-foreground)' : color;
    return (
        <span className="inline-flex items-center gap-1.5 whitespace-nowrap rounded-full py-[3px] pl-2 pr-2.5 text-[11px] font-semibold" style={{ color: accent, background: `color-mix(in srgb, ${accent} 14%, transparent)` }}>
            <span className="size-1.5 shrink-0 rounded-full" style={{ background: color, boxShadow: DOT_RING }} />
            {children}
        </span>
    );
}

// Expected value with an optional muted "current" suffix.
function Dual({ exp, cur }) {
    return <span className="tabular-nums">{exp}{cur ? <span className="text-muted-foreground"> · cur {cur}</span> : null}</span>;
}

// Drawer section block with icon header.
function Section({ icon: Icon, title, children }) {
    return (
        <section>
            <div className="mb-2 flex items-center gap-2">
                <span className="grid size-6 place-items-center rounded-md bg-accent text-primary"><Icon className="size-3.5" /></span>
                <h3 className="m-0 text-[11px] font-bold uppercase tracking-wide text-muted-foreground">{title}</h3>
            </div>
            {children}
        </section>
    );
}

// Definition row inside a drawer section.
function Row({ label, children }) {
    return (
        <div className="flex items-baseline justify-between gap-3 border-b border-border/40 py-1.5 last:border-0">
            <span className="shrink-0 text-[12px] text-muted-foreground">{label}</span>
            <span className="min-w-0 truncate text-right text-[13px] font-semibold text-foreground" title={typeof children === 'string' ? children : undefined}>{children}</span>
        </div>
    );
}

export default function ProjectApprovalPm({ lines = [], scoped = true, filterOptions = {} }) {
    const { show: showToast } = useToast();
    // Server ships one row per pending CC line; derive line-level filter option lists
    // from the shipped set (client-side filter/paginate over the scoped queue, like the proto).
    const LINES = lines;
    const distinct = (key) => [...new Set(lines.map((l) => l[key]).filter(Boolean))].sort((a, b) => String(a).localeCompare(String(b)));
    const OPT = {
        companies: (filterOptions.companies || []).map((c) => c.CompanyName),
        divisions: (filterOptions.divisions || []).map((d) => d.DivisionName),
        industries: (filterOptions.industries || []).map((i) => i.IndustryName),
        principals: distinct('producer'),
        products: distinct('product'),
        applications: distinct('application'),
        creators: distinct('creator'),
        priorities: distinct('priority'),
    };
    const [guideOpen, setGuideOpen] = useState(false);
    // Toolbar filters — instant apply (list grammar), no Search/Apply step.
    const [q, setQ] = useState('');
    const [pills, setPills] = useState(EMPTY_PILLS);
    const [extras, setExtras] = useState([]);
    const [selected, setSelected] = useState(new Set());
    const [sort, setSort] = useState('newest');
    const [page, setPage] = useState(1);
    const [perPage, setPerPage] = useState(10);
    const [detail, setDetail] = useState(null);
    const [confirmA, setConfirmA] = useState(null); // { action: 'Approve'|'Reject', items: line[] }
    const [modalComment, setModalComment] = useState('');
    // Column order/visibility — persisted per page, edited via the ⚙ modal.
    const [columnState, setColumnState] = useState(loadColumnState);
    const [showColumns, setShowColumns] = useState(false);
    const visibleCols = columnState
        .map((c) => ({ c, d: COLUMN_DEFS.find((d) => d.id === c.id) }))
        .filter(({ c, d }) => d && (d.required || c.visible))
        .map(({ d }) => d);
    const applyColumns = (next) => { setColumnState(next); try { localStorage.setItem(COLUMN_STORAGE_KEY, JSON.stringify(next)); } catch { /* private mode */ } };
    const resetColumns = () => { try { localStorage.removeItem(COLUMN_STORAGE_KEY); } catch { /* private mode */ } const d = defaultColumnState(); setColumnState(d); return d; };

    const setPill = (k, v) => { setPills((p) => ({ ...p, [k]: v })); setPage(1); };
    const removeExtra = (k) => { setExtras((e) => e.filter((x) => x !== k)); setPill(k, []); };
    const resetFilters = () => { setQ(''); setPills(EMPTY_PILLS); setExtras([]); setPage(1); };
    const activeFilterCount = (q.trim() ? 1 : 0) + Object.values(pills).filter((v) => v.length > 0).length;

    const coreFields = [
        { key: 'company', label: 'Company', opts: OPT.companies },
        { key: 'division', label: 'Division', opts: OPT.divisions },
        { key: 'status', label: 'Status', opts: STATUS_FILTERS },
        { key: 'priority', label: 'Priority', opts: OPT.priorities },
    ];
    const extraFields = [
        { key: 'industry', label: 'Industry', opts: OPT.industries },
        { key: 'principal', label: 'Principal', opts: OPT.principals },
        { key: 'product', label: 'Product', opts: OPT.products },
        { key: 'application', label: 'Application', opts: OPT.applications },
        { key: 'creator', label: 'Creator', opts: OPT.creators },
    ];
    const visibleExtras = extraFields.filter((fl) => extras.includes(fl.key));
    const hiddenExtras = extraFields.filter((fl) => !extras.includes(fl.key));

    const rows = useMemo(() => {
        const needle = q.trim().toLowerCase();
        const match = (vals, v) => vals.length === 0 || vals.includes(v);
        const r = LINES.filter((l) => {
            if (needle && !(String(l.id).includes(needle)
                || (l.company || '').toLowerCase().includes(needle)
                || (l.product || '').toLowerCase().includes(needle)
                || (l.producer || '').toLowerCase().includes(needle))) return false;
            if (!match(pills.company, l.company)) return false;
            if (!match(pills.division, l.division)) return false;
            if (!match(pills.status, l.status)) return false;
            if (!match(pills.priority, l.priority)) return false;
            if (!match(pills.industry, l.industry)) return false;
            if (!match(pills.principal, l.producer)) return false;
            if (!match(pills.product, l.product)) return false;
            if (!match(pills.application, l.application)) return false;
            if (!match(pills.creator, l.creator)) return false;
            return true;
        });
        return r.sort((x, y) => (sort === 'newest' ? y.id - x.id : x.id - y.id));
    }, [LINES, q, pills, sort]);

    // Column-header sort (ClientSort) — applies on top of the Newest/Oldest base order.
    const { sorted, sortKey, sortDir, toggleSort } = useClientSort(rows, SORT_GETTERS);
    // Resizable columns — drag a header's right edge (house pattern); ids follow visibleCols.
    const { widthOf, startResize, resizingId } = useResizableColumns(COL_W);
    const colIds = ['check', ...visibleCols.map((c) => c.id), 'action'];
    const tableWidth = colIds.reduce((sum, id) => sum + widthOf(id), 0);

    // One <td> per column id — keeps the table driven by visibleCols (⚙ hide/reorder).
    const renderCell = (l, colId) => {
        switch (colId) {
            case 'id': return <td key="id" className="font-bold tabular-nums text-primary">#{l.id}</td>;
            case 'priority': return <td key="priority"><Pill color={priorityDot(l.priority)}>{l.priority}</Pill></td>;
            case 'company': return (
                <td key="company">
                    <div className="font-bold text-foreground">{l.company}</div>
                    <div className="text-[11px] text-muted-foreground">{l.division}</div>
                </td>
            );
            case 'product': return (
                <td key="product">
                    <div className="font-semibold text-foreground">{l.product || '—'}</div>
                    <div className="text-[11px] text-muted-foreground">{l.producer || '—'}{l.application ? ` · ${l.application}` : ''}</div>
                </td>
            );
            case 'target': return (
                <td key="target">
                    <div className="font-bold tabular-nums text-foreground">${money(l.targetValue)}</div>
                    <div className="text-[11px] text-muted-foreground">{l.targetDate || '—'}</div>
                </td>
            );
            case 'status': return <td key="status"><Pill color={STATUS_DOT[l.status]}>{l.status}</Pill></td>;
            default: return null;
        }
    };

    const totalPages = Math.max(1, Math.ceil(rows.length / perPage));
    const currentPage = Math.min(page, totalPages);
    const pageRows = sorted.slice((currentPage - 1) * perPage, currentPage * perPage);
    const allChecked = pageRows.length > 0 && pageRows.every((l) => selected.has(l.key));
    const toggleAll = () => setSelected((prev) => { const n = new Set(prev); if (allChecked) pageRows.forEach((l) => n.delete(l.key)); else pageRows.forEach((l) => n.add(l.key)); return n; });
    const toggleSel = (k) => setSelected((prev) => { const n = new Set(prev); n.has(k) ? n.delete(k) : n.add(k); return n; });

    const selectedLines = useMemo(() => rows.filter((r) => selected.has(r.key)), [rows, selected]);
    const openConfirm = (action, items) => {
        if (!items.length) { showToast('Select at least one product first.', 'warning'); return; }
        setModalComment('');
        setConfirmA({ action, items });
    };
    const [submitting, setSubmitting] = useState(false);
    const [formError, setFormError] = useState('');
    const submitConfirm = () => {
        const text = modalComment.trim();
        if (!text || submitting) return; // comment mandatory for BOTH actions (legacy-faithful)
        const action = confirmA.action === 'Approve' ? 'approve' : 'reject';
        const details = confirmA.items.map((it) => it.ccId).filter((n) => Number.isInteger(n) && n > 0);
        if (details.length === 0) return;
        setSubmitting(true);
        setFormError('');
        router.post(
            route('company-projects.approval-pm.act', { action }),
            { details, comment: text },
            {
                preserveScroll: true,
                onSuccess: () => {
                    setSelected(new Set());
                    setConfirmA(null);
                    setDetail(null);
                },
                onError: (errors) => setFormError(errors.details || errors.comment || 'Processing failed — reload the queue.'),
                onFinish: () => setSubmitting(false),
            },
        );
    };

    return (
        <section className="flex min-w-0 flex-col gap-4">
            <header className="flex flex-wrap items-center justify-between gap-3">
                <h1 className="m-0 text-2xl font-extrabold tracking-tight text-foreground">Approval PM - Company Project</h1>
                <div className="flex items-center gap-3">
                    <span className="text-xs font-medium text-muted-foreground tabular-nums">FRI, 26-06-2026 14:34:00</span>
                    <div className="relative" onMouseEnter={() => setGuideOpen(true)} onMouseLeave={() => setGuideOpen(false)}>
                        <button
                            type="button"
                            onClick={() => setGuideOpen((v) => !v)}
                            title="Status Guide"
                            aria-label="Status Guide"
                            className={`inline-grid size-9 place-items-center rounded-full border transition-colors ${guideOpen ? 'border-primary bg-accent text-primary' : 'border-input text-muted-foreground hover:border-primary hover:text-primary'}`}
                        >
                            <HelpCircle className="size-[18px]" />
                        </button>
                        {guideOpen && (
                            <div className="absolute right-0 top-full z-[56] w-[360px] max-w-[90vw] pt-2">
                                <div className="rounded-2xl border border-border bg-card p-3.5 text-left shadow-xl">
                                    <div className="mb-2.5 flex items-center justify-between">
                                        <h3 className="m-0 text-[13px] font-bold text-foreground">Status Guide</h3>
                                        <button type="button" onClick={() => setGuideOpen(false)} className="inline-grid size-7 place-items-center rounded-full text-muted-foreground hover:bg-muted hover:text-foreground" aria-label="Close"><X className="size-4" /></button>
                                    </div>
                                    <ul className="m-0 flex list-none flex-col gap-2 p-0">
                                        {STATUS_GUIDE.map(([name, desc]) => (
                                            <li key={name} className="flex items-start gap-2.5">
                                                <span className="inline-flex w-[104px] shrink-0 items-center gap-1.5 pt-0.5">
                                                    <span className="size-2 shrink-0 rounded-full" style={{ background: STATUS_DOT[name], boxShadow: DOT_RING }} />
                                                    <span className="text-[12px] font-semibold leading-tight text-foreground">{name}</span>
                                                </span>
                                                <span className="text-[11px] leading-snug text-muted-foreground">{desc}</span>
                                            </li>
                                        ))}
                                    </ul>
                                </div>
                            </div>
                        )}
                    </div>
                </div>
            </header>

            <div className="flex flex-col items-start gap-4 xl:flex-row">
                {/* Left Pane (Table & Filter) */}
                <div className="flex min-w-0 flex-1 flex-col gap-4 self-stretch">
                    {!scoped && <p className="rounded-lg border border-border bg-secondary/40 px-4 py-2 text-[12px] text-muted-foreground">Oversight view — you have no head-division principals, so approving/rejecting is disabled.</p>}

                    {/* List — one card: toolbar + selection banner + table (list grammar) */}
                    <article className={`${CARD} overflow-hidden`}>
                        <div className="flex flex-wrap items-center gap-2.5 border-b border-border/50 px-6 py-5">
                            <label className="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 ID, company, product" autoComplete="off" value={q}
                                    onChange={(e) => { setQ(e.target.value); setPage(1); }}
                                    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}>

                            <span aria-hidden="true" className="h-5 w-px shrink-0 bg-border/70" />

                            {coreFields.map((fl) => (
                                <FilterPill key={fl.key} label={fl.label} value={pills[fl.key]} options={fl.opts} onChange={(v) => setPill(fl.key, v)} />
                            ))}
                            {visibleExtras.map((fl) => (
                                <FilterPill key={fl.key} label={fl.label} value={pills[fl.key]} options={fl.opts} onChange={(v) => setPill(fl.key, v)} onRemove={() => removeExtra(fl.key)} />
                            ))}
                            <AddFilterMenu fields={hiddenExtras} onAdd={(k) => setExtras((e) => [...e, k])} />

                            {activeFilterCount > 0 && (
                                <button type="button" onClick={resetFilters} 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">
                                    Reset filters
                                </button>
                            )}

                            <div className="ml-0 sm:ml-auto inline-flex items-center gap-2">
                                <span className="text-[11px] font-semibold text-muted-foreground tabular-nums">{rows.length} products</span>
                                <NativeSelect value={sort} onChange={(e) => setSort(e.target.value)} aria-label="Sort"
                                    className="h-8 rounded-md border border-input bg-card px-2 text-xs font-medium text-foreground outline-none focus:border-primary">
                                    <option value="newest">Newest</option>
                                    <option value="oldest">Oldest</option>
                                </NativeSelect>
                            </div>
                            </div>
                        </div>

                        {pageRows.length === 0 ? (
                            <p className="py-12 text-center text-sm text-muted-foreground">No products match the filter.</p>
                        ) : (
                            <div className="overflow-x-auto p-4 pt-3">
                                <table style={{ minWidth: tableWidth }} className={`${TABLE} table-fixed`}>
                                    <colgroup>
                                        {colIds.map((id) => <col key={id} style={{ width: widthOf(id) }} />)}
                                    </colgroup>
                                    <thead>
                                        <tr>
                                            <th>
                                                <CheckBox checked={allChecked} onChange={toggleAll} ariaLabel="Select all rows on page" />
                                            </th>
                                            {visibleCols.map((c) => (
                                                <th key={c.id} className="group/col relative">
                                                    <SortButton id={c.id} label={c.label} sortKey={sortKey} sortDir={sortDir} onToggle={toggleSort} />
                                                    <ColumnResizeGrip onMouseDown={(e) => startResize(e, c.id)} active={resizingId === c.id} />
                                                </th>
                                            ))}
                                            <th className="group/col relative !text-right">Action<ColumnResizeGrip onMouseDown={(e) => startResize(e, 'action')} active={resizingId === 'action'} /></th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        {pageRows.map((l) => {
                                            const isActive = detail?.key === l.key;
                                            const isSel = selected.has(l.key);
                                            return (
                                                <tr key={l.key} onClick={() => setDetail(l)} className={`cursor-pointer transition-colors ${isActive ? 'bg-primary/10 hover:!bg-primary/15' : isSel ? `${SELECTED_TD} ${SELECTED_HOVER_TD}` : ''}`}>
                                                <td onClick={(e) => e.stopPropagation()}>
                                                    <CheckBox checked={selected.has(l.key)} onChange={() => toggleSel(l.key)} ariaLabel={`Select ${l.key}`} />
                                                </td>
                                                {visibleCols.map((c) => renderCell(l, c.id))}
                                                <td className="text-right">
                                                    <div className="flex items-center justify-end gap-1.5" onClick={(e) => e.stopPropagation()}>
                                                        <button type="button" onClick={() => setDetail(l)} className="grid size-6 place-items-center rounded-md border border-border bg-transparent text-muted-foreground transition-colors hover:border-primary hover:bg-primary/5 hover:text-primary" title="View Detail" aria-label="View Detail"><Eye className="size-3.5" strokeWidth={2.5} /></button>
                                                        <button type="button" disabled={!scoped} onClick={() => openConfirm('Approve', [l])} className="grid size-6 place-items-center rounded-md border border-success/30 bg-success/5 text-success-text transition-colors hover:bg-success/15 disabled:opacity-50" title="Approve" aria-label="Approve"><Check className="size-3.5" strokeWidth={3} /></button>
                                                        <button type="button" disabled={!scoped} onClick={() => openConfirm('Reject', [l])} className="grid size-6 place-items-center rounded-md border border-border bg-transparent text-muted-foreground transition-colors hover:border-danger hover:bg-danger/10 hover:text-danger-text disabled:opacity-50" title="Reject" aria-label="Reject"><X className="size-3.5" strokeWidth={2.5} /></button>
                                                    </div>
                                                </td>
                                                </tr>
                                            );
                                        })}
                                    </tbody>
                                </table>
                            </div>
                        )}

                        <ListFooter
                            page={currentPage}
                            totalPages={totalPages}
                            onPage={setPage}
                            pageSize={perPage}
                            onPageSize={(n) => { setPerPage(n); setPage(1); }}
                            pageSizeOptions={[10, 25, 50]}
                            total={rows.length}
                            itemLabel="products"
                        />
                    </article>
                </div>

                {/* Right Pane (Detail Split View) */}
                {detail && (
                    <aside className="sticky top-6 flex w-full shrink-0 flex-col overflow-hidden rounded-2xl border border-border bg-card shadow-sm xl:max-h-[calc(100vh-3rem)] xl:w-[420px] 2xl:w-[460px]">
                        <header className="flex items-start justify-between gap-3 border-b border-border px-5 py-4">
                            <div className="min-w-0">
                                <div className="flex items-center gap-2">
                                    <span className="text-sm font-bold tabular-nums text-primary">#{detail.id}</span>
                                    <Pill color={priorityDot(detail.priority)}>{detail.priority}</Pill>
                                    <Pill color={STATUS_DOT[detail.status]}>{detail.status}</Pill>
                                </div>
                                <div className="mt-1.5 truncate text-base font-extrabold text-foreground" title={detail.company}>{detail.company}</div>
                                <div className="truncate text-[12px] text-muted-foreground">{detail.division} · {detail.industry}</div>
                            </div>
                            <button type="button" onClick={() => setDetail(null)} className="inline-grid size-8 shrink-0 place-items-center rounded-md text-muted-foreground hover:bg-muted hover:text-foreground" aria-label="Close"><X className="size-5" /></button>
                        </header>

                        <div className="flex-1 space-y-5 overflow-y-auto px-5 py-4">
                            {/* hero — headline target */}
                            <div className="rounded-xl border border-primary/15 bg-linear-to-br from-violet-500/10 to-primary/5 p-4">
                                <div className="text-[10px] font-bold uppercase tracking-wide text-primary/80">Target Value</div>
                                <div className="mt-0.5 text-2xl font-extrabold tabular-nums text-foreground">${money(detail.targetValue)}</div>
                                <div className="mt-3 grid grid-cols-3 gap-2">
                                    {[['Target Qty', `${money(detail.targetQty)} ${detail.satuan}`], ['Target Price', `$${money(detail.targetPrice)}`], ['Target Date', detail.targetDate || '—']].map(([k, v]) => (
                                        <div key={k} className="rounded-lg bg-card/70 px-2.5 py-2">
                                            <div className="text-[9px] font-semibold uppercase tracking-wide text-muted-foreground">{k}</div>
                                            <div className="truncate text-[12px] font-bold tabular-nums text-foreground" title={v}>{v}</div>
                                        </div>
                                    ))}
                                </div>
                            </div>

                            {/* project */}
                            <Section icon={FolderKanban} title="Project">
                                <Row label="Project">{detail.title || '—'}</Row>
                                <Row label="Creator">{detail.creator || '—'}</Row>
                            </Section>

                            {/* product */}
                            <Section icon={Package} title="Product">
                                <div className="mb-2 rounded-lg bg-muted/40 px-3 py-2 text-sm font-bold text-foreground">{detail.product || '—'}</div>
                                <Row label="Principal">{detail.producer || '—'}</Row>
                                <Row label="Application">{detail.application || '—'}</Row>
                                <Row label="Supplier">{detail.supplier || '—'}</Row>
                                <Row label="Opportunity">{detail.opportunity || '—'}</Row>
                            </Section>

                            {/* pricing & volume — expected vs current */}
                            <Section icon={Coins} title="Pricing & Volume">
                                <div className="overflow-hidden rounded-xl border border-border/50">
                                    <table className="w-full text-left text-[12px]">
                                        <thead>
                                            <tr className="bg-muted/30 text-[10px] uppercase tracking-wide text-muted-foreground">
                                                <th className="px-4 py-2.5 font-semibold">Metric</th>
                                                <th className="px-4 py-2.5 !text-right font-semibold">Expected</th>
                                                <th className="px-4 py-2.5 !text-right font-semibold">Current</th>
                                            </tr>
                                        </thead>
                                        <tbody className="divide-y divide-border/50 tabular-nums">
                                            {[
                                                ['Price $', `$${money(detail.price)}`, detail.currentPrice ? `$${money(detail.currentPrice)}` : '—'],
                                                ['Qty / Year', `${money(detail.qty)} ${detail.satuan}`, detail.currentQty ? `${money(detail.currentQty)} ${detail.satuan}` : '—'],
                                                ['Value / Year', `$${money(detail.valuePerYear)}`, detail.currentValue ? `$${money(detail.currentValue)}` : '—'],
                                            ].map(([k, e, c]) => (
                                                <tr key={k}>
                                                    <td className="px-4 py-2.5 font-medium text-muted-foreground">{k}</td>
                                                    <td className="px-4 py-2.5 text-right font-bold text-foreground">{e}</td>
                                                    <td className="px-4 py-2.5 text-right text-muted-foreground">{c}</td>
                                                </tr>
                                            ))}
                                        </tbody>
                                    </table>
                                </div>
                                <div className="mt-2 flex gap-2">
                                    <span className="rounded-md bg-secondary/80 px-2 py-1 text-[10px] font-medium text-muted-foreground">{detail.priceType}</span>
                                    <span className="rounded-md bg-secondary/80 px-2 py-1 text-[10px] font-medium text-muted-foreground">{detail.qtyType}</span>
                                </div>
                            </Section>

                            {/* remark */}
                            {detail.remark && (
                                <Section icon={FileText} title="Remark">
                                    <p className="m-0 text-[13px] leading-relaxed text-foreground rounded-lg bg-muted/30 px-3 py-2">{detail.remark}</p>
                                </Section>
                            )}

                            {/* competitor */}
                            <Section icon={Users} title={`Competitors (${detail.competitors?.length || 0})`}>
                                {detail.competitors?.length ? (
                                    <div className="flex flex-col gap-3">
                                        {detail.competitors.map((c, ci) => (
                                            <div key={ci} className="rounded-xl border border-border bg-card p-3 shadow-sm transition-shadow hover:shadow-md">
                                                <div className="flex items-start justify-between gap-2">
                                                    <div>
                                                        <div className="text-[13px] font-bold text-foreground">{c.product}</div>
                                                        <div className="mt-0.5 text-[11px] text-muted-foreground">{c.producer} · {c.supplier}</div>
                                                    </div>
                                                    <div className="text-right">
                                                        <div className="text-[13px] font-bold tabular-nums text-foreground">${money(c.value)}</div>
                                                        <div className="mt-0.5 text-[10px] tabular-nums text-muted-foreground">${money(c.price)} × {money(c.qty)}</div>
                                                    </div>
                                                </div>
                                            </div>
                                        ))}
                                    </div>
                                ) : (
                                    <div className="flex items-center gap-2 rounded-xl border border-dashed border-border/70 px-4 py-3">
                                        <Users className="size-4 text-muted-foreground/50" />
                                        <span className="text-[12px] font-medium text-muted-foreground">No competitor data yet.</span>
                                    </div>
                                )}
                            </Section>
                        </div>

                        <footer className="grid grid-cols-2 gap-2.5 border-t border-border px-5 py-4">
                            <button type="button" disabled={!scoped} onClick={() => openConfirm('Reject', [detail])} className="inline-flex h-9 items-center justify-center gap-1.5 rounded-lg border border-danger/40 bg-card text-xs font-bold text-danger-text transition-colors hover:border-danger hover:bg-danger/10 disabled:opacity-50"><X className="size-4" /> Reject</button>
                            <button type="button" disabled={!scoped} onClick={() => openConfirm('Approve', [detail])} className="inline-flex h-9 items-center justify-center gap-1.5 rounded-lg border border-success/50 bg-card text-xs font-bold text-success-text transition-colors hover:border-success hover:bg-success/10 disabled:opacity-50"><Check className="size-4" /> Approve</button>
                        </footer>
                    </aside>
                )}
            </div>

            {/* Confirm modal — Approve / Reject (single, drawer, or bulk) */}
            {confirmA && (() => {
                const isApprove = confirmA.action === 'Approve';
                const n = confirmA.items.length;
                return (
                    <div className="fixed inset-0 z-[60] flex items-center justify-center p-4">
                        <div className="absolute inset-0 bg-black/50 backdrop-blur-[1px]" onClick={() => setConfirmA(null)} aria-hidden="true" />
                        <div role="dialog" aria-modal="true" className="relative w-full max-w-md rounded-2xl border border-border bg-card p-5 shadow-2xl">
                            <div className="flex items-start gap-3">
                                <span className={`grid size-10 shrink-0 place-items-center rounded-full ${isApprove ? 'bg-success/10 text-success-text' : 'bg-danger/10 text-danger-text'}`}>
                                    {isApprove ? <Check className="size-5" /> : <X className="size-5" />}
                                </span>
                                <div className="min-w-0">
                                    <h3 className="m-0 text-base font-bold text-foreground">{confirmA.action} {n} product{n > 1 ? 's' : ''}?</h3>
                                    <p className="m-0 mt-0.5 text-[12px] leading-snug text-muted-foreground">
                                        {isApprove ? 'The following product(s) will be approved (PM).' : 'The following product(s) will be rejected.'} This action will be recorded in the history.
                                    </p>
                                </div>
                                <button type="button" onClick={() => setConfirmA(null)} className="-mr-1 -mt-1 inline-grid size-8 shrink-0 place-items-center rounded-md text-muted-foreground hover:bg-muted hover:text-foreground" aria-label="Close"><X className="size-4" /></button>
                            </div>

                            <ul className="m-0 mt-3 flex max-h-32 list-none flex-col gap-1 overflow-y-auto rounded-lg border border-border/60 bg-muted/30 p-2 text-[12px]">
                                {confirmA.items.map((it) => (
                                    <li key={it.key} className="flex items-center gap-2 truncate">
                                        <span className="shrink-0 font-bold tabular-nums text-primary">#{it.id}</span>
                                        <span className="truncate font-medium text-foreground">{it.product || '—'}</span>
                                        <span className="ml-auto shrink-0 truncate text-muted-foreground">{it.company}</span>
                                    </li>
                                ))}
                            </ul>

                            <label className="mt-3 block">
                                <span className="mb-1.5 block text-[12px] font-semibold text-muted-foreground">Comment {isApprove ? <span className="font-normal">(optional)</span> : <span className="text-danger-text">*</span>}</span>
                                <textarea value={modalComment} onChange={(e) => setModalComment(e.target.value)} rows={3} autoFocus placeholder={isApprove ? 'Add a note…' : 'Reason for rejection…'} className="w-full resize-y rounded-lg border border-input bg-card px-3 py-2.5 text-sm text-foreground outline-none transition-colors placeholder:text-muted-foreground/55 focus:border-primary focus:ring-1 focus:ring-primary" />
                            </label>
                            {formError && <p className="mt-2 text-[12px] font-medium text-danger-text">{formError}</p>}

                            <div className="mt-4 flex items-center justify-end gap-2.5">
                                <button type="button" onClick={() => setConfirmA(null)} className="inline-flex h-9 items-center rounded-lg border border-input bg-card px-4 text-xs font-bold text-foreground transition-colors hover:border-primary hover:text-primary">Cancel</button>
                                <button
                                    type="button"
                                    disabled={(!isApprove && !modalComment.trim()) || submitting}
                                    onClick={submitConfirm}
                                    className={`inline-flex h-9 items-center gap-1.5 rounded-lg px-5 text-xs font-bold text-white shadow-sm transition-[filter] hover:brightness-105 disabled:cursor-not-allowed disabled:opacity-50 ${isApprove ? 'bg-success' : 'bg-danger'}`}
                                >
                                    {isApprove ? <Check className="size-3.5" /> : <X className="size-3.5" />} {confirmA.action}
                                </button>
                            </div>
                        </div>
                    </div>
                );
            })()}

            <CustomizeColumnsModal
                open={showColumns}
                onClose={() => setShowColumns(false)}
                groups={COLUMN_GROUPS}
                definitions={COLUMN_DEFS}
                state={columnState}
                onApply={applyColumns}
                onReset={resetColumns}
            />

        {/* Floating decision pill — ui-conventions.md: approval pages put the action row in a
            centred pinned pill, never right-aligned. Approve first, heavier actions to its right
            (this queue rejects rather than revises). Rendered even with nothing picked, disabled,
            so the checkbox column always has a visible verb. */}
        <DecisionBar>
          {selected.size > 0 ? (
            <span className="inline-flex items-center gap-2 text-[12.5px] font-medium text-foreground">
              <span className="grid size-5 place-items-center rounded-full bg-primary text-[11px] font-bold text-primary-foreground tabular-nums">{selected.size}</span>
              products selected
              <button type="button" onClick={() => setSelected(new Set())}
                className="text-[12px] font-medium text-muted-foreground transition-colors hover:text-foreground">Clear</button>
            </span>
          ) : (
            <span className="text-[12.5px] font-medium text-muted-foreground">Select products to approve</span>
          )}
          <div className="flex items-center gap-2.5">
            <Button size="sm" disabled={!scoped || selected.size === 0} onClick={() => openConfirm('Approve', selectedLines)} className="h-9 gap-1.5 px-4 text-xs font-bold">
              <Check className="size-3.5" strokeWidth={3} />Approve
            </Button>
            <Button variant="outline" size="sm" disabled={!scoped || selected.size === 0} onClick={() => openConfirm('Reject', selectedLines)}
              className="h-9 gap-1.5 border-danger/40 px-4 text-xs font-bold text-danger-text hover:border-danger hover:bg-danger/10 hover:text-danger-text">
              <X className="size-3.5" strokeWidth={2.5} />Reject
            </Button>
          </div>
        </DecisionBar>
        </section>
    );
}

ProjectApprovalPm.layout = [AppLayout];
