import { useMemo, useState } from 'react';
import { useForm } from '@inertiajs/react';
import { Loader2, Search, Wallet } from 'lucide-react';
import AppLayout from '@/Layouts/AppLayout';
import { TopBar, Crumb, CrumbSep, CrumbCurrent, ListCard } from '@/Components/Table';
import { CheckBox } from '@/Components/Proto/UI/CheckBox';
import { useToast } from '@/Components/Toast';
import { cn } from '@/lib/utils';

/**
 * Pengaturan Dashboard — which dashboard cards each ROLE sees, and whether it sees figures.
 *
 * A role × capability MATRIX, not a list of rows. Role-Menu Assignments already edits one
 * role × one menu through two dropdowns; doing eight capabilities across 29 roles that way is
 * data entry. Roles are the rows because IT thinks per role ("what may Gudang see"), and 29
 * rows × 8 boxes fits one screen without pagination.
 *
 * ⚠️ The money column is NOT a widget. It redacts figures INSIDE the other cards — a role can
 * keep "Transaksi Terbaru" and still lose the amount on every row. It is drawn apart from the
 * widget columns on purpose; shown as just another checkbox it reads like an eighth card.
 */
export default function DashboardWidgetIndex({ roles = [], capabilities = [] }) {
    const { show: showToast } = useToast();
    const [query, setQuery] = useState('');

    const widgetCaps = capabilities.filter((c) => !c.isModifier);
    const moneyCap = capabilities.find((c) => c.isModifier);

    // The whole matrix is ONE form: a checkbox is a local edit until Save, so IT can plan a
    // change across several roles and commit it in one go (and one audit-able request).
    const form = useForm({
        grants: roles.map((r) => ({ roleId: r.id, capabilities: r.capabilities ?? [] })),
    });

    const held = useMemo(() => {
        const map = new Map();
        form.data.grants.forEach((g) => map.set(g.roleId, new Set(g.capabilities)));
        return map;
    }, [form.data.grants]);

    const setGrants = (next) => form.setData('grants', next);

    const toggle = (roleId, capId) => setGrants(form.data.grants.map((g) => {
        if (g.roleId !== roleId) return g;
        const on = g.capabilities.includes(capId);
        return {
            ...g,
            capabilities: on ? g.capabilities.filter((c) => c !== capId) : [...g.capabilities, capId],
        };
    }));

    /** Column toggle — grant/revoke one capability for every role currently listed. */
    const toggleColumn = (capId, on) => {
        const visibleIds = new Set(shown.map((r) => r.id));
        setGrants(form.data.grants.map((g) => {
            if (!visibleIds.has(g.roleId)) return g;
            const has = g.capabilities.includes(capId);
            if (on && !has) return { ...g, capabilities: [...g.capabilities, capId] };
            if (!on && has) return { ...g, capabilities: g.capabilities.filter((c) => c !== capId) };
            return g;
        }));
    };

    /** Row toggle — everything on or everything off for one role. */
    const toggleRow = (roleId, on) => setGrants(form.data.grants.map((g) => (
        g.roleId === roleId
            ? { ...g, capabilities: on ? capabilities.map((c) => c.id) : [] }
            : g
    )));

    const shown = useMemo(() => {
        const q = query.trim().toLowerCase();
        return q ? roles.filter((r) => r.name.toLowerCase().includes(q)) : roles;
    }, [roles, query]);

    const submit = () => form.post(route('dashboard-widgets.update'), {
        preserveScroll: true,
        // No onSuccess toast — the server sends it (.claude/rules/notifications.md).
        onError: () => showToast('Please check the form and try again.', 'error'),
    });

    const TH = 'whitespace-nowrap px-2 py-2.5 text-center text-[11px] font-semibold uppercase tracking-wide text-muted-foreground';

    return (
        <section className="flex min-w-0 flex-col gap-[18px]">
            <TopBar
                title="Pengaturan Dashboard"
                breadcrumb={<><Crumb href={route('dashboard-widgets.index')}>Pengelolaan</Crumb><CrumbSep /><CrumbCurrent>Pengaturan Dashboard</CrumbCurrent></>}
                action={
                    <button type="button" onClick={submit} disabled={form.processing}
                        className="inline-flex h-9 items-center justify-center gap-1.5 rounded-lg bg-linear-to-br from-violet-500 to-primary px-4 text-xs font-bold text-white shadow-sm transition-[filter] hover:brightness-105 disabled:opacity-60">
                        {form.processing ? <><Loader2 className="size-3.5 animate-spin" />Menyimpan…</> : 'Simpan'}
                    </button>
                }
            />

            <ListCard>
                <div className="flex flex-wrap items-center gap-2.5 border-b border-border/50 px-5 py-4">
                    <label className="relative inline-flex h-8 w-[240px] max-w-full 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="Cari role…" autoComplete="off" value={query}
                            onChange={(e) => setQuery(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>
                    <p className="m-0 text-[11.5px] font-medium text-muted-foreground">
                        Kolom <b className="text-foreground">Lihat Angka Uang</b> bukan widget — ia menyembunyikan
                        angka di dalam kartu lain, termasuk nilai tiap baris Transaksi Terbaru.
                    </p>
                </div>

                <div className="overflow-x-auto">
                    <table className="w-full border-separate border-spacing-0">
                        <thead>
                            <tr>
                                <th className={cn(TH, '!text-left pl-6')}>Role</th>
                                <th className={cn(TH, '!text-right')}>User</th>
                                {widgetCaps.map((c) => (
                                    <th key={c.id} className={TH}>
                                        <span className="block">{c.label}</span>
                                        <span className="mt-1 flex justify-center gap-1.5 text-[10px] font-bold">
                                            <button type="button" onClick={() => toggleColumn(c.id, true)} className="text-primary hover:underline">semua</button>
                                            <span className="opacity-40">·</span>
                                            <button type="button" onClick={() => toggleColumn(c.id, false)} className="text-muted-foreground hover:text-danger-text hover:underline">nol</button>
                                        </span>
                                    </th>
                                ))}
                                {moneyCap && (
                                    <th className={cn(TH, 'border-l border-border bg-warning-bg/40 !text-warning-text')}>
                                        <span className="flex items-center justify-center gap-1"><Wallet className="size-3.5" />{moneyCap.label}</span>
                                        <span className="mt-1 flex justify-center gap-1.5 text-[10px] font-bold">
                                            <button type="button" onClick={() => toggleColumn(moneyCap.id, true)} className="text-primary hover:underline">semua</button>
                                            <span className="opacity-40">·</span>
                                            <button type="button" onClick={() => toggleColumn(moneyCap.id, false)} className="text-muted-foreground hover:text-danger-text hover:underline">nol</button>
                                        </span>
                                    </th>
                                )}
                                <th className={TH}>Baris</th>
                            </tr>
                        </thead>
                        <tbody>
                            {shown.length === 0 ? (
                                <tr><td colSpan={capabilities.length + 3} className="px-6 py-7 text-center italic text-muted-foreground">Tidak ada role yang cocok.</td></tr>
                            ) : shown.map((r) => {
                                const set = held.get(r.id) ?? new Set();
                                return (
                                    <tr key={r.id} className="[&>td]:border-b [&>td]:border-border/50 [&>td]:px-2 [&>td]:py-2.5 hover:[&>td]:bg-secondary/40">
                                        <td className="!pl-6 text-[12.5px] font-semibold text-foreground">
                                            {r.name}
                                            {/* A role nobody configured would get a blank dashboard silently.
                                                Flagged so IT sees it before a user reports it. */}
                                            {r.unconfigured && (
                                                <span className="ml-2 inline-flex rounded-full bg-warning-bg px-2 py-0.5 text-[10px] font-bold text-warning-text">belum diatur</span>
                                            )}
                                        </td>
                                        <td className="text-right text-[12px] tabular-nums text-muted-foreground">{r.userCount}</td>
                                        {widgetCaps.map((c) => (
                                            <td key={c.id} className="text-center">
                                                <span className="inline-flex justify-center">
                                                    <CheckBox checked={set.has(c.id)} onChange={() => toggle(r.id, c.id)} ariaLabel={`${r.name} — ${c.label}`} />
                                                </span>
                                            </td>
                                        ))}
                                        {moneyCap && (
                                            <td className="border-l border-border bg-warning-bg/20 text-center">
                                                <span className="inline-flex justify-center">
                                                    <CheckBox checked={set.has(moneyCap.id)} onChange={() => toggle(r.id, moneyCap.id)} ariaLabel={`${r.name} — ${moneyCap.label}`} />
                                                </span>
                                            </td>
                                        )}
                                        <td className="whitespace-nowrap text-center text-[10px] font-bold">
                                            <button type="button" onClick={() => toggleRow(r.id, true)} className="text-primary hover:underline">semua</button>
                                            <span className="mx-1 opacity-40">·</span>
                                            <button type="button" onClick={() => toggleRow(r.id, false)} className="text-muted-foreground hover:text-danger-text hover:underline">nol</button>
                                        </td>
                                    </tr>
                                );
                            })}
                        </tbody>
                    </table>
                </div>
            </ListCard>
        </section>
    );
}

DashboardWidgetIndex.layout = [AppLayout];
