import { createFileRoute, Link, useRouter } from '@tanstack/react-router'
import { useMemo, useState } from 'react'
import { useSuspenseQuery, useMutation, useQueryClient, queryOptions } from '@tanstack/react-query'
import * as Icons from 'lucide-react'
import { supabase } from '@/auth/supabase'
import { Button } from '@/components/ui/button'
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Select, SelectTrigger, SelectContent, SelectItem, SelectValue } from '@/components/ui/select'
import { toast } from 'sonner'

/* -------------------- Tipos -------------------- */
export type Facultad = {
  id: string
  nombre: string
  icon: string
  color?: string | null
}

/* -------------------- Query Keys & Fetchers -------------------- */
const facultadKeys = {
  root: ['facultades'] as const,
  all: () => [...facultadKeys.root, 'all'] as const,
}

async function fetchFacultades(): Promise<Facultad[]> {
  const { data, error } = await supabase
    .from('facultades')
    .select('id, nombre, icon, color')
    .order('nombre')
  if (error) throw error
  return (data ?? []) as Facultad[]
}

const facultadesOptions = () =>
  queryOptions({ queryKey: facultadKeys.all(), queryFn: fetchFacultades, staleTime: 60_000 })

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

/* ----------- Paleta curada ----------- */
const PALETTE: { name: string; hex: `#${string}` }[] = [
  { name: 'Indigo', hex: '#4F46E5' },
  { name: 'Blue', hex: '#2563EB' },
  { name: 'Sky', hex: '#0EA5E9' },
  { name: 'Teal', hex: '#14B8A6' },
  { name: 'Emerald', hex: '#10B981' },
  { name: 'Lime', hex: '#84CC16' },
  { name: 'Amber', hex: '#F59E0B' },
  { name: 'Orange', hex: '#F97316' },
  { name: 'Red', hex: '#EF4444' },
  { name: 'Rose', hex: '#F43F5E' },
  { name: 'Violet', hex: '#7C3AED' },
  { name: 'Purple', hex: '#9333EA' },
  { name: 'Fuchsia', hex: '#C026D3' },
  { name: 'Slate', hex: '#334155' },
  { name: 'Zinc', hex: '#3F3F46' },
  { name: 'Neutral', hex: '#404040' },
]

/* Un set corto y útil de íconos Lucide */
const ICON_CHOICES = [
  'Building2', 'Building', 'School', 'University', 'Landmark', 'Library', 'Layers',
  'Atom', 'FlaskConical', 'Microscope', 'Cpu', 'Hammer', 'Palette', 'Shapes', 'BookOpen', 'GraduationCap',
] as const
export type IconName = (typeof ICON_CHOICES)[number]

function gradientFrom(color?: string | null) {
  const base = color && /^#([0-9a-f]{6}|[0-9a-f]{3})$/i.test(color) ? color : '#2563eb'
  return `linear-gradient(135deg, ${base} 0%, ${base}CC 40%, ${base}99 70%, ${base}66 100%)`
}

