// routes/_authenticated/usuarios.tsx
import { createFileRoute, useRouter } from "@tanstack/react-router"
import { useMemo, useState } from "react"
import { useSuspenseQuery, queryOptions, useMutation, useQueryClient } from "@tanstack/react-query"
import { supabase, useSupabaseAuth } from "@/auth/supabase"
import type { Role, UserClaims } from "@/auth/supabase"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"
import { Label } from "@/components/ui/label"
import { Select, SelectTrigger, SelectContent, SelectItem, SelectValue } from "@/components/ui/select"
import * as Icons from "lucide-react"
import { CarreraCombobox, FacultadCombobox } from "@/components/users/procedencia-combobox"
import { toast } from "sonner"




/* -------------------- Query Keys & Fetcher -------------------- */
const usersKeys = {
  root: ["usuarios"] as const,
  list: () => [...usersKeys.root, "list"] as const,
}

async function fetchUsers(): Promise<UserClaims[]> {
  try {
    const { data: perfiles, error } = await supabase.from("perfiles").select("id");

    if (error) {
      console.error("Error al obtener usuarios:", error.message);
      return []; // Devuelve un arreglo vacío en caso de error
    }

    if (!perfiles || perfiles.length === 0) {
      console.log("No se encontraron perfiles.");
      return []; // Devuelve un arreglo vacío si no hay datos
    }

    // Llama a `obtener_claims_usuario` para cada perfil
    const usuarios = await Promise.all(
      perfiles.map(async (perfil) => {
        const { data: claims, error: rpcError } = await supabase.rpc("obtener_claims_usuario", {
          p_user_id: perfil.id, // Pasa el ID del perfil como parámetro
        });

        console.log("Claims para perfil", perfil.id, claims[0]);
        if (rpcError) {
          console.error(`Error al obtener claims para el perfil ${perfil.id}:`, rpcError.message);
          return null; // Devuelve null si hay un error
        }

        return {
          id: perfil.id,
          role: claims[0]?.role,
          title: claims[0]?.title,
          facultad_id: claims[0]?.facultad_id,
          carrera_id: claims[0]?.carrera_id,
          facultad_color: claims[0]?.facultad_color,
          clave: claims[0]?.clave,
          nombre: claims[0]?.nombre,
          apellidos: claims[0]?.apellidos,
          avatar: claims[0]?.avatar,
        };
      })
    );

    // Filtra los resultados nulos (errores en las llamadas RPC)
    return usuarios.filter((u) => u !== null) as UserClaims[];
  } catch (err) {
    console.error("Error inesperado:", err);
    return []; // Devuelve un arreglo vacío en caso de error inesperado
  }
}



const usersOptions = () =>
  queryOptions({ queryKey: usersKeys.list(), queryFn: fetchUsers, staleTime: 60_000 })

/* -------------------- Ruta -------------------- */
export const Route = createFileRoute("/_authenticated/usuarios")({
  component: RouteComponent,
  loader: async ({ context: { queryClient } }) => {
    await queryClient.ensureQueryData(usersOptions())
    return null
  },
})

