// routes/_authenticated/asignatura/$asignaturaId.tsx
import { useQueryClient } from "@tanstack/react-query";
import { createFileRoute, Link, useRouter } from "@tanstack/react-router"
import * as Icons from "lucide-react"
import { useCallback, useEffect, useMemo, useRef, useState } from "react"
import { supabase, useSupabaseAuth } from "@/auth/supabase"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
import { Input } from "@/components/ui/input"
import {
  Select,
  SelectTrigger,
  SelectContent,
  SelectItem,
  SelectValue
} from "@/components/ui/select"
import confetti from "canvas-confetti"

import {
  Accordion, AccordionContent, AccordionItem, AccordionTrigger,
} from "@/components/ui/accordion"
import {
  Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle,
} from "@/components/ui/dialog"
import { Textarea } from "@/components/ui/textarea"
import { Label } from "@/components/ui/label"
import { Separator } from "@/components/ui/separator"
import { ScrollArea } from "@/components/ui/scroll-area"
import { typeStyle } from "@/components/asignaturas/typeStyle"
import { Stat } from "@/components/asignaturas/Stat"
import { Section } from "@/components/asignaturas/Section"
import { EditBibliografiaButton } from "@/components/asignaturas/EditBibliografíaButton"

/* ================== Tipos ================== */
type Asignatura = {
  id: string; nombre: string; clave: string | null; tipo: string | null; semestre: number | null;
  creditos: number | null; horas_teoricas: number | null; horas_practicas: number | null;
  objetivos: string | null; contenidos: Record<string, Record<string, string>> | null;
  bibliografia: string[] | null; criterios_evaluacion: string | null; plan_id: string | null;
}
type PlanMini = { id: string; nombre: string }

/* ================== Ruta ================== */
export const Route = createFileRoute("/_authenticated/asignatura/$asignaturaId")({
  component: Page,
  loader: async ({ params }) => {
    const { data: a, error } = await supabase
      .from("asignaturas")
      .select("id, nombre, clave, tipo, semestre, creditos, horas_teoricas, horas_practicas, objetivos, contenidos, bibliografia, criterios_evaluacion, plan_id")
      .eq("id", params.asignaturaId)
      .single()
    if (error || !a) throw error ?? new Error("Asignatura no encontrada")

    let plan: PlanMini | null = null
    if (a.plan_id) {
      const { data: p } = await supabase
        .from("plan_estudios").select("id, nombre").eq("id", a.plan_id).single()
      plan = p as PlanMini | null
    }
    return { a: a as Asignatura, plan }
  },
})

/* ================== Helpers UI ================== */

