// General Affairs — "My Request" list (Phase 1 wiring, 2026-07-23).
// The actor's OWN vehicle service requests (server scope vsr.UserIDInput = me,
// VehicleServiceRequestController@myRequest). No proto page existed for this stage, so it
// is built on the module's house list grammar (the GA proto search pages + VisitPlans/List):
// ONE card = toolbar (search + date range + vehicle pill + reset + ⚙) → data-driven list
// table → ListFooter, driven SERVER-side by Inertia's router (not client mock).
// Rows are read-only in Phase 1 — the detail page + Cancel/Revise arrive in Phase 6.
import { useEffect, useMemo, useRef, useState } from 'react';
import { router } from '@inertiajs/react';
import { Search, Settings, RotateCcw } from 'lucide-react';
import AppLayout from '@/Layouts/AppLayout';
import { StatusBadge } from '@/Components/Proto/UI/StatusBadge';
import { OptionPill } from '@/Components/MenuQuotations/QuotationListPage/QuotationListPills';
import { CustomizeColumnsModal } from '@/Components/Proto/Modals/CustomizeColumnsModal';
import { CreateActionButton } from '@/Components/Table/CreateActionButton';
import { ListFooter } from '@/Components/Table/ListFooter';
import { SortButton } from '@/lib/ClientSort';
import { useServerSortNav } from '@/lib/ServerSort';
import { useResizableColumns, ColumnResizeGrip } from '@/lib/useResizableColumns';

const CARD = 'rounded-2xl border border-border bg-card shadow-sm';
const INPUT_PILL = 'h-8 rounded-full border border-input bg-card px-3 text-xs font-medium text-foreground outline-none transition-colors focus-visible:border-primary';

// List tier grammar (shared with the GA proto search pages): pill header band, td
// py-[16px] text-[12px], px-3.5 with first:pl-7 / last:pr-5, zebra + hover on tbody.
const LIST_TABLE =
    'w-full border-separate border-spacing-0 ' +
    '[&_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-3 [&_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:last-child]:rounded-r-full ' +
    '[&_th:first-child]:pl-7 [&_td:first-child]:pl-7 [&_th:last-child]:pr-5 [&_td:last-child]:pr-5 ' +
    '[&_th.number]:text-right [&_td.number]:text-right ' +
    '[&_tbody_td]:overflow-hidden [&_tbody_td]:whitespace-nowrap [&_tbody_td]:border-b [&_tbody_td]:border-border/50 [&_tbody_td]:px-3.5 [&_tbody_td]:py-[16px] [&_tbody_td]:text-[12px] [&_tbody_td]:font-medium [&_tbody_td]:text-foreground [&_tbody_tr:last-child_td]:border-b-0 ' +
    '[&_tbody_tr:nth-child(even)_td]:bg-secondary/25';

