import { createFileRoute, Link, redirect } from "@tanstack/react-router"
import { useEffect, useMemo, useRef, useState } from "react"
import * as Icons from "lucide-react"
import { useMutation, useQueryClient, useSuspenseQuery } from "@tanstack/react-query"
import { supabase, useSupabaseAuth } from "@/auth/supabase"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { AcademicSections, planKeys } from "@/components/planes/academic-sections"
import { GradientMesh } from "../../../components/planes/GradientMesh"
import { asignaturaExtraOptions, asignaturaKeys, asignaturasCountOptions, asignaturasPreviewOptions, planByIdOptions, type AsignaturaLite, type PlanFull } from "@/components/planes/planQueries"
import { softAccentStyle } from "@/components/planes/planHelpers"
import { Dialog, DialogContent, DialogDescription, DialogTitle } from "@/components/ui/dialog"
import { DialogFooter, DialogHeader } from "@/components/ui/dialog"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import confetti from "canvas-confetti"
import { Textarea } from "@/components/ui/textarea"
import { AuroraButton } from "@/components/effect/aurora-button"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { DeletePlanButton } from "@/components/planes/DeletePlan"
import { AddAsignaturaButton } from "@/components/planes/AddAsignaturaButton"

type LoaderData = { planId: string }

export const Route = createFileRoute("/_authenticated/plan/$planId")({
  component: RouteComponent,
  pendingComponent: PageSkeleton,
  beforeLoad: ({ params }) => {
    if (!params.planId) {
      throw redirect({ to: "/planes", search: { plan: "" } })
    }
  },

  loader: async ({ params, context: { queryClient } }): Promise<LoaderData> => {
    const { planId } = params
    await Promise.all([
      queryClient.ensureQueryData(planByIdOptions(planId)),
      queryClient.ensureQueryData(asignaturasCountOptions(planId)),
      queryClient.ensureQueryData(asignaturasPreviewOptions(planId)),
    ])
    return { planId }
  },
})