function Page() {
  const router = useRouter()
  const { a: aFromLoader, plan } = Route.useLoaderData() as { a: Asignatura; plan: PlanMini | null }
  const [a, setA] = useState<Asignatura>(aFromLoader)

  const horasT = a.horas_teoricas ?? 0
  const horasP = a.horas_practicas ?? 0
  const horas = horasT + horasP
  const style = typeStyle(a.tipo)

  // ordenar unidades
  const unidades = useMemo(() => {
    const entries = Object.entries(a.contenidos ?? {})
    const norm = (s: string) => {
      const m = String(s).match(/^\s*(\d+)/)
      return m ? [parseInt(m[1], 10), s] as const : [Number.POSITIVE_INFINITY, s] as const
    }
    return entries
      .map(([k, v]) => ({ key: k, order: norm(k)[0], title: norm(k)[1], temas: Object.entries(v) }))
      .sort((A, B) => (A.order === B.order ? A.title.localeCompare(B.title) : A.order - B.order))
      .map(u => ({ ...u, temas: u.temas.sort(([x], [y]) => Number(x) - Number(y)) }))
  }, [a.contenidos])
  const temasCount = useMemo(() => unidades.reduce((acc, u) => acc + u.temas.length, 0), [unidades])

  // buscar dentro del syllabus
  const [query, setQuery] = useState("")
  const filteredUnidades = useMemo(() => {
    const t = query.trim().toLowerCase()
    if (!t) return unidades
    return unidades.map(u => ({
      ...u,
      temas: u.temas.filter(([, tema]) => String(tema).toLowerCase().includes(t)),
    })).filter(u => u.temas.length > 0)
  }, [query, unidades])

  // atajos
  const searchRef = useRef<HTMLInputElement | null>(null)
  useEffect(() => {
    const onKey = (e: KeyboardEvent) => {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") { e.preventDefault(); searchRef.current?.focus() }
      if (e.key === "Escape") router.history.back()
    }
    window.addEventListener("keydown", onKey)
    return () => window.removeEventListener("keydown", onKey)
  }, [router])

  async function share() {
    const url = window.location.href
    try {
      if (navigator.share) await navigator.share({ title: a.nombre, url })
      else { await navigator.clipboard.writeText(url); alert("Enlace copiado") }
    } catch { }
  }

  return (
    <div className="relative p-6 space-y-6">
      {/* ===== Migas ===== */}
      <nav className="text-sm text-neutral-500">
        <Link
          to={plan ? "/plan/$planId" : "/planes"}
          params={plan ? { planId: plan.id } : undefined}
          className="hover:underline"
        >
          {plan ? plan.nombre : "Planes"}
        </Link>
        <span className="mx-1">/</span>
        <span className="text-neutral-900">{a.nombre}</span>
      </nav>

      {/* ===== Hero ===== */}
      <div className="relative overflow-hidden rounded-3xl border shadow-sm">
        <div className={`absolute inset-0 bg-gradient-to-br ${style.halo} via-white to-transparent`} />
        <div className="relative p-6 flex flex-col grid grid-cols-1 gap-4 md:flex-row md:items-center md:justify-between">
          <div className="min-w-0">
            <div className="inline-flex items-center gap-2 text-xs text-neutral-600">
              <Icons.BookOpen className="h-4 w-4" /> Asignatura
              {plan && <>
                <span>·</span>
                <Link to="/plan/$planId" params={{ planId: plan.id }} className="hover:underline">
                  {plan.nombre}
                </Link>
              </>}
            </div>
            <h1 className="mt-1 text-2xl md:text-3xl font-bold truncate">{a.nombre}</h1>
            <div className="mt-2 flex flex-wrap items-center gap-2 text-[11px]">
              {a.clave && <Badge variant="outline">Clave: {a.clave}</Badge>}
              {a.tipo && <Badge className={style.chip} variant="secondary">{a.tipo}</Badge>}
              {a.creditos != null && <Badge variant="outline">{a.creditos} créditos</Badge>}
              <Badge variant="outline">H T/P: {horasT}/{horasP}</Badge>
              <Badge variant="outline">Semestre {a.semestre ?? "—"}</Badge>
            </div>
          </div>

          {/* Acciones rápidas */}
          <div className="flex items-center gap-2">
            <Button variant="outline" size="sm" onClick={() => window.print()}>
              <Icons.Printer className="h-4 w-4 mr-2" /> Imprimir
            </Button>
            <Button variant="outline" size="sm" onClick={share}>
              <Icons.Share2 className="h-4 w-4 mr-2" /> Compartir
            </Button>
            <EditAsignaturaButton asignatura={a} onUpdate={setA} />
            <MejorarAIButton asignaturaId={a.id} onApply={(nuevo) => setA(nuevo)} />
            <BorrarAsignaturaButton asignatura_id={a.id} />
          </div>
        </div>

        {/* Stats rápidos */}
        <div className="relative px-6 pb-6">
          <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
            <Stat icon={Icons.Coins} label="Créditos" value={a.creditos ?? "—"} />
            <Stat icon={Icons.Clock} label="Horas totales" value={horas} />
            <Stat icon={Icons.ListTree} label="Unidades" value={unidades.length} />
            <Stat icon={Icons.BookMarked} label="Temas" value={temasCount} />
          </div>
        </div>
      </div>

      {/* ===== Layout principal ===== */}
      <div className="grid gap-6 lg:grid-cols-[1fr,320px]">
        {/* ===== Columna principal ===== */}
        <div className="space-y-6">
          {/* Objetivo */}
          {a.objetivos && (
            <Section id="objetivo" title="Objetivo de la asignatura" icon={Icons.Target}>
              <p className="text-sm leading-relaxed text-neutral-800">{a.objetivos}</p>
            </Section>
          )}

          {/* Syllabus */}
          
            <Section id="syllabus" title="Programa / Contenidos" icon={Icons.ListTree}>
              <div className="flex items-center gap-2 mb-2">
                <div className="relative flex-1">
                  <Icons.Search className="absolute left-2 top-1/2 -translate-y-1/2 h-4 w-4 text-neutral-400" />
                  <Input
                    ref={searchRef}
                    value={query}
                    onChange={(e) => setQuery(e.target.value)}
                    placeholder="Buscar tema dentro del programa (⌘/Ctrl K)…"
                    className="pl-8"
                  />
                </div>
                {query && (
                  <Button variant="ghost" onClick={() => setQuery("")}>Limpiar</Button>
                )}
              </div>

              {/* NUEVO: botón de edición */}
              <div className="flex justify-end mb-2">
                <EditContenidosButton
                  asignaturaId={a.id}
                  value={a.contenidos as any}
                  onSaved={(contenidos) => setA(s => ({ ...s, contenidos }))}
                />
              </div>

              {/* …tu render flexible existente… */}
              {(() => {
                // helpers de normalización (como ya los tienes)
                const titleOf = (u: any): string => {
                  const t = (u.temas || []).find(([k]: any[]) => String(k).toLowerCase() === "titulo")?.[1]
                  if (typeof t === "string" && t.trim()) return t
                  return /^\s*\d+/.test(String(u.key))
                    ? (u.title && u.title !== u.key ? u.title : `Unidad ${u.key && Number(u.key) ? Number(u.key) : 1}`)
                    : (u.title || String(u.key))
                }
                const temasOf = (u: any): string[] => {
                  const pairs: any[] = Array.isArray(u.temas) ? u.temas : []
                  const sub = pairs.find(([k]) => String(k).toLowerCase() === "subtemas")?.[1]
                  if (Array.isArray(sub)) return sub.map(String)
                  if (sub && typeof sub === "object") {
                    return Object.entries(sub).sort(([a], [b]) => Number(a) - Number(b)).map(([, v]) => String(v))
                  }
                  const numerados = pairs
                    .filter(([k, v]) => /^\d+$/.test(String(k)) && (typeof v === "string" || typeof v === "number"))
                    .sort(([a], [b]) => Number(a) - Number(b))
                    .map(([, v]) => String(v))
                  if (numerados.length) return numerados
                  return pairs
                    .filter(([k, v]) => !["titulo", "seccion"].includes(String(k).toLowerCase()) && typeof v === "string")
                    .map(([, v]) => String(v))
                }

                const q = query.trim().toLowerCase()
                const visible = (filteredUnidades.length ? filteredUnidades : unidades)
                  .map((u: any) => {
                    const list = temasOf(u)
                    const title = titleOf(u)
                    const match = !q || list.some(t => t.toLowerCase().includes(q)) || title.toLowerCase().includes(q)
                    return { ...u, __title: title, __temas: list, __match: match }
                  })
                  .filter((u: any) => u.__match)

                return (
                  <Accordion type="multiple" className="mt-2">
                    {visible.map((u: any, i: number) => (
                      <AccordionItem key={`${u.key}-${i}`} value={`u-${i}`} className="border rounded-xl mb-2 overflow-hidden">
                        <AccordionTrigger className="px-4 py-2 hover:no-underline text-left">
                          <div className="flex items-center justify-between w-full">
                            <span className="font-medium">
                              {/^\s*\d+/.test(String(u.key))
                                ? `Unidad ${u.key && Number(u.key) ? Number(u.key) : 1}${u.__title ? `: ${u.__title}` : ""}`
                                : u.__title}
                            </span>
                            <span className="text-[11px] text-neutral-500">{u.__temas.length} tema(s)</span>
                          </div>
                        </AccordionTrigger>
                        <AccordionContent className="px-5 pb-3">
                          <ul className="list-disc ml-5 text-[13px] text-neutral-700 space-y-1">
                            {u.__temas.map((t: string, idx: number) => (
                              <li key={idx} className="break-words">{t}</li>
                            ))}
                          </ul>
                        </AccordionContent>
                      </AccordionItem>
                    ))}
                    {!visible.length && (
                      <div className="text-sm text-neutral-500 py-6 text-center">No hay temas que coincidan.</div>
                    )}
                  </Accordion>
                )
              })()}
            </Section>
          


          {/* Bibliografía */}
          <Section id="bibliografia" title="Bibliografía" icon={Icons.LibraryBig}>
            <div className="flex justify-end mb-2">
              <EditBibliografiaButton
                asignaturaId={a.id}
                value={a.bibliografia ?? []}
                onSaved={(bibliografia) => setA(s => ({ ...s, bibliografia }))}
              />
            </div>

            {a.bibliografia && a.bibliografia.length > 0 ? (
              <ul className="space-y-2 text-sm text-neutral-800">
                {a.bibliografia.map((ref, i) => (
                  <li key={i} className="flex items-start gap-2 leading-relaxed">
                    <span className="mt-1 text-neutral-400">•</span>
                    <span className="break-words">{ref}</span>
                  </li>
                ))}
              </ul>
            ) : (
              <div className="text-sm text-neutral-500">Sin bibliografía.</div>
            )}
          </Section>


          {/* Evaluación */}
          {a.criterios_evaluacion && (
            <Section id="evaluacion" title="Criterios de evaluación" icon={Icons.ClipboardCheck}>
              <p className="text-sm text-neutral-800 leading-relaxed">{a.criterios_evaluacion}</p>
            </Section>
          )}
        </div>

        {/* ===== Sidebar ===== */}
        <aside className="space-y-4 lg:sticky lg:top-6 self-start">
          <div className="rounded-2xl border bg-white/70 dark:bg-neutral-900/60 p-4">
            <h4 className="font-semibold text-sm mb-2">Resumen</h4>
            <div className="grid grid-cols-2 gap-2 text-xs">
              <MiniKV label="Créditos" value={a.creditos ?? "—"} />
              <MiniKV label="Semestre" value={a.semestre ?? "—"} />
              <MiniKV label="Horas teóricas" value={horasT} />
              <MiniKV label="Horas prácticas" value={horasP} />
              <MiniKV label="Unidades" value={unidades.length} />
              <MiniKV label="Temas" value={temasCount} />
            </div>
          </div>

          <div className="rounded-2xl border bg-white/70 dark:bg-neutral-900/60 p-4">
            <h4 className="font-semibold text-sm mb-2">Navegación</h4>
            <nav className="text-sm space-y-1">
              {a.objetivos && <Anchor href="#objetivo" label="Objetivo" />}
              {unidades.length > 0 && <Anchor href="#syllabus" label="Programa / Contenidos" />}
              {a.bibliografia && a.bibliografia.length > 0 && <Anchor href="#bibliografia" label="Bibliografía" />}
              {a.criterios_evaluacion && <Anchor href="#evaluacion" label="Evaluación" />}
            </nav>
          </div>

          {plan && (
            <Link
              to="/plan/$planId"
              params={{ planId: plan.id }}
              className="block rounded-2xl border p-4 hover:bg-neutral-50 transition"
            >
              <div className="flex items-center gap-3">
                <div className="h-9 w-9 rounded-xl grid place-items-center border bg-white/80">
                  <Icons.ScrollText className="h-4 w-4" />
                </div>
                <div>
                  <div className="text-xs text-neutral-500">Plan de estudios</div>
                  <div className="font-medium truncate">{plan.nombre}</div>
                </div>
              </div>
            </Link>
          )}
        </aside>
      </div>

      {/* ===== Volver ===== */}
      <div className="pt-2">
        <Button variant="outline" asChild>
          <Link to={plan ? "/plan/$planId" : "/planes"} params={plan ? { planId: plan.id } : undefined}>
            <Icons.ArrowLeft className="h-4 w-4 mr-2" /> Volver
          </Link>
        </Button>
      </div>
    </div>
  )
}