// ---- Data-driven columns (hide/reorder via the ⚙ CustomizeColumnsModal) ----
const COLUMN_GROUPS = [{ id: 'request', label: 'Request' }];
const COLUMN_DEFS = [
    { id: 'reqNo', label: 'Req No', groupId: 'request', required: true }, // row anchor — cannot be hidden
    { id: 'tanggal', label: 'Tanggal', groupId: 'request' },
    { id: 'status', label: 'Status', groupId: 'request' },
    { id: 'owner', label: 'Owner', groupId: 'request' },
    { id: 'creator', label: 'Creator', groupId: 'request' },
    { id: 'vehicle', label: 'Vehicle', groupId: 'request' },
    { id: 'km', label: 'KM', groupId: 'request', numeric: true },
    { id: 'comment', label: 'Comment', groupId: 'request' },
];
// Sortable columns — id → raw row value (house ClientSort pattern; A→Z on first click).
// Columns the SERVER can order by — must mirror the controller's SORT_COLUMNS.
// A column not listed here renders a plain label instead of a dead sort button.
const SORTABLE = new Set(['reqNo', 'tanggal', 'status', 'owner', 'creator', 'vehicle', 'km', 'comment']);
// Resizable-column default widths for the table-fixed layout (no trailing actions column here).
const COL_W = {
    reqNo: 90, tanggal: 110, status: 140, owner: 140, creator: 140,
    vehicle: 180, km: 80, comment: 240,
};
const COL_W_FALLBACK = 130;
const REQUIRED_IDS = new Set(COLUMN_DEFS.filter((d) => d.required).map((d) => d.id));
const defaultColumnState = () => COLUMN_DEFS.map((d) => ({ id: d.id, visible: true }));
const STORAGE_KEY = 'gaMyRequestColumns_v1';
// Load-guard (house rule): drop stored ids no longer in COLUMN_DEFS, force required
// columns visible, append columns added since the payload was saved.
function loadStoredState() {
    try {
        const raw = localStorage.getItem(STORAGE_KEY);
        if (!raw) return defaultColumnState();
        const defIds = new Set(COLUMN_DEFS.map((d) => d.id));
        const parsed = JSON.parse(raw)
            .filter((c) => c && defIds.has(c.id))
            .map((c) => ({ id: c.id, visible: REQUIRED_IDS.has(c.id) ? true : Boolean(c.visible) }));
        const present = new Set(parsed.map((c) => c.id));
        COLUMN_DEFS.forEach((d) => { if (!present.has(d.id)) parsed.push({ id: d.id, visible: true }); });
        return parsed;
    } catch {
        return defaultColumnState();
    }
}

function renderCell(row, colId) {
    switch (colId) {
        case 'reqNo': return <span className="font-bold tabular-nums text-primary">#{row.id}</span>;
        case 'tanggal': return row.tanggal || '—';
        case 'status': return row.statusName ? <StatusBadge tone={row.statusTone}>{row.statusName}</StatusBadge> : '—';
        case 'owner': return row.owner || '—';
        case 'creator': return row.creator || '—';
        case 'vehicle': return row.vehicleLabel || '—';
        case 'km': return row.km ?? '—';
        case 'comment': return row.comment
            ? <span className="block max-w-72 truncate" title={row.comment}>{row.comment}</span>
            : '—';
        default: return '—';
    }
}

