import AdminLayout from '@/Layouts/AdminLayout';
import { DataTable, type TableMeta } from '@/components/admin/DataTable';
import PageHeader from '@/components/admin/PageHeader';
import {
    DropdownMenu,
    DropdownMenuContent,
    DropdownMenuItem,
    DropdownMenuSeparator,
    DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { useDataTable, type TableParams } from '@/hooks/useDataTable';
import { useDeleteWithUndo } from '@/hooks/useDeleteWithUndo';
import { api } from '@/lib/api';
import { parseServerDate } from '@/lib/date';
import { cn } from '@/lib/utils';
import { Head, Link } from '@inertiajs/react';
import {
    keepPreviousData,
    useQuery,
    useQueryClient,
} from '@tanstack/react-query';
import type { ColumnDef } from '@tanstack/react-table';
import { format } from 'date-fns';
import { KeyRound, Lock, MoreHorizontal, Plus, Trash2 } from 'lucide-react';
import { toast } from 'sonner';

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

interface RoleRow {
    id: number;
    name: string;
    description: string | null;
    is_protected: boolean;
    permissions_count: number;
    users_count: number;
    created_at: string;
}

interface RolesResponse {
    data: RoleRow[];
    meta: TableMeta;
    filter_counts: Record<string, number>;
}

// ── API helpers ───────────────────────────────────────────────────────────────

function fetchRoles(params: TableParams): Promise<RolesResponse> {
    const sp = new URLSearchParams({ page: String(params.page) });
    if (params.sort) sp.set('sort', params.sort);
    if (params.dir !== 'asc') sp.set('dir', params.dir);
    if (params.search) sp.set('search', params.search);
    return api.get(`/admin/api/roles?${sp}`);
}

const apiDelete = (id: number) => api.delete(`/admin/roles/${id}`);
const apiRestore = (id: number) => api.post(`/admin/roles/${id}/restore`);
const apiBulkDelete = (ids: number[]) =>
    api.post('/admin/roles/bulk-delete', { ids });
const apiBulkRestore = (ids: number[]) =>
    api.post('/admin/roles/bulk-restore', { ids });

// ── Row actions ───────────────────────────────────────────────────────────────

function RowActions({
    role,
    onDelete,
}: {
    role: RoleRow;
    onDelete: (r: RoleRow) => void;
}) {
    if (role.is_protected) return null;

    return (
        <DropdownMenu>
            <DropdownMenuTrigger asChild>
                <button className="text-muted-foreground hover:bg-muted/60 hover:text-foreground flex h-7 w-7 items-center justify-center rounded-md transition-colors focus:outline-none">
                    <MoreHorizontal className="h-4 w-4" />
                    <span className="sr-only">Actions</span>
                </button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end" className="w-44">
                <DropdownMenuItem asChild className="gap-2 text-xs">
                    <Link href={`/admin/roles/${role.id}/edit`}>
                        <KeyRound className="h-3.5 w-3.5" />
                        Edit role
                    </Link>
                </DropdownMenuItem>
                <DropdownMenuSeparator />
                <DropdownMenuItem
                    className="gap-2 text-xs text-red-600 focus:text-red-600 dark:text-red-400 dark:focus:text-red-400"
                    onClick={() => onDelete(role)}
                >
                    <Trash2 className="h-3.5 w-3.5" />
                    Delete
                </DropdownMenuItem>
            </DropdownMenuContent>
        </DropdownMenu>
    );
}

// ── Empty meta ────────────────────────────────────────────────────────────────

const EMPTY_META: TableMeta = {
    current_page: 1,
    last_page: 1,
    total: 0,
    per_page: 25,
    from: 0,
    to: 0,
};

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

export default function RolesIndex() {
    const qc = useQueryClient();
    const { params, setParams } = useDataTable({ sort: 'name', dir: 'asc' });
    const { deleteWithUndo } = useDeleteWithUndo();

    const { data, isLoading, isFetching } = useQuery({
        queryKey: ['admin.roles', params],
        queryFn: () => fetchRoles(params),
        placeholderData: keepPreviousData,
    });

    const invalidate = () =>
        qc.invalidateQueries({ queryKey: ['admin.roles'] });

    const handleDelete = (role: RoleRow) => {
        deleteWithUndo({
            noun: 'role',
            onDelete: () => apiDelete(role.id),
            onUndo: () => apiRestore(role.id),
            onSuccess: invalidate,
        });
    };

    const handleBulkDelete = (rows: RoleRow[]) => {
        const deletable = rows.filter((r) => !r.is_protected);
        if (!deletable.length) {
            toast.error(
                'No deletable roles selected (super admin is protected)',
            );
            return;
        }
        const ids = deletable.map((r) => r.id);
        deleteWithUndo({
            noun: 'role',
            count: ids.length,
            onDelete: () => apiBulkDelete(ids),
            onUndo: () => apiBulkRestore(ids),
            onSuccess: invalidate,
        });
    };

    const exportUrl = (() => {
        const sp = new URLSearchParams();
        if (params.search) sp.set('search', params.search);
        const qs = sp.toString();
        return `/admin/roles/export${qs ? `?${qs}` : ''}`;
    })();

    const columns: ColumnDef<RoleRow, unknown>[] = [
        {
            accessorKey: 'name',
            header: 'Role',
            meta: { sortable: true, label: 'Role' },
            cell: ({ row }) => (
                <div className="flex min-w-0 items-start gap-2">
                    <div className="min-w-0">
                        <div className="flex items-center gap-2">
                            <p className="text-foreground font-mono text-sm font-medium">
                                {row.original.name}
                            </p>
                            {row.original.is_protected && (
                                <span className="inline-flex items-center gap-1 rounded-full bg-amber-500/10 px-1.5 py-0.5 text-[10px] font-semibold text-amber-600 dark:text-amber-400">
                                    <Lock className="h-2.5 w-2.5" />
                                    Protected
                                </span>
                            )}
                        </div>
                        {row.original.description && (
                            <p className="text-muted-foreground mt-0.5 max-w-xs truncate text-[11px]">
                                {row.original.description}
                            </p>
                        )}
                    </div>
                </div>
            ),
        },
        {
            accessorKey: 'permissions_count',
            header: 'Permissions',
            meta: { sortable: true, label: 'Permissions' },
            cell: ({ row }) => (
                <span className="text-foreground/80 text-sm tabular-nums">
                    {row.original.permissions_count}
                </span>
            ),
        },
        {
            accessorKey: 'users_count',
            header: 'Admins',
            meta: { sortable: true, label: 'Admins' },
            cell: ({ row }) => (
                <span className="text-foreground/80 text-sm tabular-nums">
                    {row.original.users_count}
                </span>
            ),
        },
        {
            accessorKey: 'created_at',
            header: 'Created',
            meta: { sortable: true, label: 'Created' },
            cell: ({ row }) => (
                <span className="text-muted-foreground text-xs tabular-nums">
                    {format(
                        parseServerDate(row.original.created_at),
                        'dd MMM yyyy',
                    )}
                </span>
            ),
        },
        {
            id: '_actions',
            header: '',
            cell: ({ row }) => (
                <RowActions role={row.original} onDelete={handleDelete} />
            ),
            enableHiding: false,
        },
    ];

    return (
        <AdminLayout title="Roles">
            <Head title="Roles" />

            <div className="space-y-6 p-6 lg:p-8">
                <PageHeader
                    title="Roles"
                    description="Define what each admin role can access within the platform"
                    action={
                        <div className="flex items-center gap-2">
                            <Link
                                href="/admin/roles/trash"
                                className={cn(
                                    'border-border flex items-center gap-1.5 rounded-lg border px-3 py-2',
                                    'text-muted-foreground hover:bg-muted/40 hover:text-foreground text-xs font-medium transition-colors',
                                )}
                            >
                                <Trash2 className="h-3.5 w-3.5" />
                                Trash
                            </Link>
                            <Link
                                href="/admin/roles/create"
                                className="bg-primary text-primary-foreground hover:bg-primary/90 flex items-center gap-1.5 rounded-lg px-3 py-2 text-xs font-semibold transition-colors"
                            >
                                <Plus className="h-3.5 w-3.5" />
                                New role
                            </Link>
                        </div>
                    }
                />

                <DataTable
                    columns={columns}
                    data={data?.data ?? []}
                    meta={data?.meta ?? EMPTY_META}
                    params={params}
                    isLoading={isLoading}
                    isFetching={isFetching}
                    onParamsChange={setParams}
                    quickFilters={[
                        {
                            label: 'All',
                            value: 'all',
                            count: data?.filter_counts.all,
                        },
                    ]}
                    bulkActions={[
                        {
                            label: 'Delete',
                            icon: Trash2,
                            onClick: handleBulkDelete,
                            variant: 'destructive',
                        },
                    ]}
                    exportUrl={exportUrl}
                    onRefresh={invalidate}
                    searchPlaceholder="Search roles…"
                    noun="roles"
                    getRowId={(row) => String(row.id)}
                />
            </div>
        </AdminLayout>
    );
}
