'use client';

import { useState, useEffect, useCallback } from 'react';
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;
}

export function RoleList() {
  const [roles, setRoles] = useState<Role[]>([]);
  const [loading, setLoading] = useState(true);
  const [formOpen, setFormOpen] = useState(false);
  const [editingRole, setEditingRole] = useState<Role | null>(null);
  const [deletingId, setDeletingId] = useState<string | null>(null);
  const [viewingPermissions, setViewingPermissions] = useState<Role | null>(null);

  const fetchRoles = useCallback(async () => {
    setLoading(true);
    try {
      const res = await apiFetch<{ data: Role[] }>('/api/v1/admin/roles');
      setRoles(res.data);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    void fetchRoles();
  }, [fetchRoles]);

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

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

  async function handleDeleteRole(id: string) {
    setDeletingId(id);
    try {
      await apiFetch(`/api/v1/admin/roles/${id}`, { method: 'DELETE' });
      await fetchRoles();
    } finally {
      setDeletingId(null);
    }
  }

  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" />
              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" />
            <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" />
                  <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={() => handleDeleteRole(row.original.id)}
              loading={deletingId === 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" />
            New Role
          </Button>
        }
      />

      <DataTable
        columns={columns}
        data={roles}
        isLoading={loading}
        getRowId={(row) => row.id}
        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-[11px] font-medium'
                              : 'inline-flex items-center rounded-full bg-muted text-muted-foreground px-2 py-0.5 text-[11px] 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>
  );
}