/* -------------------- Página -------------------- */
function RouteComponent() {
  const router = useRouter()
  const qc = useQueryClient()
  const { data: facultades } = useSuspenseQuery(facultadesOptions())

  const [createOpen, setCreateOpen] = useState(false)
  const [editOpen, setEditOpen] = useState(false)

  const [form, setForm] = useState<{ nombre: string; icon: IconName; color: `#${string}` }>(
    { nombre: '', icon: 'Building2', color: '#2563EB' },
  )
  const [editing, setEditing] = useState<Facultad | null>(null)

  /* --------- Mutations (create / update) --------- */
  const createFacultad = useMutation({
    mutationFn: async (payload: { nombre: string; icon: IconName; color: `#${string}` }) => {
      const { error } = await supabase.from('facultades').insert(payload)
      if (error) throw new Error(error.message)
    },
    onSuccess: async () => {
      toast.success('Facultad creada ✨')
      setCreateOpen(false)
      await qc.invalidateQueries({ queryKey: facultadKeys.root })
      router.invalidate()
    },
    onError: (e: any) => toast.error(e?.message || 'No se pudo crear'),
  })

  const updateFacultad = useMutation({
    mutationFn: async ({ id, ...payload }: { id: string; nombre: string; icon: IconName; color: `#${string}` }) => {
      const { error } = await supabase.from('facultades').update(payload).eq('id', id)
      if (error) throw new Error(error.message)
    },
    onSuccess: async () => {
      toast.success('Cambios guardados ✅')
      setEditOpen(false)
      setEditing(null)
      await qc.invalidateQueries({ queryKey: facultadKeys.root })
      router.invalidate()
    },
    onError: (e: any) => toast.error(e?.message || 'No se pudo guardar'),
  })

  function openCreate() {
    setForm({ nombre: '', icon: 'Building2', color: '#2563EB' })
    setCreateOpen(true)
  }
  function openEdit(f: Facultad) {
    setEditing(f)
    setForm({
      nombre: f.nombre,
      icon: (ICON_CHOICES.includes(f.icon as IconName) ? (f.icon as IconName) : 'Building2'),
      color: f.color && /^#([0-9a-f]{6}|[0-9a-f]{3})$/i.test(f.color) ? (f.color as `#${string}`) : '#2563EB',
    })
    setEditOpen(true)
  }

  return (
    <div className="p-6 space-y-4">
      {/* Header */}
      <div className="flex items-center justify-between">
        <h1 className="text-xl font-bold flex items-center gap-2">
          <Icons.Building2 className="w-5 h-5" /> Facultades
        </h1>
        <div className="flex items-center gap-2">
          <Button
            variant="outline"
            onClick={async () => {
              await qc.invalidateQueries({ queryKey: facultadKeys.root })
              router.invalidate()
            }}
          >
            <Icons.RefreshCcw className="w-4 h-4 mr-2" /> Recargar
          </Button>
          <Button onClick={openCreate}>
            <Icons.Plus className="w-4 h-4 mr-2" /> Nueva facultad
          </Button>
        </div>
      </div>

      {/* Grid */}
      <div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
        {facultades.map((fac) => {
          const LucideIcon = (Icons as any)[fac.icon] || Icons.Building2
          const bg = { background: gradientFrom(fac.color) }
          return (
            <div key={fac.id} className="group relative rounded-3xl overflow-hidden shadow-xl border">
              <Link
                to="/facultad/$facultadId"
                params={{ facultadId: fac.id }}
                aria-label={`Administrar ${fac.nombre}`}
                className="block focus:outline-none focus-visible:ring-4 ring-white/60"
                style={bg}
              >
                <div
                  className="absolute inset-0 opacity-0 group-hover:opacity-15 transition-opacity"
                  style={{ background: 'radial-gradient(1200px 400px at 20% -20%, rgba(255,255,255,.45), transparent 60%)' }}
                />
                <div className="relative h-56 sm:h-64 lg:h-72 p-6 flex flex-col justify-between text-white">
                  <LucideIcon className="w-20 h-20 md:w-24 md:h-24 drop-shadow-md" />
                  <div className="flex items-end justify-between">
                    <h3 className="text-xl md:text-2xl font-bold drop-shadow-sm pr-2">{fac.nombre}</h3>
                    <Icons.ArrowRight className="w-6 h-6 opacity-0 translate-x-2 group-hover:opacity-100 group-hover:translate-x-0 transition-all" />
                  </div>
                </div>
              </Link>

              <div className="absolute top-3 right-3">
                <Button size="icon" variant="secondary" className="backdrop-blur bg-white/80 hover:bg-white" onClick={() => openEdit(fac)}>
                  <Icons.Pencil className="w-4 h-4" />
                </Button>
              </div>
            </div>
          )
        })}
      </div>

      {/* Dialog Crear */}
      <Dialog open={createOpen} onOpenChange={setCreateOpen}>
        <DialogContent className="sm:max-w-lg">
          <DialogHeader>
            <DialogTitle>Nueva facultad</DialogTitle>
          </DialogHeader>

          <FormFields form={form} setForm={setForm} />

          <DialogFooter>
            <Button variant="outline" onClick={() => setCreateOpen(false)}>Cancelar</Button>
            <Button
              onClick={() => {
                if (!form.nombre.trim()) { toast.error('Nombre requerido'); return }
                createFacultad.mutate({ nombre: form.nombre.trim(), icon: form.icon, color: form.color })
              }}
              disabled={createFacultad.isPending}
            >
              {createFacultad.isPending ? 'Guardando…' : 'Crear'}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Dialog Editar */}
      <Dialog open={editOpen} onOpenChange={(o) => { setEditOpen(o); if (!o) setEditing(null) }}>
        <DialogContent className="sm:max-w-lg">
          <DialogHeader>
            <DialogTitle>Editar facultad</DialogTitle>
          </DialogHeader>

          <FormFields form={form} setForm={setForm} />

          <DialogFooter>
            <Button variant="outline" onClick={() => { setEditOpen(false); setEditing(null) }}>Cancelar</Button>
            <Button
              onClick={() => {
                if (!editing) return
                if (!form.nombre.trim()) { toast.error('Nombre requerido'); return }
                updateFacultad.mutate({ id: editing.id, nombre: form.nombre.trim(), icon: form.icon, color: form.color })
              }}
              disabled={updateFacultad.isPending}
            >
              {updateFacultad.isPending ? 'Guardando…' : 'Guardar'}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  )
}

