import AdminLayout from '@/Layouts/AdminLayout';
import { api } from '@/lib/api';
import { cn } from '@/lib/utils';
import { Head, router } from '@inertiajs/react';
import { ArrowLeft, ShieldCheck } from 'lucide-react';
import { useEffect, useRef, useState } from 'react';
import { toast } from 'sonner';

// ── Types ─────────────────────────────────────────────────────────────────────

interface Permission {
    id: number;
    name: string;
    label: string;
}

interface PermissionCategory {
    id: number;
    name: string;
    permissions: Permission[];
}

interface Role {
    id: number;
    name: string;
    description: string | null;
    is_protected: boolean;
    permissions: string[];
}

interface Props {
    role?: Role;
    permissionCategories: PermissionCategory[];
}

// ── Helpers ───────────────────────────────────────────────────────────────────

function toSnakeCase(raw: string): string {
    return raw
        .trim()
        .toLowerCase()
        .replace(/[\s-]+/g, '_')
        .replace(/[^a-z0-9_]/g, '')
        .replace(/_+/g, '_')
        .replace(/^_+|_+$/g, '');
}

function submitRole(data: {
    id?: number;
    name: string;
    description: string;
    permissions: string[];
}) {
    return data.id
        ? api.put(`/admin/roles/${data.id}`, data)
        : api.post('/admin/roles', data);
}

// ── Page ──────────────────────────────────────────────────────────────────────