/* ===== Bits Sidebar ===== */
function MiniKV({ label, value }: { label: string; value: string | number }) {
  return (
    <div className="rounded-xl border bg-white/60 p-2">
      <div className="text-[11px] text-neutral-500">{label}</div>
      <div className="font-medium tabular-nums">{value}</div>
    </div>
  )
}
function Anchor({ href, label }: { href: string; label: string }) {
  return (
    <a href={href} className="flex items-center gap-2 text-neutral-700 hover:underline">
      <Icons.Dot className="h-5 w-5 -ml-1" /> {label}
    </a>
  )
}

/* ======= Modales ======= */
function EditAsignaturaButton({ asignatura, onUpdate }: {
  asignatura: Asignatura; onUpdate: (a: Asignatura) => void
}) {
  const [open, setOpen] = useState(false)
  const [saving, setSaving] = useState(false)
  const [form, setForm] = useState<Partial<Asignatura>>({})
  const auth = useSupabaseAuth()

  const openAndFill = () => { setForm(asignatura); setOpen(true) }

  // ✅ Función que genera las diferencias entre los datos anteriores y los nuevos
  function generateDiff(oldData: Asignatura, newData: Partial<Asignatura>) {
    const changes: any[] = []
    for (const key of Object.keys(newData)) {
      const oldValue = (oldData as any)[key]
      const newValue = (newData as any)[key]
      if (newValue !== undefined && newValue !== oldValue) {
        changes.push({
          op: "replace",
          path: `/${key}`,
          from: oldValue,
          value: newValue
        })
      }
    }
    return changes
  }

  async function save() {
    setSaving(true)
    try {
      // 1️⃣ Preparar el payload final
      const payload = {
        nombre: form.nombre ?? asignatura.nombre,
        clave: form.clave ?? asignatura.clave,
        tipo: form.tipo ?? asignatura.tipo,
        semestre: form.semestre ?? asignatura.semestre,
        creditos: form.creditos ?? asignatura.creditos,
        horas_teoricas: form.horas_teoricas ?? asignatura.horas_teoricas,
        horas_practicas: form.horas_practicas ?? asignatura.horas_practicas,
      }

      // 2️⃣ Detectar cambios
      const diff = generateDiff(asignatura, payload)

      // 3️⃣ Guardar respaldo si hubo cambios
      if (diff.length > 0) {
        const { error: backupError } = await supabase
          .from("historico_cambios_asignaturas") // 👈 usa el nombre real de tu tabla
          .insert({
            id_asignatura: asignatura.id,
            json_cambios: diff, // jsonb
            user_id: auth.user?.id,
            created_at: new Date().toISOString()
          })
        if (backupError) throw backupError
      }

      // 4️⃣ Actualizar el registro principal
      const { data, error } = await supabase
        .from("asignaturas")
        .update(payload)
        .eq("id", asignatura.id)
        .select()
        .maybeSingle()

      if (error) throw error

      // 5️⃣ Actualizar vista local
      if (data) {
        onUpdate(data as Asignatura)
        setOpen(false)
      }
    } catch (err: any) {
      alert(err.message ?? "Error al guardar")
    } finally {
      setSaving(false)
    }

  }

  return (
    <>
      <Button variant="secondary" size="sm" onClick={openAndFill}>
        <Icons.Pencil className="h-4 w-4 mr-2" /> Editar
      </Button>
      <Dialog open={open} onOpenChange={setOpen}>
        <DialogContent className="max-w-xl">
          <DialogHeader>
            <DialogTitle className="font-mono" >Editar asignatura</DialogTitle>
            <DialogDescription>Actualiza campos básicos.</DialogDescription>
          </DialogHeader>

          <div className="grid gap-3 sm:grid-cols-2">
            <Field label="Nombre">
              <Input value={form.nombre ?? ""} onChange={e => setForm(s => ({ ...s, nombre: e.target.value }))} />
            </Field>
            <Field label="Clave">
              <Input value={form.clave ?? ""} onChange={e => setForm(s => ({ ...s, clave: e.target.value }))} />
            </Field>
            <Field label="Tipo">
              <Select value={form.tipo ?? ""} onValueChange={v => setForm(s => ({ ...s, tipo: v }))}>
                <SelectTrigger className="w-full">
                  <SelectValue placeholder="Selecciona tipo…" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="Obligatoria">
                    <span className={typeStyle("Obligatoria").chip}>Obligatoria</span>
                  </SelectItem>
                  <SelectItem value="Optativa">
                    <span className={typeStyle("Optativa").chip}>Optativa</span>
                  </SelectItem>
                  <SelectItem value="Taller">
                    <span className={typeStyle("Taller").chip}>Taller</span>
                  </SelectItem>
                  <SelectItem value="Laboratorio">
                    <span className={typeStyle("Laboratorio").chip}>Laboratorio</span>
                  </SelectItem>
                  <SelectItem value="Otro">
                    <span className={typeStyle("Otro").chip}>Otro</span>
                  </SelectItem>
                </SelectContent>
              </Select>
            </Field>
            <Field label="Semestre">
              <Input value={String(form.semestre ?? "")} onChange={e => setForm(s => ({ ...s, semestre: Number(e.target.value) || null }))} />
            </Field>
            <Field label="Créditos">
              <Input value={String(form.creditos ?? "")} onChange={e => setForm(s => ({ ...s, creditos: Number(e.target.value) || null }))} />
            </Field>
            <Field label="Horas teóricas">
              <Input value={String(form.horas_teoricas ?? "")} onChange={e => setForm(s => ({ ...s, horas_teoricas: Number(e.target.value) || null }))} />
            </Field>
            <Field label="Horas prácticas">
              <Input value={String(form.horas_practicas ?? "")} onChange={e => setForm(s => ({ ...s, horas_practicas: Number(e.target.value) || null }))} />
            </Field>
          </div>

          <DialogFooter>
            <Button variant="outline" onClick={() => setOpen(false)}>Cancelar</Button>
            <Button onClick={save} disabled={saving}>{saving ? "Guardando…" : "Guardar"}</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  )
}

