import { useState } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import { Switch } from "@/components/ui/switch";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import {
  Search, Loader2, UserCog, Shield, Key, Eye, ChevronRight, Users,
} from "lucide-react";
import { useToast } from "@/hooks/use-toast";
import { rolesService } from "@/services/roles.service";
import type { UserWithRoles, UserRoleDetail, Role, Permission } from "@/types/role-permission";

const ROLE_COLORS = [
  "bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300",
  "bg-violet-100 text-violet-700 dark:bg-violet-900 dark:text-violet-300",
  "bg-emerald-100 text-emerald-700 dark:bg-emerald-900 dark:text-emerald-300",
  "bg-amber-100 text-amber-700 dark:bg-amber-900 dark:text-amber-300",
  "bg-rose-100 text-rose-700 dark:bg-rose-900 dark:text-rose-300",
  "bg-cyan-100 text-cyan-700 dark:bg-cyan-900 dark:text-cyan-300",
  "bg-orange-100 text-orange-700 dark:bg-orange-900 dark:text-orange-300",
];

function roleColor(idx: number) {
  return ROLE_COLORS[idx % ROLE_COLORS.length];
}

function initials(name: string) {
  return name.split(" ").map(w => w[0]).join("").toUpperCase().slice(0, 2);
}

const CATEGORY_BADGE: Record<string, string> = {
  exam: "bg-violet-100 text-violet-700",
  user: "bg-blue-100 text-blue-700",
  entity: "bg-emerald-100 text-emerald-700",
  assignment: "bg-amber-100 text-amber-700",
  classroom: "bg-rose-100 text-rose-700",
  payment: "bg-cyan-100 text-cyan-700",
  report: "bg-orange-100 text-orange-700",
};

function catBadge(cat: string) {
  return CATEGORY_BADGE[cat.toLowerCase()] ?? "bg-gray-100 text-gray-700";
}