export default function RolesForm({ role, permissionCategories }: Props) {
    const isEdit = !!role;
    const isProtected = role?.is_protected ?? false;

    const [rawName, setRawName] = useState(role?.name ?? '');
    const [snakeName, setSnakeName] = useState(role?.name ?? '');
    const [description, setDescription] = useState(role?.description ?? '');
    const [selected, setSelected] = useState<Set<string>>(
        new Set(role?.permissions ?? []),
    );
    const [errors, setErrors] = useState<Record<string, string>>({});
    const [saving, setSaving] = useState(false);
    const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);

    useEffect(() => {
        if (isProtected) return;
        if (debounceRef.current) clearTimeout(debounceRef.current);
        debounceRef.current = setTimeout(() => {
            setSnakeName(toSnakeCase(rawName));
        }, 400);
        return () => {
            if (debounceRef.current) clearTimeout(debounceRef.current);
        };
    }, [rawName, isProtected]);

    const allPerms = permissionCategories.flatMap((c) =>
        c.permissions.map((p) => p.name),
    );
    const allSel =
        allPerms.length > 0 && allPerms.every((n) => selected.has(n));
    const totalSel = selected.size;
    const showPreview =
        !isProtected && snakeName !== rawName && rawName.trim() !== '';

    const toggleAll = () => {
        setSelected(allSel ? new Set() : new Set(allPerms));
    };

    const toggleCategory = (cat: PermissionCategory) => {
        const allCatSel = cat.permissions.every((p) => selected.has(p.name));
        setSelected((prev) => {
            const next = new Set(prev);
            cat.permissions.forEach((p) =>
                allCatSel ? next.delete(p.name) : next.add(p.name),
            );
            return next;
        });
    };

    const togglePermission = (permName: string) => {
        setSelected((prev) => {
            const next = new Set(prev);
            if (next.has(permName)) {
                next.delete(permName);
            } else {
                next.add(permName);
            }
            return next;
        });
    };

    const handleSubmit = async (e: React.FormEvent) => {
        e.preventDefault();
        setErrors({});
        setSaving(true);

        const finalName = isProtected
            ? (role?.name ?? '')
            : toSnakeCase(rawName);

        try {
            await submitRole({
                id: role?.id,
                name: finalName,
                description: description.trim(),
                permissions: Array.from(selected),
            });

            toast.success(isEdit ? 'Role updated' : 'Role created');
            router.visit('/admin/roles');
        } catch (err) {
            const apiErr = err as {
                errors?: Record<string, string[]>;
                message?: string;
            };
            if (apiErr.errors) {
                const flat: Record<string, string> = {};
                Object.entries(apiErr.errors).forEach(([k, v]) => {
                    flat[k] = Array.isArray(v) ? (v[0] as string) : String(v);
                });
                setErrors(flat);
            } else {
                toast.error(apiErr.message ?? 'Failed to save role');
            }
        } finally {
            setSaving(false);
        }
    };

    const title = isEdit ? `Edit: ${role!.name}` : 'New Role';

    return (
        <AdminLayout
            title={title}
            breadcrumbs={[
                { label: 'System' },
                { label: 'Roles', href: '/admin/roles' },
                { label: isEdit ? role!.name : 'New Role' },
            ]}
        >
            <Head title={title} />

            <div className="p-6 lg:p-8">
                <form
                    onSubmit={handleSubmit}
                    className="flex flex-col gap-6 pb-10"
                >
                    {/* ── Page title row ─────────────────────────────────────── */}
                    <div className="flex items-center gap-3">
                        <button
                            type="button"
                            onClick={() => router.visit('/admin/roles')}
                            className="border-border text-muted-foreground hover:bg-muted/40 hover:text-foreground flex h-8 w-8 shrink-0 items-center justify-center rounded-lg border transition-colors"
                        >
                            <ArrowLeft className="h-4 w-4" />
                        </button>
                        <ShieldCheck className="text-primary h-5 w-5" />
                        <h1 className="text-foreground text-lg font-bold">
                            {isEdit ? 'Edit Role' : 'New Role'}
                        </h1>
                        {isProtected && (
                            <span className="rounded-full bg-amber-500/10 px-2.5 py-0.5 text-xs font-semibold text-amber-600 dark:text-amber-400">
                                Protected
                            </span>
                        )}
                    </div>

                    {/* ── Two-column body ────────────────────────────────────── */}
                    <div className="grid grid-cols-1 gap-6 lg:grid-cols-[1fr_2fr]">
                        {/* ── Left: Details ────────────────────────────────── */}
                        <div className="flex flex-col gap-6">
                            <div className="pf-glass space-y-5 rounded-xl p-6">
                                <p className="text-muted-foreground dark:text-muted-foreground/65 text-[10px] font-bold tracking-widest uppercase">
                                    Role details
                                </p>

                                {/* Name */}
                                <div className="space-y-1.5">
                                    <label className="text-muted-foreground block text-xs font-semibold tracking-wide uppercase">
                                        Role name{' '}
                                        <span className="text-destructive">
                                            *
                                        </span>
                                    </label>
                                    <input
                                        value={rawName}
                                        onChange={(e) =>
                                            setRawName(e.target.value)
                                        }
                                        placeholder="e.g. Billing Admin"
                                        disabled={isProtected}
                                        autoComplete="off"
                                        className={cn(
                                            'bg-card dark:bg-muted/30 w-full rounded-lg border px-3 py-2.5 text-sm transition-colors outline-none',
                                            'placeholder:text-muted-foreground dark:placeholder:text-muted-foreground/60',
                                            'focus:border-primary/50 focus:ring-primary/20 focus:ring-1',
                                            errors.name
                                                ? 'border-destructive'
                                                : 'border-border',
                                            isProtected &&
                                                'cursor-not-allowed opacity-60',
                                        )}
                                    />
                                    {showPreview && (
                                        <p className="text-muted-foreground flex items-center gap-1.5 text-[11px]">
                                            <span className="text-muted-foreground dark:text-muted-foreground/65">
                                                →
                                            </span>
                                            <code className="text-foreground/80 font-mono">
                                                {snakeName}
                                            </code>
                                            <span className="text-muted-foreground dark:text-muted-foreground/65">
                                                will be saved
                                            </span>
                                        </p>
                                    )}
                                    {errors.name && (
                                        <p className="text-destructive text-xs">
                                            {errors.name}
                                        </p>
                                    )}
                                    {!isProtected && !errors.name && (
                                        <p className="text-muted-foreground text-[11px]">
                                            Converted to snake_case
                                            automatically. Must be unique.
                                        </p>
                                    )}
                                    {isProtected && (
                                        <p className="text-muted-foreground text-[11px]">
                                            The super admin role name cannot be
                                            changed.
                                        </p>
                                    )}
                                </div>

                                {/* Description */}
                                <div className="space-y-1.5">
                                    <label className="text-muted-foreground block text-xs font-semibold tracking-wide uppercase">
                                        Description
                                    </label>
                                    <textarea
                                        value={description}
                                        onChange={(e) =>
                                            setDescription(e.target.value)
                                        }
                                        rows={4}
                                        placeholder="Describe what this role is responsible for…"
                                        className={cn(
                                            'border-border bg-card dark:bg-muted/30 w-full resize-none rounded-lg border px-3 py-2.5 text-sm transition-colors outline-none',
                                            'placeholder:text-muted-foreground dark:placeholder:text-muted-foreground/60 focus:border-primary/50 focus:ring-primary/20 focus:ring-1',
                                        )}
                                    />
                                </div>
                            </div>

                            {/* Actions */}
                            <div className="flex items-center justify-end gap-3">
                                <button
                                    type="button"
                                    onClick={() => router.visit('/admin/roles')}
                                    className="border-border text-muted-foreground hover:bg-muted/40 rounded-lg border px-5 py-2.5 text-sm font-medium transition-colors"
                                >
                                    Cancel
                                </button>
                                <button
                                    type="submit"
                                    disabled={saving}
                                    className="bg-primary text-primary-foreground hover:bg-primary/90 rounded-lg px-5 py-2.5 text-sm font-semibold transition-colors disabled:opacity-60"
                                >
                                    {saving
                                        ? 'Saving…'
                                        : isEdit
                                          ? 'Save changes'
                                          : 'Create role'}
                                </button>
                            </div>
                        </div>

                        {/* ── Right: Permissions ──────────────────────────── */}
                        <div className="pf-glass flex flex-col overflow-hidden rounded-xl">
                            {/* Permissions header */}
                            <div className="border-border/60 flex shrink-0 items-center justify-between border-b px-6 py-4">
                                <div>
                                    <p className="text-muted-foreground dark:text-muted-foreground/65 text-[10px] font-bold tracking-widest uppercase">
                                        Permissions
                                    </p>
                                    <p className="text-foreground mt-0.5 text-sm font-medium">
                                        {totalSel} of {allPerms.length} selected
                                    </p>
                                </div>
                                {isProtected ? (
                                    <span className="text-muted-foreground text-xs">
                                        Super admin bypasses all permission
                                        checks
                                    </span>
                                ) : (
                                    <button
                                        type="button"
                                        onClick={toggleAll}
                                        className={cn(
                                            'rounded-lg border px-3 py-1.5 text-xs font-semibold transition-colors',
                                            allSel
                                                ? 'border-border text-muted-foreground hover:bg-muted/40'
                                                : 'border-primary/30 bg-primary/5 text-primary hover:bg-primary/10',
                                        )}
                                    >
                                        {allSel ? 'Deselect all' : 'Select all'}
                                    </button>
                                )}
                            </div>

                            {/* Scrollable permissions list */}
                            <div
                                className="admin-scrollbar overflow-y-auto"
                                style={{
                                    maxHeight: 'calc(100vh - 260px)',
                                    minHeight: '480px',
                                }}
                            >
                                <div className="divide-border/40 divide-y">
                                    {permissionCategories.map((cat) => {
                                        const catSel = cat.permissions.filter(
                                            (p) => selected.has(p.name),
                                        ).length;
                                        const catTotal = cat.permissions.length;
                                        const allCatSel = catSel === catTotal;

                                        return (
                                            <div
                                                key={cat.id}
                                                className="px-6 py-4"
                                            >
                                                <div className="mb-3 flex items-center justify-between">
                                                    <div className="flex items-center gap-2">
                                                        <span className="text-muted-foreground dark:text-muted-foreground/60 text-[10px] font-bold tracking-widest uppercase">
                                                            {cat.name}
                                                        </span>
                                                        <span className="bg-muted text-muted-foreground rounded-full px-1.5 py-0.5 text-[10px] font-semibold tabular-nums">
                                                            {catSel}/{catTotal}
                                                        </span>
                                                    </div>
                                                    {!isProtected && (
                                                        <button
                                                            type="button"
                                                            onClick={() =>
                                                                toggleCategory(
                                                                    cat,
                                                                )
                                                            }
                                                            className="text-primary text-[11px] font-medium hover:underline"
                                                        >
                                                            {allCatSel
                                                                ? 'Deselect all'
                                                                : 'Select all'}
                                                        </button>
                                                    )}
                                                </div>

                                                <div className="grid gap-2 sm:grid-cols-2 xl:grid-cols-3">
                                                    {cat.permissions.map(
                                                        (perm) => {
                                                            const checked =
                                                                selected.has(
                                                                    perm.name,
                                                                );
                                                            return (
                                                                <label
                                                                    key={
                                                                        perm.id
                                                                    }
                                                                    className={cn(
                                                                        'flex min-h-[56px] cursor-pointer items-start gap-3 rounded-lg border px-3 py-2.5 transition-all',
                                                                        checked
                                                                            ? 'border-primary/30 bg-primary/5'
                                                                            : 'bg-muted/30 hover:border-border hover:bg-muted/50 border-transparent',
                                                                        isProtected &&
                                                                            'pointer-events-none opacity-40',
                                                                    )}
                                                                >
                                                                    <input
                                                                        type="checkbox"
                                                                        checked={
                                                                            checked
                                                                        }
                                                                        disabled={
                                                                            isProtected
                                                                        }
                                                                        onChange={() =>
                                                                            !isProtected &&
                                                                            togglePermission(
                                                                                perm.name,
                                                                            )
                                                                        }
                                                                        className="border-border accent-primary mt-0.5 h-3.5 w-3.5 shrink-0 rounded"
                                                                    />
                                                                    <div className="min-w-0">
                                                                        <p className="text-foreground text-xs leading-tight font-medium">
                                                                            {
                                                                                perm.label
                                                                            }
                                                                        </p>
                                                                        <p className="text-muted-foreground dark:text-muted-foreground/60 mt-0.5 font-mono text-[10px]">
                                                                            {
                                                                                perm.name
                                                                            }
                                                                        </p>
                                                                    </div>
                                                                </label>
                                                            );
                                                        },
                                                    )}
                                                </div>
                                            </div>
                                        );
                                    })}
                                </div>
                            </div>
                        </div>
                    </div>
                </form>
            </div>
        </AdminLayout>
    );
}