// ...existing code...
function RouteComponent() {
  const qc = useQueryClient()
  const { planId } = Route.useLoaderData() as LoaderData
  const auth = useSupabaseAuth()

  const { data: plan } = useSuspenseQuery(planByIdOptions(planId))
  const { data: asignaturasCount } = useSuspenseQuery(asignaturasCountOptions(planId))
  const { data: asignaturasPreview } = useSuspenseQuery(asignaturasPreviewOptions(planId))

  const showFacultad = auth.claims?.role === 'lci' || auth.claims?.role === 'vicerrectoria'
  const showCarrera = auth.claims?.role === 'secretario_academico'

  const fac = plan.carreras?.facultades
  const accent = useMemo(() => softAccentStyle(fac?.color), [fac?.color])
  const IconComp = (fac?.icon && (Icons as any)[fac.icon]) || Icons.Building2
  const facColor = plan.carreras?.facultades?.color ?? null

  // Animaciones y refs pueden modularizarse si se desea
  const headerRef = useRef<HTMLDivElement>(null)
  const statsRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    // ...animaciones header y stats...
  }, [])

  return (
    <div className="relative p-6 space-y-6">
      <GradientMesh color={fac?.color} />
      <nav className="relative text-sm text-neutral-500">
        <Link to="/planes" search={{ plan: '' }} className="hover:underline">Planes de estudio</Link>
        <span className="mx-1">/</span>
        <span className="text-primary">{plan.nombre}</span>
      </nav>
      <Card ref={headerRef} className="relative overflow-hidden border shadow-sm">
        <div className="absolute inset-0 -z-0" style={accent} />
        <CardHeader className="relative z-10 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
          <div className="flex items-center gap-3 min-w-0">
            <span className="hdr-icon inline-flex items-center justify-center rounded-2xl border px-3 py-2 bg-white/70"
              style={{ borderColor: accent.borderColor as string }}>
              <IconComp className="w-6 h-6" />
            </span>
            <div className="min-w-0">
              <CardTitle className="hdr-title truncate font-mono">{plan.nombre}</CardTitle>
              <div className="hdr-chips text-xs text-neutral-600 truncate">
                {showCarrera && plan.carreras?.nombre ? `Carrera: ${plan.carreras.nombre}` : null}
                {showFacultad && fac?.nombre ? `${showCarrera ? ' · ' : ''}Facultad: ${fac.nombre}` : null}
              </div>
            </div>
          </div>
          <div className="hdr-chips flex flex-wrap items-center gap-2">
            {plan.estado && (
              <Badge variant="outline" className="bg-white/60" style={{ borderColor: accent.borderColor }}>
                {plan.estado}
              </Badge>
            )}
            <div className='flex gap-2'>
              <EditPlanButton plan={plan} />
              <AdjustAIButton plan={plan} />
              <DeletePlanButton planId={plan.id} />
            </div>
          </div>
        </CardHeader>
        <CardContent ref={statsRef}>
          <div className="academics relative z-10 grid gap-3 [grid-template-columns:repeat(auto-fit,minmax(180px,1fr))]">
            <StatCard label="Nivel" value={plan.nivel ?? "—"} Icon={Icons.GraduationCap} accent={facColor} />
            <StatCard label="Duración" value={plan.duracion ?? "—"} Icon={Icons.Clock} accent={facColor} />
            <StatCard label="Créditos" value={fmt(plan.total_creditos)} Icon={Icons.Coins} accent={facColor} />
            <StatCard label="Creado" value={plan.fecha_creacion ? new Date(plan.fecha_creacion).toLocaleDateString() : "—"} Icon={Icons.CalendarDays} accent={facColor} />
          </div>
        </CardContent>
      </Card>
      <div className="academics">
        <AcademicSections planId={plan.id} color={fac?.color} />
      </div>
      <Card className="border shadow-sm">
        <CardHeader className="flex items-center justify-between gap-2">
          <CardTitle className="text-base font-mono">Asignaturas ({asignaturasCount})</CardTitle>
          <div className="flex items-center gap-2">
            <AddAsignaturaButton planId={plan.id} onAdded={() => {
              qc.invalidateQueries({ queryKey: asignaturaKeys.count(plan.id) })
              qc.invalidateQueries({ queryKey: asignaturaKeys.preview(plan.id) })
            }} />
            <Link
              to="/asignaturas/$planId"
              search={{ q: "", planId: plan.id, carreraId: "", f: "", facultadId: "" }}
              params={{ planId: plan.id }}
              className="inline-flex items-center gap-2 rounded-xl border px-3 py-2 text-sm hover:bg-neutral-50"
              title="Ver todas las asignaturas"
            >
              <Icons.BookOpen className="w-4 h-4" /> Ver en página de Asignaturas
            </Link>
          </div>
        </CardHeader>
        <CardContent>
          {asignaturasPreview.length === 0 ? (
            <div className="text-sm text-neutral-500">Sin asignaturas</div>
          ) : (
            <div className="grid gap-3 sm:grid-cols-2">
              {asignaturasPreview.map((a) => (
                <AsignaturaPreviewCard key={a.id} asignatura={a} />
              ))}
            </div>
          )}
        </CardContent>
      </Card>
    </div>
  )
}

function hexToRgbA(hex?: string | null, a = .25) {
  if (!hex) return `rgba(37,99,235,${a})`
  const h = hex.replace("#", "")
  const v = h.length === 3 ? h.split("").map(c => c + c).join("") : h
  const n = parseInt(v, 16)
  const r = (n >> 16) & 255, g = (n >> 8) & 255, b = n & 255
  return `rgba(${r},${g},${b},${a})`
}

const fmt = (n?: number | null) => (n !== null && n !== undefined) ? Intl.NumberFormat().format(n) : "—"