/* ----------- Subcomponentes ----------- */
function FormFields({
  form,
  setForm,
}: {
  form: { nombre: string; icon: IconName; color: `#${string}` }
  setForm: React.Dispatch<React.SetStateAction<{ nombre: string; icon: IconName; color: `#${string}` }>>
}) {
  const PreviewIcon = (Icons as any)[form.icon] || Icons.Building2
  const bg = useMemo(() => ({ background: gradientFrom(form.color) }), [form.color])

  return (
    <div className="grid gap-4">
      {/* Preview */}
      <div className="rounded-2xl overflow-hidden border">
        <div className="h-36 p-4 flex items-end justify-between text-white" style={bg}>
          <PreviewIcon className="w-14 h-14 drop-shadow-md" />
          <span className="text-xs bg-white/20 px-2 py-1 rounded">Vista previa</span>
        </div>
      </div>

      {/* Nombre */}
      <div className="space-y-1">
        <Label>Nombre</Label>
        <Input value={form.nombre} onChange={(e) => setForm((s) => ({ ...s, nombre: e.target.value }))} placeholder="Facultad de Ingeniería" />
      </div>

      {/* Icono */}
      <div className="space-y-1">
        <Label>Ícono</Label>
        <Select value={form.icon} onValueChange={(v) => setForm((s) => ({ ...s, icon: v as IconName }))}>
          <SelectTrigger><SelectValue placeholder="Selecciona ícono" /></SelectTrigger>
          <SelectContent className="max-h-72">
            {ICON_CHOICES.map((k) => {
              const Ico = (Icons as any)[k]
              return (
                <SelectItem key={k} value={k}>
                  <span className="inline-flex items-center gap-2">
                    <Ico className="w-4 h-4" /> {k}
                  </span>
                </SelectItem>
              )
            })}
          </SelectContent>
        </Select>
      </div>

      {/* Color (paleta curada) */}
      <div className="space-y-2">
        <Label>Color</Label>
        <ColorGrid value={form.color} onChange={(hex) => setForm((s) => ({ ...s, color: hex }))} />
      </div>
    </div>
  )
}

function ColorGrid({ value, onChange }: { value: `#${string}`; onChange: (hex: `#${string}`) => void }) {
  return (
    <div className="grid grid-cols-8 gap-2">
      {PALETTE.map((c) => (
        <button
          key={c.hex}
          type="button"
          onClick={() => onChange(c.hex)}
          className={`relative h-9 rounded-xl ring-1 ring-black/10 transition ${value === c.hex ? 'outline outline-2 outline-offset-2 outline-black/70' : 'hover:scale-[1.03]'}`}
          style={{ background: c.hex }}
          title={c.name}
          aria-label={c.name}
        >
          {value === c.hex && <Icons.Check className="absolute right-1.5 bottom-1.5 w-4 h-4 text-white drop-shadow" />}
        </button>
      ))}
    </div>
  )
}