export default function UserRoles() {
  const { toast } = useToast();
  const qc = useQueryClient();
  const [search, setSearch] = useState("");
  const [roleFilter, setRoleFilter] = useState("all");

  const [editOpen, setEditOpen] = useState(false);
  const [editUserId, setEditUserId] = useState<number | null>(null);
  const [editRoleIds, setEditRoleIds] = useState<Set<number>>(new Set());

  const [viewOpen, setViewOpen] = useState(false);
  const [viewUserId, setViewUserId] = useState<number | null>(null);

  const usersQ = useQuery({
    queryKey: ["users-with-roles", search, roleFilter],
    queryFn: () => rolesService.listUsersWithRoles({
      ...(search ? { search } : {}),
      ...(roleFilter !== "all" ? { role_id: Number(roleFilter) } : {}),
      size: 200,
    }),
  });
  const rolesQ = useQuery({ queryKey: ["roles"], queryFn: () => rolesService.listRoles() });
  const viewQ = useQuery({
    queryKey: ["user-roles-detail", viewUserId],
    queryFn: () => rolesService.getUserRoles(viewUserId!),
    enabled: viewUserId !== null,
  });

  const users: UserWithRoles[] = usersQ.data?.data ?? [];
  const allRoles: Role[] = rolesQ.data?.data ?? [];

  const saveRolesMut = useMutation({
    mutationFn: ({ userId, roleIds }: { userId: number; roleIds: number[] }) =>
      rolesService.updateUserRoles(userId, roleIds),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["users-with-roles"] });
      qc.invalidateQueries({ queryKey: ["roles"] });
      setEditOpen(false);
      toast({ title: "Roles updated successfully" });
    },
    onError: () => toast({ title: "Failed to update roles", variant: "destructive" }),
  });

  const loading = usersQ.isLoading || rolesQ.isLoading;

  const totalWithRoles = users.filter(u => u.role_ids.length > 0).length;
  const totalWithoutRoles = users.filter(u => u.role_ids.length === 0).length;

  const openEditRoles = (u: UserWithRoles) => {
    setEditUserId(u.id);
    setEditRoleIds(new Set(u.role_ids));
    setEditOpen(true);
  };

  const openViewPerms = (u: UserWithRoles) => {
    setViewUserId(u.id);
    setViewOpen(true);
  };

  const toggleRole = (rid: number) => {
    setEditRoleIds(prev => {
      const s = new Set(prev);
      if (s.has(rid)) s.delete(rid); else s.add(rid);
      return s;
    });
  };

  const handleSave = () => {
    if (editUserId !== null) {
      saveRolesMut.mutate({ userId: editUserId, roleIds: Array.from(editRoleIds) });
    }
  };

  const viewDetail: UserRoleDetail | undefined = viewQ.data;
  const effectivePerms: Permission[] = viewDetail?.effective_permissions ?? [];
  const permsByCategory = effectivePerms.reduce<Record<string, Permission[]>>((acc, p) => {
    const cat = p.category || "General";
    (acc[cat] ??= []).push(p);
    return acc;
  }, {});

  if (loading) {
    return <div className="flex items-center justify-center min-h-[400px]"><Loader2 className="h-8 w-8 animate-spin text-primary" /></div>;
  }

  return (
    <div className="space-y-6">
      {/* Header */}
      <div className="flex flex-wrap items-center justify-between gap-4">
        <div>
          <h1 className="text-2xl font-bold flex items-center gap-2">
            <UserCog className="h-7 w-7 text-primary" />
            User Roles
          </h1>
          <p className="text-muted-foreground">Assign roles to users and view their effective permissions.</p>
        </div>
      </div>

      {/* Summary */}
      <div className="grid grid-cols-2 sm:grid-cols-4 gap-4">
        <Card>
          <CardContent className="pt-5 pb-4 flex items-center gap-3">
            <div className="h-10 w-10 rounded-lg bg-primary/10 flex items-center justify-center"><Users className="h-5 w-5 text-primary" /></div>
            <div><p className="text-xl font-bold">{users.length}</p><p className="text-xs text-muted-foreground">Total Users</p></div>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="pt-5 pb-4 flex items-center gap-3">
            <div className="h-10 w-10 rounded-lg bg-emerald-500/10 flex items-center justify-center"><Shield className="h-5 w-5 text-emerald-500" /></div>
            <div><p className="text-xl font-bold">{totalWithRoles}</p><p className="text-xs text-muted-foreground">With Roles</p></div>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="pt-5 pb-4 flex items-center gap-3">
            <div className="h-10 w-10 rounded-lg bg-amber-500/10 flex items-center justify-center"><UserCog className="h-5 w-5 text-amber-500" /></div>
            <div><p className="text-xl font-bold">{totalWithoutRoles}</p><p className="text-xs text-muted-foreground">No Roles</p></div>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="pt-5 pb-4 flex items-center gap-3">
            <div className="h-10 w-10 rounded-lg bg-violet-500/10 flex items-center justify-center"><Key className="h-5 w-5 text-violet-500" /></div>
            <div><p className="text-xl font-bold">{allRoles.length}</p><p className="text-xs text-muted-foreground">Available Roles</p></div>
          </CardContent>
        </Card>
      </div>

      {/* Filters */}
      <div className="flex flex-wrap gap-3">
        <div className="relative max-w-xs w-full">
          <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
          <Input placeholder="Search users..." className="pl-9" value={search} onChange={e => setSearch(e.target.value)} />
        </div>
        <Select value={roleFilter} onValueChange={setRoleFilter}>
          <SelectTrigger className="w-[200px]">
            <SelectValue placeholder="Filter by role" />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="all">All Roles</SelectItem>
            {allRoles.map(r => (
              <SelectItem key={r.id} value={String(r.id)}>{r.name}</SelectItem>
            ))}
          </SelectContent>
        </Select>
      </div>

      {/* Users Table */}
      <Card>
        <CardContent className="pt-6">
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>User</TableHead>
                <TableHead>Email / Login</TableHead>
                <TableHead>Assigned Roles</TableHead>
                <TableHead className="text-center">Permissions</TableHead>
                <TableHead className="text-right">Actions</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {users.length === 0 && (
                <TableRow><TableCell colSpan={5} className="text-center text-muted-foreground py-12">No users found.</TableCell></TableRow>
              )}
              {users.map(u => (
                <TableRow key={u.id} className="group">
                  <TableCell>
                    <div className="flex items-center gap-3">
                      <Avatar className="h-8 w-8">
                        <AvatarFallback className="text-xs bg-primary/10 text-primary font-medium">{initials(u.name)}</AvatarFallback>
                      </Avatar>
                      <span className="font-medium">{u.name}</span>
                    </div>
                  </TableCell>
                  <TableCell className="text-muted-foreground text-sm">{u.email || u.login}</TableCell>
                  <TableCell>
                    <div className="flex flex-wrap gap-1">
                      {u.roles.length === 0 && <span className="text-xs text-muted-foreground italic">No roles</span>}
                      {u.roles.map((r, i) => (
                        <Badge key={r.id} variant="outline" className={`text-[11px] px-1.5 py-0 ${roleColor(i)}`}>
                          <Shield className="h-2.5 w-2.5 mr-0.5" />{r.name}
                        </Badge>
                      ))}
                    </div>
                  </TableCell>
                  <TableCell className="text-center">
                    <Badge variant="secondary" className="text-xs">{u.effective_permission_count}</Badge>
                  </TableCell>
                  <TableCell className="text-right">
                    <div className="flex justify-end gap-1">
                      <Tooltip><TooltipTrigger asChild>
                        <Button size="sm" variant="ghost" className="h-8 gap-1 text-xs" onClick={() => openViewPerms(u)}>
                          <Eye className="h-3.5 w-3.5" /> View
                        </Button>
                      </TooltipTrigger><TooltipContent>View effective permissions</TooltipContent></Tooltip>
                      <Tooltip><TooltipTrigger asChild>
                        <Button size="sm" variant="outline" className="h-8 gap-1 text-xs" onClick={() => openEditRoles(u)}>
                          <UserCog className="h-3.5 w-3.5" /> Assign <ChevronRight className="h-3 w-3" />
                        </Button>
                      </TooltipTrigger><TooltipContent>Manage role assignments</TooltipContent></Tooltip>
                    </div>
                  </TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </CardContent>
      </Card>

      {/* ── Assign Roles Dialog ── */}
      <Dialog open={editOpen} onOpenChange={o => { setEditOpen(o); if (!o) setEditUserId(null); }}>
        <DialogContent className="max-w-lg">
          <DialogHeader>
            <DialogTitle className="flex items-center gap-2">
              <UserCog className="h-5 w-5 text-primary" />
              Assign Roles
            </DialogTitle>
            <CardDescription>
              Toggle roles for user: <strong>{users.find(u => u.id === editUserId)?.name}</strong>
            </CardDescription>
          </DialogHeader>
          <div className="space-y-2 max-h-[50vh] overflow-y-auto pr-1">
            {allRoles.length === 0 && <p className="text-sm text-muted-foreground text-center py-8">No roles available. Create roles first.</p>}
            {allRoles.map((r, i) => (
              <label key={r.id} className={`flex items-center gap-3 px-4 py-3 rounded-lg border cursor-pointer transition-all ${
                editRoleIds.has(r.id)
                  ? "border-primary/40 bg-primary/5 shadow-sm"
                  : "border-border hover:border-muted-foreground/30 hover:bg-muted/30"
              }`}>
                <Switch checked={editRoleIds.has(r.id)} onCheckedChange={() => toggleRole(r.id)} />
                <div className="flex-1 min-w-0">
                  <div className="flex items-center gap-2">
                    <Badge variant="outline" className={`text-[10px] px-1.5 py-0 ${roleColor(i)}`}>
                      <Shield className="h-2.5 w-2.5 mr-0.5" />{r.name}
                    </Badge>
                    <span className="text-xs text-muted-foreground">{r.permissions.length} permission{r.permissions.length !== 1 ? "s" : ""}</span>
                  </div>
                  {r.description && <p className="text-xs text-muted-foreground mt-0.5 truncate">{r.description}</p>}
                </div>
              </label>
            ))}
          </div>
          <DialogFooter>
            <div className="flex items-center gap-2 mr-auto text-sm text-muted-foreground">
              <Shield className="h-4 w-4" /> {editRoleIds.size} of {allRoles.length} selected
            </div>
            <Button variant="outline" onClick={() => setEditOpen(false)}>Cancel</Button>
            <Button disabled={saveRolesMut.isPending} onClick={handleSave}>
              {saveRolesMut.isPending ? <Loader2 className="h-4 w-4 mr-1 animate-spin" /> : null}
              Save Roles
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* ── View Effective Permissions Dialog ── */}
      <Dialog open={viewOpen} onOpenChange={o => { setViewOpen(o); if (!o) setViewUserId(null); }}>
        <DialogContent className="max-w-2xl max-h-[85vh]">
          <DialogHeader>
            <DialogTitle className="flex items-center gap-2">
              <Key className="h-5 w-5 text-primary" />
              Effective Permissions
            </DialogTitle>
            {viewDetail && (
              <CardDescription>
                <strong>{viewDetail.user.name}</strong> ({viewDetail.user.login})
              </CardDescription>
            )}
          </DialogHeader>
          {viewQ.isLoading ? (
            <div className="flex justify-center py-12"><Loader2 className="h-6 w-6 animate-spin text-primary" /></div>
          ) : viewDetail ? (
            <div className="space-y-4 overflow-y-auto max-h-[60vh] pr-1">
              {/* Assigned roles summary */}
              <div>
                <p className="text-xs font-medium text-muted-foreground mb-2 uppercase tracking-wider">Assigned Roles</p>
                <div className="flex flex-wrap gap-1.5">
                  {viewDetail.roles.filter(r => r.assigned).map((r, i) => (
                    <Badge key={r.id} variant="outline" className={`${roleColor(i)} text-xs px-2 py-0.5`}>
                      <Shield className="h-3 w-3 mr-1" />{r.name}
                      <span className="ml-1 text-[10px] opacity-70">({r.permission_count})</span>
                    </Badge>
                  ))}
                  {viewDetail.roles.filter(r => r.assigned).length === 0 && (
                    <span className="text-sm text-muted-foreground italic">No roles assigned</span>
                  )}
                </div>
              </div>

              {/* Permissions grouped by category */}
              <div>
                <p className="text-xs font-medium text-muted-foreground mb-2 uppercase tracking-wider">
                  Effective Permissions ({effectivePerms.length})
                </p>
                {effectivePerms.length === 0 ? (
                  <p className="text-sm text-muted-foreground italic py-4 text-center">No permissions (assign roles to grant permissions)</p>
                ) : (
                  <div className="space-y-3">
                    {Object.entries(permsByCategory).map(([cat, perms]) => (
                      <Card key={cat} className="border-muted">
                        <CardHeader className="py-2 px-4">
                          <div className="flex items-center gap-2">
                            <Badge className={`${catBadge(cat)} font-medium text-[10px]`}>{cat}</Badge>
                            <span className="text-xs text-muted-foreground">{perms.length}</span>
                          </div>
                        </CardHeader>
                        <CardContent className="px-4 pb-3 pt-0">
                          <div className="grid gap-1">
                            {perms.map(p => (
                              <div key={p.id} className="flex items-center gap-2 py-1">
                                <div className="h-5 w-5 rounded bg-emerald-500/15 flex items-center justify-center">
                                  <Key className="h-2.5 w-2.5 text-emerald-600" />
                                </div>
                                <code className="text-[10px] font-mono bg-muted px-1 rounded text-muted-foreground">{p.code}</code>
                                <span className="text-xs">{p.name}</span>
                              </div>
                            ))}
                          </div>
                        </CardContent>
                      </Card>
                    ))}
                  </div>
                )}
              </div>
            </div>
          ) : null}
          <DialogFooter>
            <Button variant="outline" onClick={() => setViewOpen(false)}>Close</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
