'use client';

import { useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { type ColumnDef } from '@tanstack/react-table';
import { Pencil, Trash2, Plus, Lock } from 'lucide-react';

import { DataTable } from '@/components/shared/data-table';
import { PageHeader } from '@/components/shared/page-header';
import { ConfirmationDialog } from '@/components/shared/confirmation-dialog';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import { apiFetch } from '@/lib/api/client';
import { formatRole } from '@/lib/constants';
import { RoleForm } from './role-form';

interface Role {
  id: string;
  name: string;
  description: string | null;
  isSystem: boolean;
  isGlobal: boolean;
  permissions: Record<string, Record<string, boolean>>;
  createdAt: string;
}

const ROLES_QUERY_KEY = ['admin', 'roles'] as const;

export function RoleList() {
  const queryClient = useQueryClient();
  const [formOpen, setFormOpen] = useState(false);
  const [editingRole, setEditingRole] = useState<Role | null>(null);
  const [viewingPermissions, setViewingPermissions] = useState<Role | null>(null);

  const { data: roles = [], isLoading: loading } = useQuery<Role[]>({
    queryKey: ROLES_QUERY_KEY,
    queryFn: () => apiFetch<{ data: Role[] }>('/api/v1/admin/roles').then((r) => r.data),
  });

  const deleteMutation = useMutation({
    mutationFn: (id: string) => apiFetch(`/api/v1/admin/roles/${id}`, { method: 'DELETE' }),
    onSuccess: () => queryClient.invalidateQueries({ queryKey: ROLES_QUERY_KEY }),
  });

  const fetchRoles = () => queryClient.invalidateQueries({ queryKey: ROLES_QUERY_KEY });

  function handleNewRole() {
    setEditingRole(null);
    setFormOpen(true);
  }

  function handleEditRole(role: Role) {
    setEditingRole(role);
    setFormOpen(true);
  }

  function countPermissions(perms: Record<string, Record<string, boolean>>): string {
    let granted = 0;
    let total = 0;
    for (const group of Object.values(perms)) {
      for (const val of Object.values(group)) {
        total++;
        if (val) granted++;
      }
    }
    return `${granted}/${total}`;
  }

  const columns: ColumnDef<Role, unknown>[] = [
    {
      accessorKey: 'name',
      header: 'Name',
      cell: ({ row }) => (
        <div className="flex items-center gap-2">
          {/* Display-normalize: snake_case → "Snake Case" so admin-
              created roles with arbitrary keys still read cleanly.
              The underlying name is stored verbatim and is what code
              checks against  -  display is purely cosmetic. */}
          <span className="font-medium">{formatRole(row.original.name)}</span>
          {row.original.isSystem && (
            <Badge variant="outline" className="text-xs">
              <Lock className="mr-1 h-3 w-3" aria-hidden />
              System
            </Badge>
          )}
        </div>
      ),
    },
    {
      accessorKey: 'description',
      header: 'Description',
      cell: ({ row }) => (
        <span className="text-muted-foreground text-sm">{row.original.description ?? '-'}</span>
      ),
    },
    {
      id: 'permissions',
      header: 'Permissions',
      cell: ({ row }) => (
        <button
          type="button"
          onClick={() => setViewingPermissions(row.original)}
          className="inline-flex"
          title="View permission breakdown"
        >
          <Badge
            variant="secondary"
            className="cursor-pointer hover:bg-secondary/80 transition-colors"
          >
            {countPermissions(row.original.permissions)}
          </Badge>
        </button>
      ),
    },
    {
      id: 'actions',
      header: '',
      cell: ({ row }) => (
        <div className="flex items-center justify-end gap-1">
          <Button variant="ghost" size="sm" onClick={() => handleEditRole(row.original)}>
            <Pencil className="h-4 w-4" aria-hidden />
            <span className="sr-only">Edit</span>
          </Button>
          {!row.original.isSystem && (
            <ConfirmationDialog
              trigger={
                <Button
                  variant="ghost"
                  size="sm"
                  className="text-destructive hover:text-destructive"
                >
                  <Trash2 className="h-4 w-4" aria-hidden />
                  <span className="sr-only">Delete</span>
                </Button>
              }
              title="Delete Role"
              description={`Delete "${row.original.name}"? Users assigned to this role must be reassigned first.`}
              confirmLabel="Delete"
              onConfirm={() => deleteMutation.mutate(row.original.id)}
              loading={deleteMutation.isPending && deleteMutation.variables === row.original.id}
            />
          )}
        </div>
      ),
      enableSorting: false,
      size: 80,
    },
  ];

  return (
    <div>
      <PageHeader
        title="Role Management"
        description="Manage roles and their permissions"
        actions={
          <Button onClick={handleNewRole}>
            <Plus className="mr-1.5 h-4 w-4" aria-hidden />
            New Role
          </Button>
        }
      />

      <DataTable
        columns={columns}
        data={roles}
        isLoading={loading}
        getRowId={(row) => row.id}
        cardRender={({ original }) => (
          <div className="rounded-xl border border-border bg-card p-4 shadow-sm">
            <div className="flex items-start justify-between gap-3">
              <div className="min-w-0 flex-1">
                <div className="flex items-center gap-2">
                  <p className="truncate text-sm font-semibold text-foreground">
                    {formatRole(original.name)}
                  </p>
                  {original.isSystem ? (
                    <Badge variant="outline" className="text-xs">
                      <Lock className="mr-1 h-3 w-3" aria-hidden />
                      System
                    </Badge>
                  ) : null}
                </div>
                {original.description ? (
                  <p className="mt-1 text-xs text-muted-foreground">{original.description}</p>
                ) : null}
                <button
                  type="button"
                  onClick={() => setViewingPermissions(original)}
                  className="mt-2 inline-flex"
                  title="View permission breakdown"
                >
                  <Badge variant="secondary" className="cursor-pointer hover:bg-secondary/80">
                    {countPermissions(original.permissions)} permissions
                  </Badge>
                </button>
              </div>
              <div className="flex shrink-0 items-center gap-1">
                <Button
                  variant="ghost"
                  size="sm"
                  onClick={() => handleEditRole(original)}
                  aria-label="Edit role"
                >
                  <Pencil className="h-4 w-4" aria-hidden />
                </Button>
                {!original.isSystem ? (
                  <ConfirmationDialog
                    trigger={
                      <Button
                        variant="ghost"
                        size="sm"
                        className="text-destructive hover:text-destructive"
                        aria-label="Delete role"
                      >
                        <Trash2 className="h-4 w-4" aria-hidden />
                      </Button>
                    }
                    title="Delete Role"
                    description={`Delete "${original.name}"? Users assigned to this role must be reassigned first.`}
                    confirmLabel="Delete"
                    onConfirm={() => deleteMutation.mutate(original.id)}
                    loading={deleteMutation.isPending && deleteMutation.variables === original.id}
                  />
                ) : null}
              </div>
            </div>
          </div>
        )}
        emptyState={
          <div className="text-center py-8">
            <p className="text-muted-foreground">No roles defined.</p>
          </div>
        }
      />

      <RoleForm
        open={formOpen}
        onOpenChange={setFormOpen}
        role={editingRole}
        onSuccess={fetchRoles}
      />

      {/* Permissions inspector  -  opens when admin clicks the count
          badge in the table. Lists granted vs denied per resource so
          they can spot gaps before opening the editor. */}
      <Dialog open={!!viewingPermissions} onOpenChange={(o) => !o && setViewingPermissions(null)}>
        <DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto">
          <DialogHeader>
            <DialogTitle>
              Permissions - {viewingPermissions ? formatRole(viewingPermissions.name) : ''}
            </DialogTitle>
            <DialogDescription>
              Granted vs total per resource. Click Edit to change.
            </DialogDescription>
          </DialogHeader>
          {viewingPermissions && (
            <div className="space-y-3">
              {Object.entries(viewingPermissions.permissions).map(([resource, actions]) => {
                const granted = Object.values(actions).filter(Boolean).length;
                const total = Object.keys(actions).length;
                return (
                  <div key={resource} className="rounded-md border px-3 py-2">
                    <div className="flex items-center justify-between mb-1.5">
                      <span className="text-sm font-medium capitalize">
                        {resource.replace(/_/g, ' ')}
                      </span>
                      <Badge variant="secondary" className="text-xs">
                        {granted}/{total}
                      </Badge>
                    </div>
                    <div className="flex flex-wrap gap-1.5">
                      {Object.entries(actions).map(([action, allowed]) => (
                        <span
                          key={action}
                          className={
                            allowed
                              ? 'inline-flex items-center rounded-full bg-emerald-50 text-emerald-900 px-2 py-0.5 text-xs font-medium'
                              : 'inline-flex items-center rounded-full bg-muted text-muted-foreground px-2 py-0.5 text-xs font-medium line-through opacity-60'
                          }
                        >
                          {action.replace(/_/g, ' ')}
                        </span>
                      ))}
                    </div>
                  </div>
                );
              })}
            </div>
          )}
          <DialogFooter>
            <Button variant="outline" onClick={() => setViewingPermissions(null)}>
              Close
            </Button>
            {viewingPermissions && (
              <Button
                onClick={() => {
                  const role = viewingPermissions;
                  setViewingPermissions(null);
                  handleEditRole(role);
                }}
              >
                Edit
              </Button>
            )}
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