function MejorarAIButton({ asignaturaId, onApply }: {
  asignaturaId: string; onApply: (a: Asignatura) => void
}) {
  const [open, setOpen] = useState(false)
  const [prompt, setPrompt] = useState("")
  const [insert, setInsert] = useState(true)
  const [loading, setLoading] = useState(false)

  async function apply() {
    setLoading(true)
    try {
      const res = await fetch(`${import.meta.env.VITE_BACK_ORIGIN}/api/mejorar/asignatura`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ asignatura_id: asignaturaId, prompt, insert }),
      })
      if (!res.ok) {
        const txt = await res.text()
        throw new Error(txt || "Error IA")
      }
      const nuevo = await res.json()
      onApply(nuevo as Asignatura)
      confetti({
        particleCount: 120,
        spread: 80,
        origin: { y: 0.6 },
      })
      setOpen(false)
    } catch (e: any) {
      alert(e?.message ?? "Error al mejorar la asignatura")
    } finally {
      setLoading(false)
    }
  }

  return (
    <>
      <Button size="sm" onClick={() => setOpen(true)}>
        <Icons.Sparkles className="h-4 w-4 mr-2" /> Mejorar con IA
      </Button>
      <Dialog open={open} onOpenChange={setOpen}>
        <DialogContent className="max-w-xl">
          <DialogHeader>
            <DialogTitle className="font-mono" >Mejorar asignatura con IA</DialogTitle>
            <DialogDescription>
              Describe el ajuste que deseas (p. ej. “refuerza contenidos prácticos y añade bibliografía reciente”).
            </DialogDescription>
          </DialogHeader>
          <Textarea
            value={prompt}
            onChange={(e) => setPrompt(e.target.value)}
            className="min-h-[140px]"
            placeholder="Escribe tu prompt…"
          />
          <label className="flex items-center gap-2 text-sm">
            <input type="checkbox" checked={insert} onChange={(e) => setInsert(e.target.checked)} />
            Guardar cambios
          </label>
          <DialogFooter>
            <Button variant="outline" onClick={() => setOpen(false)}>Cancelar</Button>
            <Button
              onClick={apply}
              disabled={!prompt.trim() || loading}
              className={
                loading
                  ? "relative overflow-hidden text-white shadow-md"
                  : ""
              }
            >
              {loading ? (
                <span className="relative z-10">Pensando…</span>
              ) : (
                "Aplicar ajuste"
              )}
              {loading && (
                <span className="absolute inset-0 animate-aurora" />
              )}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  )
}