/* ===== UI bits ===== */
function StatCard({ label, value = "—", Icon = Icons.Info, accent, className = "", title }: {
  label: string
  value?: React.ReactNode
  Icon?: React.ComponentType<React.SVGProps<SVGSVGElement>>
  accent?: string | null
  className?: string
  title?: string
}) {
  const border = hexToRgbA(accent, .28)
  const chipBg = hexToRgbA(accent, .08)
  const glow = hexToRgbA(accent, .14)

  return (
    <div
      className={`group relative overflow-hidden rounded-2xl border p-4 sm:p-5 bg-white/70 dark:bg-neutral-900/60 backdrop-blur shadow-sm hover:shadow-md transition-all ${className}`}
      style={{ borderColor: border }}
      title={title ?? (typeof value === "string" ? value : undefined)}
      aria-label={`${label}: ${typeof value === "string" ? value : ""}`}
    >
      <div className="flex items-center justify-between gap-3">
        <div className="text-xs text-neutral-500">{label}</div>
        <span className="inline-flex items-center justify-center rounded-xl px-2.5 py-2 border" style={{ borderColor: border, background: chipBg }}>
          <Icon className="h-4 w-4 opacity-80" />
        </span>
      </div>
      <div className="mt-1 text-2xl font-semibold tabular-nums tracking-tight truncate">{value}</div>
      <div className="pointer-events-none absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity" style={{ background: `radial-gradient(600px 120px at 20% -10%, ${glow}, transparent 60%)` }} />
    </div>
  )
}

/* ===== Editar ===== */
function EditPlanButton({ plan }: { plan: PlanFull }) {
  const [open, setOpen] = useState(false)
  const [form, setForm] = useState<Partial<PlanFull>>({})
  const [saving, setSaving] = useState(false)
  const qc = useQueryClient()

  const mutation = useMutation({
    mutationFn: async (payload: Partial<PlanFull>) => {
      const { error } = await supabase.from('plan_estudios').update({
        nombre: payload.nombre ?? plan.nombre,
        nivel: payload.nivel ?? plan.nivel,
        duracion: payload.duracion ?? plan.duracion,
        total_creditos: payload.total_creditos ?? plan.total_creditos,
      }).eq('id', plan.id)
      if (error) throw error
    },
    onMutate: async (payload) => {
      await qc.cancelQueries({ queryKey: planKeys.byId(plan.id) })
      const prev = qc.getQueryData<PlanFull>(planKeys.byId(plan.id))
      qc.setQueryData<PlanFull>(planKeys.byId(plan.id), (old) => old ? { ...old, ...payload } as PlanFull : old as any)
      return { prev }
    },
    onError: (_e, _vars, ctx) => {
      if (ctx?.prev) qc.setQueryData(planKeys.byId(plan.id), ctx.prev)
    },
    onSettled: async () => {
      await qc.invalidateQueries({ queryKey: planKeys.byId(plan.id) })
    }
  })

  async function save() {
    setSaving(true)
    try {
      await mutation.mutateAsync(form)
      setOpen(false)
    } finally { setSaving(false) }
  }

  return (
    <>
      <Button variant="secondary" onClick={() => { setForm(plan); setOpen(true) }}>
        <Icons.Pencil className="w-4 h-4 mr-2" /> Editar
      </Button>
      <Dialog open={open} onOpenChange={setOpen}>
        <DialogContent className="max-w-lg">
          <DialogHeader>
            <DialogTitle className="font-mono" >Editar plan</DialogTitle>
            <DialogDescription>Actualiza datos básicos.</DialogDescription>
          </DialogHeader>
          <div className="grid gap-3">
            <Field label="Nombre"><Input value={form.nombre ?? ''} onChange={(e) => setForm({ ...form, nombre: e.target.value })} /></Field>
            <Field label="Nivel"><Input value={form.nivel ?? ''} onChange={(e) => setForm({ ...form, nivel: e.target.value })} /></Field>
            <Field label="Duración"><Input value={form.duracion ?? ''} onChange={(e) => setForm({ ...form, duracion: e.target.value })} /></Field>
            <Field label="Créditos totales"><Input value={String(form.total_creditos ?? '')} onChange={(e) => setForm({ ...form, total_creditos: Number(e.target.value) || null })} /></Field>
          </div>
          <DialogFooter>
            <Button onClick={save} disabled={saving || mutation.isPending}>{(saving || mutation.isPending) ? 'Guardando…' : 'Guardar'}</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  )
}
function Field({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <div className="space-y-1">
      <Label className="text-xs text-neutral-600">{label}</Label>
      {children}
    </div>
  )
}