/* -------------------- Página -------------------- */
function RouteComponent() {
  const auth = useSupabaseAuth()

  if (auth.claims?.role !== "lci" && auth.claims?.role !== "vicerrectoria") {
    return <div className="p-6 text-sm text-red-600">No tienes permisos para administrar usuarios.</div>
  }

  const { ROLES, ROLE_META } = useMemo(() => {
    if (!auth.roles) return { ROLES: [], ROLE_META: {} };
  
    // Construir ROLES como un arreglo de strings
    const rolesArray = auth.roles.map((role) => role.nombre);
  
    // Construir ROLE_META como un objeto basado en ROLES
    const rolesMeta = auth.roles.reduce((acc, role) => {
      acc[role.nombre] = {
        id: role.id,
        label: role.label,
        Icon: (Icons as any)[role.icono] || Icons.Cpu, // Icono por defecto si no está definido
        className: /* role.nombre_clase || */ "bg-gray-500 text-white", // Clase por defecto si no está definida
      };
      return acc;
    }, {} as Record<string, { id: string; label: string; Icon: React.ComponentType<React.SVGProps<SVGSVGElement>>; className: string }>);
  
    return { ROLES: rolesArray, ROLE_META: rolesMeta };
  }, [auth.roles]);

  const router = useRouter()
  const qc = useQueryClient()
  const { data } = useSuspenseQuery(usersOptions())

  const [q, setQ] = useState("")
  const [editing, setEditing] = useState<UserClaims | null>(null)
  const [form, setForm] = useState<{
    role?: Role
    claims_admin?: boolean
    nombre?: string; apellidos?: string; title?: string; clave?: string; avatar?: string
    facultad_id?: string | null
    carrera_id?: string | null
  }>({})

  const [createOpen, setCreateOpen] = useState(false)
  const [showPwd, setShowPwd] = useState(false)
  const [createForm, setCreateForm] = useState<{
    email: string
    password: string
    role?: Role
    claims_admin?: boolean
    nombre?: string; apellidos?: string; title?: string; clave?: string; avatar?: string
    facultad_id?: string | null
    carrera_id?: string | null
  }>({ email: "", password: "" })


  function RolePill({ role }: { role: Role }) {
    const meta = ROLE_META[role]
    if (!meta) return null
    const { Icon, className, label } = meta
    return (
      <span className={`inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[10px] sm:text-[11px] ${className} max-w-[160px] sm:max-w-none truncate`} title={label}>
        <Icon className="h-3 w-3 shrink-0" />
        <span className="truncate">{label}</span>
      </span>
    )
  }

  /* ---------- Mutations ---------- */
  const invalidateAll = async () => {
    await qc.invalidateQueries({ queryKey: usersKeys.root })
    router.invalidate()
  }

  const createUser = useMutation({
    mutationFn: async (payload: typeof createForm) => {
      // Validaciones previas
      if (!payload.role) {
        throw new Error("Selecciona un rol para el usuario.");
      }
      if ((payload.role === "secretario_academico" || payload.role === "director_facultad") && !payload.facultad_id) {
        throw new Error("Selecciona una facultad para este rol.");
      }
      if (payload.role === "jefe_carrera" && (!payload.facultad_id || !payload.carrera_id)) {
        throw new Error("Selecciona una facultad y una carrera para este rol.");
      }
      
      const password = payload.password?.trim()
      const { data, error } = await supabase.auth.signUp({
        email: payload.email.trim(),
        password,
        options: {
          data: {
            nombre: payload.nombre ?? "",
            apellidos: payload.apellidos ?? "",
            title: payload.title ?? "",
            clave: payload.clave ?? "",
            avatar: payload.avatar ?? "",
            role: payload.role,
            role_id: payload.role ? ROLE_META[payload.role]?.id : null,
            facultad_id: payload.facultad_id ?? null,
            carrera_id: payload.carrera_id ?? null,
          }
        }
      });

      if (error) throw new Error(error.message)

      const uid = data.user?.id

      if(!uid) {
        throw new Error("No se pudo obtener el ID del usuario creado.");
      }
    },
    onSuccess: async () => {
      toast.success("Usuario creado")
      setCreateOpen(false)
      setCreateForm({ email: "", password: "" })
      await invalidateAll()
    },
    onError: (e: any) => toast.error(e?.message || "No se pudo crear el usuario"),
  })

  const saveUser = useMutation({
    mutationFn: async ({ u, f }: { u: UserClaims; f: typeof form }) => {

      const { error } = await supabase.rpc('actualizar_perfil_y_rol', {
        datos: {
          user_id: u.id,
          rol_nombre: f.role,
          titulo: f.title,
          facultad_id: f.facultad_id,
          carrera_id: f.carrera_id,
          nombre: f.nombre,
          apellidos: f.apellidos,
          avatar: f.avatar,
        }
      });

      if (error) {
        throw new Error(error.message);
      }
    },
    onSuccess: async () => {
      toast.success("Cambios guardados")
      setEditing(null)
      await invalidateAll()
    },
    onError: (e: any) => toast.error(e?.message || "No se pudo guardar"),
  })

  const filtered = useMemo(() => {
    const t = q.trim().toLowerCase()
    if (!t) return data
    return data.filter((u) => {
      const role: Role | undefined = u.role
      const label = role ? ROLE_META[role]?.label : ""
      return [u.nombre, u.apellidos, label]
        .filter(Boolean)
        .some((v) => String(v).toLowerCase().includes(t))
    })
  }, [q, data])

  function openEdit(u: UserClaims) {
    setEditing(u)
    setForm({
      role: u.role,
      nombre: u.nombre ?? "",
      apellidos: u.apellidos ?? "",
      title: u.title ?? "",
      clave: u.clave ?? "",
      avatar: u.avatar ?? "",
      facultad_id: u.facultad_id ?? null,
      carrera_id: u.carrera_id ?? null,
    })
  }

  function validateScopeForSave(): string | null {
    if (!editing) return "Sin usuario"
    if (form.role === "director_facultad" || form.role === "secretario_academico") {
      if (!form.facultad_id) return "Selecciona una facultad"
    }
    if (form.role === "jefe_carrera") {
      if (!form.facultad_id || !form.carrera_id) return "Selecciona facultad y carrera"
    }
    return null
  }

  return (
    <div className="p-6 space-y-4">
      <Card>
        <CardHeader className="grid gap-3 sm:grid-cols-2 sm:items-center">
          <CardTitle className="font-mono">Usuarios</CardTitle>
          <div className="flex items-center gap-2">
            <Input placeholder="Buscar por nombre, email o rol…" value={q} onChange={(e) => setQ(e.target.value)} className="w-full" />
            <Button variant="outline" size="icon" title="Recargar" onClick={invalidateAll}>
              <Icons.RefreshCcw className="w-4 h-4" />
            </Button>
            <Button onClick={() => setCreateOpen(true)} className="whitespace-nowrap">
              <Icons.Plus className="w-4 h-4 mr-1" /> Nuevo usuario
            </Button>
          </div>
        </CardHeader>

        <CardContent>
          <div className="grid gap-3">
            {filtered.map((u) => {
              const roleCode: Role | undefined = u.role
              const banned = false // cuando se tenga acceso a ese campo
              // const banned = !!(u as any).banned_until && new Date((u as any).banned_until).getTime() > Date.now()
              return (
                <div key={u.id} className="rounded-2xl border bg-white/70 dark:bg-neutral-900/60 p-3 sm:p-4 hover:shadow-sm transition">
                  <div className="flex items-start gap-3 sm:gap-4">
                    <img src={u.avatar || `https://api.dicebear.com/7.x/initials/svg?seed=${encodeURIComponent(u.nombre || /* u.email || */ "U")}`} alt="" className="h-10 w-10 rounded-full object-cover" />
                    <div className="min-w-0 flex-1">
                      <div className="flex items-start justify-between gap-2">
                        <div className="min-w-0">
                          <div className="font-medium truncate">{u.title ? `${u.title} ` : ""}{u.nombre ? `${u.nombre} ${u.apellidos ?? ""}` : /* (u.email ?? "—") */ "—"}</div>
                          <div className="mt-1 flex flex-wrap items-center gap-1.5 sm:gap-2">
                            {roleCode && <RolePill role={roleCode} />}
                            {u.role === "lci" || u.role === "vicerrectoria" ? (
                              <Badge className="gap-1" variant="secondary"><Icons.ShieldCheck className="w-3 h-3" /> Admin</Badge>
                            ) : (
                              <Badge className="gap-1" variant="outline"><Icons.ShieldAlert className="w-3 h-3" /> Usuario</Badge>
                            )}
                            <Badge variant={banned ? ("destructive" as any) : "secondary"} className="gap-1">
                              {banned ? <Icons.BanIcon className="w-3 h-3" /> : <Icons.Check className="w-3 h-3" />} {banned ? "Baneado" : "Activo"}
                            </Badge>
                          </div>
                        </div>
                        <div className="flex items-center gap-1">
                          <Button variant="outline" size="sm" onClick={() => {}} title={banned ? "Restaurar acceso" : "Inhabilitar la cuenta"} className="hidden sm:inline-flex">
                            <Icons.BanIcon className="w-4 h-4 mr-1" /> {banned ? "Restaurar acceso" : "Inhabilitar la cuenta"}
                          </Button>
                          <Button variant="ghost" size="sm" className="hidden sm:inline-flex shrink-0" onClick={() => openEdit(u)}>
                            <Icons.Pencil className="w-4 h-4 mr-1" /> Editar
                          </Button>
                        </div>
                      </div>
                      <div className="mt-2 flex flex-wrap gap-x-3 gap-y-1 text-[11px] sm:text-xs text-neutral-600">
                        {/* Cuando se tenga acceso a esta info, se mostrará
                        <span className="inline-flex items-center gap-1"><Icons.Mail className="w-3 h-3" /> {u.email ?? "—"}</span>
                        <span className="hidden xs:inline">Creado: {new Date(u.created_at).toLocaleDateString()}</span>
                        <span className="hidden md:inline">Último acceso: {u.last_sign_in_at ? new Date(u.last_sign_in_at).toLocaleDateString() : "—"}</span> */}
                      </div>
                    </div>
                    <div className="sm:hidden self-start shrink-0 flex gap-1">
                      <Button variant="outline" size="icon" onClick={() => {}} aria-label="Ban/Unban"><Icons.BanIcon className="w-4 h-4" /></Button>
                      <Button variant="ghost" size="icon" onClick={() => openEdit(u)} aria-label="Editar"><Icons.Pencil className="w-4 h-4" /></Button>
                    </div>
                  </div>
                </div>
              )
            })}
            {!filtered.length && <div className="text-sm text-neutral-500 text-center py-10">Sin usuarios</div>}
          </div>
        </CardContent>
      </Card>

      {/* Dialog de edición */}
      <Dialog open={!!editing} onOpenChange={(o) => { if (!o) setEditing(null) }}>
        <DialogContent className="w-[min(92vw,720px)] sm:max-w-xl md:max-w-2xl">
          <DialogHeader><DialogTitle className="font-mono" >Editar usuario</DialogTitle></DialogHeader>
          <div className="grid gap-4 md:grid-cols-2">
            <div className="space-y-1"><Label>Nombre</Label><Input value={form.nombre ?? ""} onChange={(e) => setForm((s) => ({ ...s, nombre: e.target.value }))} /></div>
            <div className="space-y-1"><Label>Apellidos</Label><Input value={form.apellidos ?? ""} onChange={(e) => setForm((s) => ({ ...s, apellidos: e.target.value }))} /></div>
            <div className="space-y-1"><Label>Título <small>(opcional)</small></Label><Input value={form.title ?? ""} onChange={(e) => setForm((s) => ({ ...s, title: e.target.value }))} /></div>
            <div className="space-y-1"><Label>Clave</Label><Input value={form.clave ?? ""} onChange={(e) => setForm((s) => ({ ...s, clave: e.target.value }))} /></div>
            <div className="space-y-1"><Label>Avatar (URL)</Label><Input value={form.avatar ?? ""} onChange={(e) => setForm((s) => ({ ...s, avatar: e.target.value }))} /></div>
            <div className="space-y-1">
              <Label>Rol</Label>
              <Select
                value={form.role ?? ""}
                onValueChange={(v) => {
                  setForm((s) => {
                    const role = v as Role
                    if (role === "jefe_carrera") return { ...s, role, facultad_id: s.facultad_id ?? "", carrera_id: s.carrera_id ?? "" }
                    if (role === "secretario_academico" || role === "director_facultad") return { ...s, role, facultad_id: s.facultad_id ?? "", carrera_id: null }
                    return { ...s, role, facultad_id: null, carrera_id: null }
                  })
                }}
              >
                <SelectTrigger className="w-full"><SelectValue placeholder="Selecciona un rol" /></SelectTrigger>
                <SelectContent position="popper" side="bottom" align="start" className="w-[--radix-select-trigger-width] max-w-[min(92vw,28rem)] max-h-72 overflow-auto">
                  {ROLES.map((code) => {
                    const meta = ROLE_META[code]; const Icon = meta.Icon
                    return (
                      <SelectItem key={code} value={code} className="whitespace-normal text-sm leading-snug py-2">
                        <span className="inline-flex items-center gap-2"><Icon className="w-4 h-4" /> {meta.label}</span>
                      </SelectItem>
                    )
                  })}
                </SelectContent>
              </Select>
            </div>

            {(form.role === "secretario_academico" || form.role === "director_facultad") && (
              <div className="md:col-span-2 space-y-1">
                <Label>Facultad</Label>
                <FacultadCombobox value={form.facultad_id ?? ""} onChange={(id) => setForm((s) => ({ ...s, facultad_id: id, carrera_id: null }))} />
                <p className="text-[11px] text-neutral-500">Este rol requiere <strong>Facultad</strong>.</p>
              </div>
            )}

            {form.role === "jefe_carrera" && (
              <div className="grid gap-4 sm:grid-cols-2 md:col-span-2">
                <div className="space-y-1">
                  <Label>Facultad</Label>
                  <FacultadCombobox value={form.facultad_id ?? ""} onChange={(id) => setForm((s) => ({ ...s, facultad_id: id, carrera_id: "" }))} />
                </div>
                <div className="space-y-1">
                  <Label>Carrera</Label>
                  <CarreraCombobox facultadId={form.facultad_id ?? ""} value={form.carrera_id ?? ""} onChange={(id) => setForm((s) => ({ ...s, carrera_id: id }))} disabled={!form.facultad_id} />
                </div>
              </div>
            )}

            {/* Probablemente ya no sea necesario
            <div className="space-y-1">
              <Label>Permisos</Label>
              <Select value={String(!!form.claims_admin)} onValueChange={(v) => setForm((s) => ({ ...s, claims_admin: v === 'true' }))}>
                <SelectTrigger><SelectValue /></SelectTrigger>
                <SelectContent>
                  <SelectItem value="true">Administrador</SelectItem>
                  <SelectItem value="false">Usuario</SelectItem>
                </SelectContent>
              </Select>
            </div> */}
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setEditing(null)}>Cancelar</Button>
            <Button
              onClick={() => {
                const scopeErr = validateScopeForSave()
                if (scopeErr || !editing) { toast.error(scopeErr || 'Sin usuario'); return }
                saveUser.mutate({ u: editing, f: form })
              }}
              disabled={saveUser.isPending}
            >
              {saveUser.isPending ? "Guardando…" : "Guardar"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Modal: Nuevo usuario */}
      <Dialog open={createOpen} onOpenChange={setCreateOpen}>
        <DialogContent className="w-[min(92vw,720px)] sm:max-w-xl md:max-w-2xl">
          <DialogHeader><DialogTitle className="font-mono" >Nuevo usuario</DialogTitle></DialogHeader>

          <div className="grid gap-4 md:grid-cols-2">
            <div className="space-y-1 md:col-span-2">
              <Label>Correo</Label>
              <Input type="email" value={createForm.email} onChange={(e) => setCreateForm((s) => ({ ...s, email: e.target.value }))} placeholder="usuario@lasalle.mx" />
            </div>

            <div className="space-y-1 md:col-span-2">
              <Label>Contraseña temporal</Label>
              <div className="flex gap-2">
                <Input type={showPwd ? "text" : "password"} value={createForm.password} onChange={(e) => setCreateForm((s) => ({ ...s, password: e.target.value }))} placeholder="abCD12&;" />
                {/* <Button type="button" variant="outline" onClick={() => setCreateForm((s) => ({ ...s, password: genPassword() }))}>Generar</Button> */}
                <Button type="button" variant="outline" onClick={() => setShowPwd((v) => !v)} aria-label="Mostrar u ocultar">{showPwd ? <Icons.EyeOff className="w-4 h-4" /> : <Icons.Eye className="w-4 h-4" />}</Button>
              </div>
              <p className="text-[11px] text-neutral-500">Pídeles cambiarla al iniciar sesión.</p>
            </div>

            <div className="space-y-1"><Label>Nombre</Label><Input value={createForm.nombre ?? ""} onChange={(e) => setCreateForm((s) => ({ ...s, nombre: e.target.value }))} /></div>
            <div className="space-y-1"><Label>Apellidos</Label><Input value={createForm.apellidos ?? ""} onChange={(e) => setCreateForm((s) => ({ ...s, apellidos: e.target.value }))} /></div>
            <div className="space-y-1"><Label>Título <small>(opcional)</small></Label><Input value={createForm.title ?? ""} onChange={(e) => setCreateForm((s) => ({ ...s, title: e.target.value }))} /></div>
            <div className="space-y-1"><Label>Clave</Label><Input value={createForm.clave ?? ""} onChange={(e) => setCreateForm((s) => ({ ...s, clave: e.target.value }))} /></div>
            <div className="space-y-1 md:col-span-2"><Label>Avatar (URL)</Label><Input value={createForm.avatar ?? ""} onChange={(e) => setCreateForm((s) => ({ ...s, avatar: e.target.value }))} /></div>

            <div className="space-y-1 md:col-span-2">
              <Label>Rol</Label>
              <Select
                value={createForm.role ?? ""}
                onValueChange={(v) => {
                  setCreateForm((s) => {
                    const role = v as Role
                    console.log("Rol seleccionado: ", role, ROLE_META[role]);
                    if (role === "jefe_carrera") return { ...s, role, facultad_id: s.facultad_id ?? "", carrera_id: s.carrera_id ?? "" }
                    if (role === "secretario_academico" || role === "director_facultad") return { ...s, role, facultad_id: s.facultad_id ?? "", carrera_id: null }
                    return { ...s, role, facultad_id: null, carrera_id: null }
                  })
                }}
              >
                <SelectTrigger className="w-full"><SelectValue placeholder="Selecciona un rol" /></SelectTrigger>
                <SelectContent className="max-h-72">
                  {ROLES.map((code) => {
                    const M = ROLE_META[code]; const I = M.Icon
                    return (
                      <SelectItem key={code} value={code} className="whitespace-normal text-sm leading-snug py-2">
                        <span className="inline-flex items-center gap-2"><I className="w-4 h-4" /> {M.label}</span>
                      </SelectItem>
                    )
                  })}
                </SelectContent>
              </Select>
            </div>

            {(createForm.role === "secretario_academico" || createForm.role === "director_facultad") && (
              <div className="md:col-span-2 space-y-1">
                <Label>Facultad</Label>
                <FacultadCombobox value={createForm.facultad_id ?? ""} onChange={(id) => setCreateForm((s) => ({ ...s, facultad_id: id, carrera_id: null }))} />
              </div>
            )}

            {createForm.role === "jefe_carrera" && (
              <div className="grid gap-4 md:col-span-2 sm:grid-cols-2">
                <div className="space-y-1">
                  <Label>Facultad</Label>
                  <FacultadCombobox value={createForm.facultad_id ?? ""} onChange={(id) => setCreateForm((s) => ({ ...s, facultad_id: id, carrera_id: "" }))} />
                </div>
                <div className="space-y-1">
                  <Label>Carrera</Label>
                  <CarreraCombobox facultadId={createForm.facultad_id ?? ""} value={createForm.carrera_id ?? ""} onChange={(id) => setCreateForm((s) => ({ ...s, carrera_id: id }))} disabled={!createForm.facultad_id} />
                </div>
              </div>
            )}

            {/*  Probablemente ya no sea necesario
            <div className="space-y-1 md:col-span-2">
              <Label>Permisos</Label>
              <Select value={String(!!createForm.claims_admin)} onValueChange={(v) => setCreateForm((s) => ({ ...s, claims_admin: v === "true" }))}>
                <SelectTrigger><SelectValue /></SelectTrigger>
                <SelectContent>
                  <SelectItem value="true">Administrador</SelectItem>
                  <SelectItem value="false">Usuario</SelectItem>
                </SelectContent>
              </Select>
            </div> */}
          </div>

          <DialogFooter>
            <Button variant="outline" onClick={() => setCreateOpen(false)}>Cancelar</Button>
            <Button onClick={() => createUser.mutate(createForm)} disabled={!createForm.email || !createForm.password || createUser.isPending}>
              {createUser.isPending ? "Creando…" : "Crear usuario"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  )
}