function BorrarAsignaturaButton({ asignatura_id, onDeleted }: { asignatura_id: string; onDeleted?: () => void }) {
  const [confirm, setConfirm] = useState(false)
  const [loading, setLoading] = useState(false)
  const router = useRouter()
  const queryClient = useQueryClient()

  async function handleDelete() {
    setLoading(true)
    try {
      const { error, status, statusText } = await supabase.from("asignaturas").delete().eq("id", asignatura_id)
      console.log({ status, statusText });
      

      if (error) throw error
      setConfirm(false)
      queryClient.invalidateQueries({ queryKey: ["asignaturas"] })
      if (onDeleted) onDeleted()
      router.navigate({ to: "/asignaturas", search: {
        q: "", // Término de búsqueda vacío
        planId: "", // ID del plan (vacío si no aplica)
        carreraId: "", // ID de la carrera (vacío si no aplica)
        facultadId: "", // ID de la facultad (vacío si no aplica)
        f: "", // Filtro vacío
      }})
    } catch (e: any) {
      alert(e?.message || "Error al eliminar la asignatura")
    } finally {
      setLoading(false)
    }
  }

  return confirm ? (
    <div className="flex gap-2">
      <Button variant="outline" onClick={() => setConfirm(false)} disabled={loading}>Cancelar</Button>
      <Button variant="destructive" onClick={handleDelete} disabled={loading}>
        {loading ? "Eliminando…" : "Confirmar eliminación"}
      </Button>
    </div>
  ) : (
    <Button variant="outline" onClick={() => setConfirm(true)}>
      Eliminar asignatura
    </Button>
  )
}

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>
  )
}


