import React, { useEffect, useState, useMemo, useCallback } from "react";
import { Card, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import { Checkbox } from "@/components/ui/checkbox";
import {
    Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger,
} from "@/components/ui/dialog";
import { Shield, Plus, Save, Trash2, Copy, Lock, Search, KeyRound } from "lucide-react";
import { toast } from "sonner";
import { api } from "@/lib/api";
import { useAuth } from "@/context/AuthContext";

const ACTION_LABELS = {
    view: "View", create: "Create", edit: "Edit", delete: "Delete",
    void: "Void", print: "Print", export: "Export", import: "Import",
    bulk_update: "Bulk Edit", transfer: "Transfer", file: "File Return",
    configure: "Configure", sync: "Sync", use: "Use", assign_role: "Assign Role",
    restore: "Restore", purge: "Purge",
};

export default function RolesAndPermissions() {
    const { isAdmin } = useAuth();
    const [catalog, setCatalog] = useState({ modules: [] });
    const [roles, setRoles] = useState([]);
    const [selectedRole, setSelectedRole] = useState(null);
    const [editPerms, setEditPerms] = useState([]);
    const [dirty, setDirty] = useState(false);
    const [search, setSearch] = useState("");
    const [createOpen, setCreateOpen] = useState(false);
    const [newRole, setNewRole] = useState({ name: "", label: "", from: "viewer" });

    const load = useCallback(async () => {
        try {
            const [cat, r] = await Promise.all([
                api.get("/permissions/catalog"),
                api.get("/permissions/roles"),
            ]);
            setCatalog(cat.data);
            setRoles(r.data.roles || []);
            if (!selectedRole && r.data.roles?.length) {
                const initial = r.data.roles.find((x) => x.name === "manager") || r.data.roles[0];
                setSelectedRole(initial.name);
                setEditPerms(initial.permissions);
            }
        } catch (e) { toast.error("Failed to load roles"); }
    }, [selectedRole]);

    useEffect(() => { load(); }, []); // eslint-disable-line

    const currentRole = useMemo(() => roles.find((r) => r.name === selectedRole), [roles, selectedRole]);
    const isPreset = currentRole?.preset;
    const isSuper = currentRole?.permissions?.includes("*");

    const pickRole = (name) => {
        if (dirty && !window.confirm("Discard unsaved changes?")) return;
        const r = roles.find((x) => x.name === name);
        if (!r) return;
        setSelectedRole(name);
        setEditPerms(r.permissions || []);
        setDirty(false);
    };

    const togglePerm = (p) => {
        if (isPreset || isSuper) return;
        setEditPerms((cur) => {
            const has = cur.includes(p);
            const next = has ? cur.filter((x) => x !== p) : [...cur, p];
            setDirty(true);
            return next;
        });
    };

    const toggleModule = (mod, on) => {
        if (isPreset || isSuper) return;
        const modPerms = mod.permissions;
        setEditPerms((cur) => {
            const without = cur.filter((p) => !modPerms.includes(p));
            const next = on ? [...without, ...modPerms] : without;
            setDirty(true);
            return next;
        });
    };

    const save = async () => {
        if (!currentRole || isPreset) return;
        try {
            await api.put(`/permissions/roles/${currentRole.name}`, {
                name: currentRole.name,
                label: currentRole.label,
                permissions: editPerms,
            });
            toast.success(`Role "${currentRole.label}" saved`);
            setDirty(false);
            load();
        } catch (e) { toast.error(e.response?.data?.detail || "Save failed"); }
    };

    const createRole = async () => {
        const name = (newRole.name || "").trim().toLowerCase().replace(/\s+/g, "_");
        if (!name) { toast.error("Role name required"); return; }
        const base = roles.find((r) => r.name === newRole.from);
        try {
            await api.post("/permissions/roles", {
                name,
                label: newRole.label || name,
                permissions: base?.preset && base.permissions[0] === "*" ? [] : (base?.permissions || []),
            });
            toast.success("Role created");
            setCreateOpen(false);
            setNewRole({ name: "", label: "", from: "viewer" });
            await load();
            setSelectedRole(name);
        } catch (e) { toast.error(e.response?.data?.detail || "Create failed"); }
    };

    const deleteRole = async () => {
        if (!currentRole || isPreset) return;
        if (!window.confirm(`Delete "${currentRole.label}"? This cannot be undone.`)) return;
        try {
            await api.delete(`/permissions/roles/${currentRole.name}`);
            toast.success("Role deleted");
            setSelectedRole(null);
            load();
        } catch (e) { toast.error(e.response?.data?.detail || "Delete failed"); }
    };

    if (!isAdmin) {
        return (
            <div className="max-w-2xl mx-auto p-6 text-center">
                <Lock className="h-10 w-10 mx-auto text-muted-foreground mb-3" />
                <h2 className="font-display text-xl font-bold">Admin Only</h2>
                <p className="text-sm text-muted-foreground mt-1">Only administrators can manage roles & permissions.</p>
            </div>
        );
    }

    const filteredModules = catalog.modules.filter((m) =>
        !search || m.label.toLowerCase().includes(search.toLowerCase()) || m.key.includes(search.toLowerCase())
    );

    return (
        <div className="space-y-5" data-testid="roles-page">
            <div className="flex flex-wrap items-end justify-between gap-3">
                <div>
                    <div className="label-cap">Admin · Security</div>
                    <h1 className="font-display text-3xl font-bold tracking-tight flex items-center gap-2">
                        <Shield className="h-7 w-7 text-primary" /> Roles & Permissions
                    </h1>
                    <p className="text-sm text-muted-foreground mt-1">
                        Granular access control — {catalog.modules.length} modules, {catalog.modules.reduce((s, m) => s + m.permissions.length, 0)} permissions.
                    </p>
                </div>
                <Dialog open={createOpen} onOpenChange={setCreateOpen}>
                    <DialogTrigger asChild>
                        <Button className="bg-primary hover:bg-primary/90" data-testid="add-role-btn">
                            <Plus className="h-4 w-4 mr-1.5" /> Create Custom Role
                        </Button>
                    </DialogTrigger>
                    <DialogContent>
                        <DialogHeader><DialogTitle>Create Custom Role</DialogTitle></DialogHeader>
                        <div className="space-y-3">
                            <div>
                                <label className="text-xs font-semibold uppercase text-muted-foreground">Display Name</label>
                                <Input value={newRole.label} onChange={(e) => setNewRole({ ...newRole, label: e.target.value })} placeholder="Sales Manager" data-testid="role-label" />
                            </div>
                            <div>
                                <label className="text-xs font-semibold uppercase text-muted-foreground">Internal Name (lowercase, no spaces)</label>
                                <Input value={newRole.name} onChange={(e) => setNewRole({ ...newRole, name: e.target.value })} placeholder="sales_manager" className="font-mono" data-testid="role-name" />
                            </div>
                            <div>
                                <label className="text-xs font-semibold uppercase text-muted-foreground">Clone Permissions From</label>
                                <select
                                    value={newRole.from}
                                    onChange={(e) => setNewRole({ ...newRole, from: e.target.value })}
                                    className="w-full h-9 rounded-md border bg-background px-2 text-sm"
                                    data-testid="role-clone-from"
                                >
                                    {roles.map((r) => <option key={r.name} value={r.name}>{r.label}</option>)}
                                </select>
                            </div>
                        </div>
                        <DialogFooter>
                            <Button variant="outline" onClick={() => setCreateOpen(false)}>Cancel</Button>
                            <Button onClick={createRole} data-testid="role-create-save">Create</Button>
                        </DialogFooter>
                    </DialogContent>
                </Dialog>
            </div>

            <div className="grid grid-cols-1 lg:grid-cols-[260px_1fr] gap-5">
                {/* Roles sidebar */}
                <Card>
                    <CardContent className="p-2">
                        <div className="space-y-1">
                            {roles.map((r) => (
                                <button
                                    key={r.name}
                                    type="button"
                                    onClick={() => pickRole(r.name)}
                                    data-testid={`role-${r.name}`}
                                    className={`w-full text-left rounded-md px-3 py-2 text-sm transition flex items-center justify-between ${selectedRole === r.name ? "bg-primary/10 border border-primary/40" : "hover:bg-muted/50"}`}
                                >
                                    <div className="min-w-0">
                                        <div className="font-medium truncate flex items-center gap-1.5">
                                            <KeyRound className="h-3 w-3" />{r.label}
                                        </div>
                                        <div className="text-[10px] text-muted-foreground mt-0.5">
                                            {r.preset && <Badge variant="outline" className="text-[9px] mr-1 border-amber-500/50 text-amber-700 dark:text-amber-400">PRESET</Badge>}
                                            {r.permissions?.includes("*") ? "Super admin (all)" : `${r.permissions?.length || 0} perms`}
                                        </div>
                                    </div>
                                </button>
                            ))}
                        </div>
                    </CardContent>
                </Card>

                {/* Matrix */}
                <Card>
                    <CardContent className="p-5">
                        {!currentRole ? (
                            <div className="text-center py-12 text-muted-foreground text-sm">Pick a role on the left to view permissions.</div>
                        ) : (
                            <>
                                <div className="flex flex-wrap items-center justify-between gap-3 pb-3 mb-3 border-b">
                                    <div>
                                        <h2 className="font-display text-lg font-bold flex items-center gap-2">
                                            {currentRole.label}
                                            {isPreset && <Badge variant="outline" className="text-[10px] border-amber-500/50 text-amber-700 dark:text-amber-400">Read-only preset</Badge>}
                                            {isSuper && <Badge variant="default" className="text-[10px] bg-emerald-600">SUPER ADMIN</Badge>}
                                        </h2>
                                        <p className="text-xs text-muted-foreground mt-0.5 font-mono">{currentRole.name}</p>
                                    </div>
                                    <div className="flex items-center gap-2">
                                        <div className="relative">
                                            <Search className="absolute left-2 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground" />
                                            <Input value={search} onChange={(e) => setSearch(e.target.value)} placeholder="Filter modules" className="h-8 pl-7 w-48" data-testid="perms-filter" />
                                        </div>
                                        {!isPreset && (
                                            <Button variant="outline" size="sm" onClick={deleteRole} className="text-destructive" data-testid="role-delete">
                                                <Trash2 className="h-3.5 w-3.5 mr-1" /> Delete
                                            </Button>
                                        )}
                                        <Button onClick={save} disabled={!dirty || isPreset || isSuper} className="bg-primary hover:bg-primary/90" data-testid="perms-save">
                                            <Save className="h-3.5 w-3.5 mr-1" /> Save Changes
                                        </Button>
                                    </div>
                                </div>

                                {isSuper && (
                                    <div className="rounded-lg border border-emerald-500/30 bg-emerald-50/50 dark:bg-emerald-950/20 p-4 text-sm">
                                        Admin role has <strong>full access</strong> to every module. Cannot be customised.
                                    </div>
                                )}

                                {!isSuper && (
                                    <div className="space-y-3 max-h-[60vh] overflow-y-auto pr-2" data-testid="perms-matrix">
                                        {filteredModules.map((mod) => {
                                            const granted = mod.permissions.filter((p) => editPerms.includes(p)).length;
                                            const all = granted === mod.permissions.length;
                                            return (
                                                <div key={mod.key} className="rounded-lg border bg-card p-3">
                                                    <div className="flex items-center justify-between mb-2">
                                                        <div>
                                                            <div className="font-display font-semibold text-sm">{mod.label}</div>
                                                            <div className="text-[10px] text-muted-foreground font-mono">{mod.key} · {granted}/{mod.permissions.length}</div>
                                                        </div>
                                                        <label className="flex items-center gap-2 text-xs cursor-pointer">
                                                            <Checkbox checked={all} onCheckedChange={(c) => toggleModule(mod, !!c)} disabled={isPreset} data-testid={`perms-mod-${mod.key}-all`} />
                                                            <span className="text-muted-foreground">All</span>
                                                        </label>
                                                    </div>
                                                    <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-1.5">
                                                        {mod.actions.map((act) => {
                                                            const p = `${mod.key}.${act}`;
                                                            const on = editPerms.includes(p);
                                                            return (
                                                                <label
                                                                    key={p}
                                                                    className={`flex items-center gap-1.5 rounded px-2 py-1 text-xs transition cursor-pointer border ${on ? "bg-primary/10 border-primary/30" : "bg-muted/30 border-transparent hover:border-border"} ${(isPreset || isSuper) ? "opacity-70 cursor-not-allowed" : ""}`}
                                                                    data-testid={`perm-${p}`}
                                                                >
                                                                    <Checkbox checked={on} onCheckedChange={() => togglePerm(p)} disabled={isPreset || isSuper} className="h-3.5 w-3.5" />
                                                                    <span className="truncate">{ACTION_LABELS[act] || act}</span>
                                                                </label>
                                                            );
                                                        })}
                                                    </div>
                                                </div>
                                            );
                                        })}
                                    </div>
                                )}
                            </>
                        )}
                    </CardContent>
                </Card>
            </div>
        </div>
    );
}