/* ===== Ajustar IA ===== */
function AdjustAIButton({ plan }: { plan: PlanFull }) {
  const [open, setOpen] = useState(false)
  const [prompt, setPrompt] = useState('')
  const [loading, setLoading] = useState(false)

  async function apply() {
    setLoading(true)
    await fetch(`${import.meta.env.VITE_BACK_ORIGIN}/api/mejorar/plan`, {
      method: 'POST', headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ prompt, plan_id: plan.id }),
    }).catch(() => { })
    setLoading(false)
    confetti({ particleCount: 120, spread: 80, origin: { y: 0.6 } })
    setOpen(false)
  }

  return (
    <>
      <Button onClick={() => setOpen(true)}>
        <Icons.Sparkles className="w-4 h-4 mr-2" /> Ajustar con IA
      </Button>
      <Dialog open={open} onOpenChange={setOpen}>
        <DialogContent className="max-w-lg">
          <DialogHeader>
            <DialogTitle className="font-mono" >Ajustar con IA</DialogTitle>
            <DialogDescription>Describe cómo quieres modificar el plan actual.</DialogDescription>
          </DialogHeader>
          <Textarea value={prompt} onChange={(e) => setPrompt(e.target.value)} placeholder="Ej.: Enfatiza ciberseguridad y proyectos prácticos…" className="min-h-[120px]" />
          <DialogFooter>
            <AuroraButton onClick={apply} disabled={!prompt.trim() || loading}>
              {loading ? 'Aplicando…' : 'Aplicar ajuste'}
            </AuroraButton>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  )
}

/* ===== Skeleton ===== */
function Pulse({ className = '' }: { className?: string }) {
  return <div className={`animate-pulse bg-neutral-200 rounded-xl ${className}`} />
}
function PageSkeleton() {
  return (
    <div className="p-6 space-y-6">
      <div className="border rounded-2xl p-6">
        <div className="flex items-center gap-3">
          <Pulse className="w-10 h-10" />
          <div className="flex-1 space-y-2">
            <Pulse className="h-5 w-64" />
            <Pulse className="h-3 w-48" />
          </div>
        </div>
        <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4 mt-4">
          {Array.from({ length: 5 }).map((_, i) => <Pulse key={i} className="h-14" />)}
        </div>
      </div>
      <div className="grid gap-6 lg:grid-cols-2">
        {Array.from({ length: 6 }).map((_, i) => <Pulse key={i} className="h-40" />)}
      </div>
    </div>
  )
}