type UnitDraft = { title: string; temas: string[] }

export function EditContenidosButton({
  asignaturaId,
  value,
  onSaved,
}: {
  asignaturaId: string
  value: any
  onSaved: (contenidos: any) => void
}) {
  const [open, setOpen] = useState(false)
  const [saving, setSaving] = useState(false)
  const [units, setUnits] = useState<UnitDraft[]>([])
  const [initialUnits, setInitialUnits] = useState<UnitDraft[]>([])
  const auth = useSupabaseAuth() // 👈 para registrar el usuario que edita

  // --- Normaliza entrada flexible a estructura estable
  const normalize = useCallback((v: any): UnitDraft[] => {
    try {
      const entries = Object.entries(v ?? {})
        .sort(([a], [b]) => Number(a) - Number(b))
        .map(([key, val]) => {
          const obj = val as any
          const title =
            typeof obj?.titulo === "string" && obj.titulo.trim()
              ? obj.titulo.trim()
              : `Unidad ${key}`
          let temas: string[] = []
          if (Array.isArray(obj?.subtemas)) temas = obj.subtemas.map(String)
          else if (obj?.subtemas && typeof obj.subtemas === "object") {
            temas = Object.entries(obj.subtemas)
              .sort(([a], [b]) => Number(a) - Number(b))
              .map(([, t]) => String(t))
          } else if (Array.isArray(obj)) {
            temas = obj.map(String)
          } else if (obj && typeof obj === "object") {
            const nums = Object.entries(obj).filter(
              ([k, v]) => /^\d+$/.test(String(k)) && (typeof v === "string" || typeof v === "number"),
            )
            if (nums.length)
              temas = nums.sort(([a], [b]) => Number(a) - Number(b)).map(([, t]) => String(t))
          }
          return { title, temas }
        })
      return entries.length ? entries : [{ title: "", temas: [] }]
    } catch {
      return [{ title: "", temas: [] }]
    }
  }, [])

  // --- Construye payload consistente
  const buildPayload = useCallback((us: UnitDraft[]) => {
    const out: Record<string, any> = {}
    us.forEach((u, idx) => {
      const k = String(idx + 1)
      const sub: Record<string, string> = {}
      u.temas
        .map((t) => t.trim())
        .filter(Boolean)
        .forEach((t, i) => {
          sub[String(i + 1)] = t
        })
      out[k] = { titulo: (u.title || "").trim(), subtemas: sub }
    })
    return out
  }, [])

  // --- Limpia UI
  const cleanUnits = useCallback((us: UnitDraft[]) => {
    return us.map((u) => {
      const seen = new Set<string>()
      const temas = u.temas
        .map((t) => t.trim())
        .filter((t) => {
          if (!t) return false
          const key = t.toLowerCase()
          if (seen.has(key)) return false
          seen.add(key)
          return true
        })
      return { title: (u.title || "").trim(), temas }
    })
  }, [])

  const openEditor = () => {
    const base = normalize(value)
    setUnits(cleanUnits(base))
    setInitialUnits(cleanUnits(base))
    setOpen(true)
  }

  const hasChanges = useMemo(
    () => JSON.stringify(cleanUnits(units)) !== JSON.stringify(cleanUnits(initialUnits)),
    [units, initialUnits, cleanUnits],
  )

  // --- Atajos: Ctrl/Cmd + Enter
  useEffect(() => {
    if (!open) return
    const handler = (e: KeyboardEvent) => {
      const ctrlOrCmd = e.ctrlKey || e.metaKey
      if (ctrlOrCmd && e.key.toLowerCase() === "enter") {
        e.preventDefault()
        void save()
      }
    }
    window.addEventListener("keydown", handler)
    return () => window.removeEventListener("keydown", handler)
  }, [open, units, saving])

  // --- Acciones por unidad
  const removeUnit = (idx: number) => {
    if (!confirm("¿Eliminar esta unidad?")) return
    setUnits((prev) => prev.filter((_, i) => i !== idx))
  }

  const moveUnit = (idx: number, dir: -1 | 1) => {
    setUnits((prev) => {
      const next = [...prev]
      const j = idx + dir
      if (j < 0 || j >= next.length) return prev
      ;[next[idx], next[j]] = [next[j], next[idx]]
      return next
    })
  }

  const duplicateUnit = (idx: number) => {
    setUnits((prev) => {
      const next = [...prev]
      next.splice(idx + 1, 0, {
        title: `${prev[idx].title} (copia)`,
        temas: [...prev[idx].temas],
      })
      return next
    })
  }

  // ✅ Función para guardar con respaldo histórico
  async function save() {
    setSaving(true)
    try {
      const cleaned = cleanUnits(units)
      const contenidos = buildPayload(cleaned)

      // 1️⃣ Generar diff entre valor anterior y nuevo
      const diff = [
        {
          op: "replace",
          path: "/contenidos",
          from: value,
          value: contenidos,
        },
      ]

      // 2️⃣ Guardar respaldo en tabla de histórico (solo si hay cambios)
      if (JSON.stringify(value) !== JSON.stringify(contenidos)) {
        const { error: backupError } = await supabase
          .from("historico_cambios_asignaturas") // 👈 nombre de tu tabla de respaldo
          .insert({
            id_asignatura: asignaturaId,
            json_cambios: diff,
            user_id: auth.user?.id,
            created_at: new Date().toISOString(),
          })
        if (backupError) throw backupError
      }

      // 3️⃣ Actualizar campo contenidos
      const { data, error } = await supabase
        .from("asignaturas")
        .update({ contenidos })
        .eq("id", asignaturaId)
        .select()
        .maybeSingle()

      if (error) throw error

      setInitialUnits(cleaned)
      onSaved((data as any)?.contenidos ?? contenidos)
      setOpen(false)
    } catch (err: any) {
      alert(err.message || "Error al guardar contenidos")
    } finally {
      setSaving(false)
    }
  }

  const cancel = () => {
    if (hasChanges && !confirm("Hay cambios sin guardar. ¿Cerrar de todos modos?")) return
    setOpen(false)
  }

  return (
    <>
      <Button size="sm" variant="outline" onClick={openEditor}>
        <Icons.Pencil className="h-4 w-4 mr-2" /> Editar contenidos
      </Button>

      <Dialog open={open} onOpenChange={(o) => (o ? openEditor() : cancel())}>
        <DialogContent className="max-w-4xl p-0 overflow-hidden">
          {/* Header sticky */}
          <div className="sticky top-0 z-10 border-b bg-background/80 backdrop-blur">
            <DialogHeader className="px-6 pt-5 pb-3">
              <DialogTitle className="flex items-center gap-2">
                <Icons.BookOpen className="h-5 w-5" />
                Editar contenidos
                {hasChanges && (
                  <Badge variant="secondary" className="ml-1">Cambios sin guardar</Badge>
                )}
              </DialogTitle>
              <DialogDescription>
                Títulos de unidad y temas (uno por línea). Se guardará con <code>titulo</code> y <code>subtemas</code>.
              </DialogDescription>
            </DialogHeader>
            <div className="px-6 pb-3 flex items-center justify-between text-xs text-muted-foreground">
              <span>{units.length} unidad(es)</span>
              <span className="inline-flex items-center gap-1">
                <Icons.Keyboard className="h-3 w-3" /> Atajo: <kbd className="px-1 border rounded">Ctrl/⌘</kbd>+<kbd className="px-1 border rounded">Enter</kbd>
              </span>
            </div>
          </div>

          <ScrollArea className="max-h-[65vh] px-6">
            <div className="space-y-4 py-4">
              {units.map((u, i) => (
                <div key={i} className="rounded-2xl border p-4">
                  <div className="flex items-center justify-between mb-3 gap-2">
                    <div className="font-medium text-sm">Unidad {i + 1}</div>
                    <div className="flex items-center gap-1">
                      <Button size="icon" variant="ghost" title="Subir" onClick={() => moveUnit(i, -1)} disabled={i === 0}>
                        <Icons.ArrowUp className="w-4 h-4" />
                      </Button>
                      <Button size="icon" variant="ghost" title="Bajar" onClick={() => moveUnit(i, 1)} disabled={i === units.length - 1}>
                        <Icons.ArrowDown className="w-4 h-4" />
                      </Button>
                      <Button size="icon" variant="ghost" title="Duplicar unidad" onClick={() => duplicateUnit(i)}>
                        <Icons.Copy className="w-4 h-4" />
                      </Button>
                      <Separator orientation="vertical" className="mx-1 h-5" />
                      <Button size="icon" variant="ghost" title="Eliminar unidad" onClick={() => removeUnit(i)}>
                        <Icons.Trash2 className="w-4 h-4" />
                      </Button>
                    </div>
                  </div>

                  <div className="grid md:grid-cols-2 gap-3">
                    <div className="space-y-1">
                      <Label>Título</Label>
                      <Input
                        value={u.title}
                        onChange={(e) =>
                          setUnits((prev) => prev.map((uu, idx) => (idx === i ? { ...uu, title: e.target.value } : uu)))
                        }
                        placeholder={`Unidad ${i + 1}`}
                      />
                    </div>
                    <div className="space-y-1 md:col-span-2">
                      <div className="flex items-center justify-between">
                        <Label>Temas (uno por línea)</Label>
                        <Badge variant="outline">{u.temas.filter((t) => t.trim()).length} tema(s)</Badge>
                      </div>
                      <Textarea
                        className="min-h-[140px]"
                        value={u.temas.join("\n")}
                        onChange={(e) => {
                          const lines = e.target.value.split("\n")
                          setUnits((prev) => prev.map((uu, idx) => (idx === i ? { ...uu, temas: lines } : uu)))
                        }}
                        placeholder={`Tema 1\nTema 2\n…`}
                      />
                    </div>
                  </div>
                </div>
              ))}

              <div className="flex justify-end">
                <Button
                  variant="secondary"
                  onClick={() =>
                    setUnits((prev) => [...prev, { title: "", temas: [] }])
                  }
                >
                  <Icons.Plus className="w-4 h-4 mr-2" /> Agregar unidad
                </Button>
              </div>
            </div>
          </ScrollArea>

          <DialogFooter className="px-6 pb-5">
            <Button variant="outline" onClick={cancel}>Cancelar</Button>
            <Button onClick={save} disabled={saving || !hasChanges || units.some(u => !u.title.trim())}>
              {saving ? (
                <span className="inline-flex items-center gap-2">
                  <Icons.Loader2 className="h-4 w-4 animate-spin" /> Guardando…
                </span>
              ) : (
                "Guardar"
              )}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  )
}