export default function MyRequestSearch({ requests, filters, filterOptions, canCreate = false, canCreateAll = false }) {
    // Search keeps a debounced draft; dates + vehicle commit on change. All server-driven.
    const [q, setQ] = useState(filters.search ?? '');
    const [earlyDate, setEarlyDate] = useState(filters.early_date ?? '');
    const [endDate, setEndDate] = useState(filters.end_date ?? '');

    // Push a server visit merging current filters with `next` (page resets to 1 on any
    // filter change). preserveState keeps the typed search box; replace avoids stacking
    // one history entry per keystroke.
    const reload = (next = {}) => {
        router.get(route('general-affairs.my-request'), {
            search: q,
            early_date: earlyDate,
            end_date: endDate,
            vehicle: filters.vehicle,
            per_page: filters.per_page,
            ...next,
        }, { preserveState: true, preserveScroll: true, replace: true });
    };

    // Debounce the search box → server (skip the initial mount).
    const firstRender = useRef(true);
    useEffect(() => {
        if (firstRender.current) { firstRender.current = false; return; }
        const t = setTimeout(() => reload({ search: q, page: 1 }), 300);
        return () => clearTimeout(t);
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [q]);

    const anyFilter = Boolean(q || earlyDate || endDate || filters.vehicle);
    const resetFilters = () => {
        setQ(''); setEarlyDate(''); setEndDate('');
        reload({ search: '', early_date: '', end_date: '', vehicle: '', page: 1 });
    };

    // Column order + visibility (⚙ modal) — persisted to localStorage.
    const [columnState, setColumnState] = useState(loadStoredState);
    const [customizeOpen, setCustomizeOpen] = useState(false);
    const visibleCols = useMemo(() => columnState
        .filter((c) => c.visible)
        .map((c) => COLUMN_DEFS.find((d) => d.id === c.id))
        .filter(Boolean), [columnState]);
    const handleApplyColumns = (next) => {
        setColumnState(next);
        try { localStorage.setItem(STORAGE_KEY, JSON.stringify(next)); } catch { /* private mode */ }
    };
    const handleResetColumns = () => {
        const def = defaultColumnState();
        try { localStorage.removeItem(STORAGE_KEY); } catch { /* private mode */ }
        return def;
    };

    // Client-side sort over the current server page + resizable columns (house pattern).
    // Server-side sort: the DATABASE orders the whole table, not the browser the page.
    const { sortKey, sortDir, toggleSort } = useServerSortNav('general-affairs.my-request', filters);
    const rows = requests.data ?? [];
    const { widthOf, startResize, resizingId, resizeRef } = useResizableColumns(COL_W, COL_W_FALLBACK);
    // Direct header drag-to-reorder (LwrListPage pattern) — splices columnState and persists
    // via the existing STORAGE_KEY; resizeRef bails out so a grip drag never starts a column drag.
    const [dragColId, setDragColId] = useState(null);
    const [dragOverColId, setDragOverColId] = useState(null);
    const reorderCols = (fromId, toId) => {
        if (!fromId || !toId || fromId === toId) return;
        setColumnState((prev) => {
            const from = prev.findIndex((c) => c.id === fromId);
            const to = prev.findIndex((c) => c.id === toId);
            if (from < 0 || to < 0) return prev;
            const next = [...prev];
            const [moved] = next.splice(from, 1);
            next.splice(to, 0, moved);
            try { localStorage.setItem(STORAGE_KEY, JSON.stringify(next)); } catch { /* private mode */ }
            return next;
        });
    };
    const colIds = useMemo(() => visibleCols.map((c) => c.id), [visibleCols]);
    const tableWidth = useMemo(() => colIds.reduce((sum, id) => sum + widthOf(id), 0), [colIds, widthOf]);
    const openDetail = (id) => router.visit(route('general-affairs.my-request.show', id));

    return (
        <section className="flex min-w-0 flex-col gap-4">
            <header>
                <p className="mb-1.5 flex items-center gap-2 text-xs font-semibold text-muted-foreground">
                    <span>General Affair</span>
                    <span aria-hidden="true">›</span>
                    <span className="text-foreground">My Request</span>
                </p>
                <div className="flex items-start justify-between gap-4">
                    <div>
                        <h1 className="m-0 text-2xl font-extrabold tracking-tight text-foreground max-[560px]:text-xl">My Request — Vehicle Service Request</h1>
                        <p className="m-0 mt-1 text-[13px] font-medium text-muted-foreground">Vehicle service requests you created.</p>
                    </div>
                    <CreateActionButton
                        canCreate={canCreate}
                        label="New Request"
                        href={route('general-affairs.create')}
                        variants={[{ key: 'all', label: 'All Vehicles', can: canCreateAll, href: route('general-affairs.create-all') }]}
                    />
                </div>
            </header>

            <article className={`${CARD} overflow-hidden`}>
                {/* Toolbar */}
                <div className="flex flex-wrap items-center gap-2 border-b border-border/60 px-5 py-3">
                    <label className="relative inline-flex h-8 min-w-[200px] max-w-[280px] 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"
                            value={q}
                            onChange={(e) => setQ(e.target.value)}
                            placeholder="Vehicle Req No…"
                            autoComplete="off"
                            aria-label="Search Vehicle Req No"
                            className="min-w-0 flex-1 bg-transparent text-[12.5px] font-medium text-foreground outline-none placeholder:text-muted-foreground/70"
                        />
                    </label>
                    <input
                        type="date"
                        title="Early Date"
                        aria-label="Early Date"
                        value={earlyDate}
                        onChange={(e) => { setEarlyDate(e.target.value); reload({ early_date: e.target.value, page: 1 }); }}
                        className={`${INPUT_PILL} min-w-0 flex-1 sm:flex-none`}
                    />
                    <input
                        type="date"
                        title="End Date"
                        aria-label="End Date"
                        value={endDate}
                        onChange={(e) => { setEndDate(e.target.value); reload({ end_date: e.target.value, page: 1 }); }}
                        className={`${INPUT_PILL} min-w-0 flex-1 sm:flex-none`}
                    />
                    <OptionPill
                        label="Vehicle"
                        value={filters.vehicle}
                        options={filterOptions.vehicles}
                        onPick={(v) => reload({ vehicle: v, page: 1 })}
                    />
                    {anyFilter && (
                        <button
                            type="button"
                            onClick={resetFilters}
                            title="Reset all active filters"
                            className="inline-flex h-8 cursor-pointer items-center gap-1.5 rounded-full px-2.5 text-[12.5px] font-semibold text-muted-foreground transition-colors hover:bg-danger/10 hover:text-danger-text"
                        >
                            <RotateCcw className="size-3.5" />
                            <span>Reset filters</span>
                        </button>
                    )}
                    <div className="ml-auto flex items-center gap-2">
                        <button
                            type="button"
                            onClick={() => setCustomizeOpen(true)}
                            title="Customize columns"
                            aria-label="Customize columns"
                            className="inline-grid size-7 cursor-pointer place-items-center rounded-[7px] border-none bg-transparent text-muted-foreground transition-colors hover:text-card-foreground"
                        >
                            <Settings aria-hidden="true" className="size-3.75" strokeWidth={2} />
                        </button>
                    </div>
                </div>

                {/* Table */}
                <div className="overflow-x-auto">
                    <table style={{ minWidth: tableWidth }} className={`${LIST_TABLE} table-fixed`}>
                        <colgroup>
                            {colIds.map((id) => <col key={id} style={{ width: widthOf(id) }} />)}
                        </colgroup>
                        <thead>
                            <tr>
                                {visibleCols.map((col) => (
                                    <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); }}
                                        title="Drag to reorder · drag right edge to resize"
                                        className={`group/col relative cursor-grab select-none active:cursor-grabbing${col.numeric ? ' number' : ''}${dragColId === col.id ? ' opacity-40' : ''}${dragOverColId === col.id && dragColId !== col.id ? ' bg-accent text-primary' : ''}`}>
                                        <SortButton id={col.id} label={col.label} sortKey={sortKey} sortDir={sortDir} onToggle={toggleSort} />
                                        <ColumnResizeGrip onMouseDown={(e) => startResize(e, col.id)} active={resizingId === col.id} />
                                    </th>
                                ))}
                            </tr>
                        </thead>
                        <tbody>
                            {rows.length === 0 ? (
                                <tr>
                                    <td colSpan={visibleCols.length}>
                                        <div className="py-16 text-center text-sm font-medium text-muted-foreground">
                                            No vehicle requests found.
                                        </div>
                                    </td>
                                </tr>
                            ) : (
                                rows.map((row) => (
                                    <tr key={row.id} onClick={() => openDetail(row.id)} className="cursor-pointer">
                                        {visibleCols.map((col) => (
                                            <td key={col.id} className={col.numeric ? 'number tabular-nums' : (col.id === 'tanggal' ? 'tabular-nums' : undefined)}>
                                                {renderCell(row, col.id)}
                                            </td>
                                        ))}
                                    </tr>
                                ))
                            )}
                        </tbody>
                    </table>
                </div>

                <ListFooter
                    page={requests.current_page}
                    totalPages={requests.last_page}
                    onPage={(n) => reload({ page: n })}
                    pageSize={filters.per_page}
                    onPageSize={(n) => reload({ per_page: n, page: 1 })}
                    pageSizeOptions={[10, 25, 50, 100]}
                    total={requests.total}
                    itemLabel="requests"
                />
            </article>

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

MyRequestSearch.layout = [AppLayout];