/* ===== Asignaturas ===== */
function AsignaturaPreviewCard({ asignatura }: { asignatura: AsignaturaLite }) {
  const { data: extra } = useSuspenseQuery(asignaturaExtraOptions(asignatura.id))

  const horasT = extra?.horas_teoricas ?? null
  const horasP = extra?.horas_practicas ?? null
  const horasTot = (horasT ?? 0) + (horasP ?? 0)

  const resumenContenidos = useMemo(() => {
    const c = extra?.contenidos
    if (!c) return { unidades: 0, temas: 0 }
    const unidades = Object.keys(c).length
    const temas = Object.values(c).reduce((acc, temasObj) => acc + Object.keys(temasObj || {}).length, 0)
    return { unidades, temas }
  }, [extra?.contenidos])

  const tipo = (extra?.tipo ?? "").toLowerCase()
  const tipoChip =
    tipo.includes("oblig") ? "bg-emerald-50 text-emerald-700 border-emerald-200" :
      tipo.includes("opt") ? "bg-amber-50 text-amber-800 border-amber-200" :
        tipo.includes("taller") ? "bg-indigo-50 text-indigo-700 border-indigo-200" :
          tipo.includes("lab") ? "bg-sky-50 text-sky-700 border-sky-200" :
            "bg-neutral-100 text-neutral-700 border-neutral-200"

  return (
    <article className="group relative overflow-hidden rounded-2xl border bg-white/70 dark:bg-neutral-900/60 backdrop-blur p-4 shadow-sm hover:shadow-md transition-all hover:-translate-y-0.5" role="region" aria-label={asignatura.nombre}>
      <div className="flex items-start gap-3">
        <div className="h-9 w-9 rounded-xl grid place-items-center border bg-white/80">
          <Icons.BookOpen className="h-4 w-4" />
        </div>
        <div className="min-w-0">
          <div className="font-medium truncate" title={asignatura.nombre}>{asignatura.nombre}</div>
          <div className="mt-1 flex flex-wrap items-center gap-1.5 text-[11px]">
            {asignatura.semestre != null && (
              <span className="inline-flex items-center gap-1 rounded-full border px-2 py-0.5">
                <Icons.Calendar className="h-3 w-3" /> S{asignatura.semestre}
              </span>
            )}
            {asignatura.creditos != null && (
              <span className="inline-flex items-center gap-1 rounded-full border px-2 py-0.5">
                <Icons.Coins className="h-3 w-3" /> {asignatura.creditos} cr
              </span>
            )}
            {extra?.tipo && (
              <span className={`inline-flex items-center gap-1 rounded-full border px-2 py-0.5 ${tipoChip}`}>
                <Icons.Tag className="h-3 w-3" /> {extra.tipo}
              </span>
            )}
          </div>
        </div>
      </div>

      <div className="mt-3 grid grid-cols-3 gap-2 text-[11px]">
        <SmallStat icon={Icons.Clock} label="Horas" value={horasTot || "—"} />
        <SmallStat icon={Icons.BookMarked} label="Unidades" value={resumenContenidos.unidades || "—"} />
        <SmallStat icon={Icons.ListTree} label="Temas" value={resumenContenidos.temas || "—"} />
      </div>

      <div className="mt-3 flex items-center justify-between">
        <div className="text-[11px] text-neutral-500">
          {horasT != null || horasP != null ? (
            <>H T/P: {horasT ?? "—"}/{horasP ?? "—"}</>
          ) : (
            <span className="opacity-70">Resumen listo</span>
          )}
        </div>
        <Link to="/asignatura/$asignaturaId" params={{ asignaturaId: asignatura.id }} className="inline-flex items-center gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs hover:bg-neutral-50" title="Ver detalle">
          Ver detalle <Icons.ArrowRight className="h-3.5 w-3.5" />
        </Link>
      </div>

      <div className="pointer-events-none absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity" style={{ background: "radial-gradient(600px 120px at 20% -10%, rgba(0,0,0,.06), transparent 60%)" }} />
    </article>
  )
}

function SmallStat({ icon: Icon, label, value }: { icon: React.ComponentType<React.SVGProps<SVGSVGElement>>; label: string; value: string | number }) {
  return (
    <div className="rounded-lg border bg-white/60 dark:bg-neutral-900/50 px-2.5 py-2">
      <div className="flex items-center gap-1 text-[10px] text-neutral-500">
        <Icon className="h-3.5 w-3.5" /> {label}
      </div>
      <div className="mt-0.5 font-medium tabular-nums">{value}</div>
    </div>
  )
}
