// routes/_authenticated/archivos.tsx
import { createFileRoute, useRouter } from "@tanstack/react-router"
import { useMemo, useState } from "react"
import { supabase } from "@/auth/supabase"
import * as Icons from "lucide-react"
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 { Label } from "@/components/ui/label"
import {
  Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle,
} from "@/components/ui/dialog"
import { Textarea } from "@/components/ui/textarea"
import { Select, SelectTrigger, SelectContent, SelectItem, SelectValue } from "@/components/ui/select"
import { DetailDialog } from "@/components/archivos/DetailDialog"

import type { RefRow } from "@/types/RefRow"

export const Route = createFileRoute("/_authenticated/archivos")({
  component: RouteComponent,
  loader: async () => {
    const { data, error } = await supabase
      .from("fine_tuning_referencias")
      .select("*")
      .order("fecha_subida", { ascending: false })
      .limit(200)
    if (error) throw error
    return (data ?? []) as RefRow[]
  },
})

function chipTint(ok?: boolean | null) {
  return ok
    ? "bg-emerald-50 text-emerald-700 border-emerald-200"
    : "bg-amber-50 text-amber-800 border-amber-200"
}

function RouteComponent() {
  const router = useRouter()
  const rows = Route.useLoaderData() as RefRow[]

  const [q, setQ] = useState("")
  const [estado, setEstado] = useState<"todos" | "proc" | "pend">("todos")
  const [scope, setScope] = useState<"todos" | "internos" | "externos">("todos")

  const [viewing, setViewing] = useState<RefRow | null>(null)
  const [uploadOpen, setUploadOpen] = useState(false)

  const filtered = useMemo(() => {
    const t = q.trim().toLowerCase()
    return rows.filter((r) => {
      if (estado === "proc" && !r.procesado) return false
      if (estado === "pend" && r.procesado) return false
      if (scope === "internos" && !r.interno) return false
      if (scope === "externos" && r.interno) return false

      if (!t) return true
      const hay =
        [r.titulo_archivo, r.descripcion, r.fuente_autoridad, r.tipo_contenido, ...(r.tags ?? [])]
          .filter(Boolean)
          .some((v) => String(v).toLowerCase().includes(t))
      return hay
    })
  }, [rows, q, estado, scope])

  async function remove(id: string) {
    if (!confirm("¿Eliminar archivo de referencia?")) return
    const { error } = await supabase
      .from("fine_tuning_referencias")
      .delete()
      .eq("fine_tuning_referencias_id", id)
    if (error) return alert(error.message)
    router.invalidate()
  }

  return (
    <div className="p-6 space-y-4">
      <Card>
        <CardHeader className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
          <CardTitle className="font-mono">Archivos de referencia</CardTitle>

          <div className="flex w-full flex-col gap-2 sm:w-auto sm:flex-row sm:items-center">
            <div className="relative w-full sm:w-80">
              <Icons.Search className="absolute left-2 top-1/2 -translate-y-1/2 h-4 w-4 text-neutral-400" />
              <Input
                value={q}
                onChange={(e) => setQ(e.target.value)}
                placeholder="Buscar por título, etiqueta, fuente…"
                className="pl-8"
              />
            </div>

            <Select value={estado} onValueChange={(v: any) => setEstado(v)}>
              <SelectTrigger className="sm:w-[160px]">
                <SelectValue placeholder="Estado" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="todos">Todos</SelectItem>
                <SelectItem value="proc">Procesados</SelectItem>
                <SelectItem value="pend">Pendientes</SelectItem>
              </SelectContent>
            </Select>

            <Select value={scope} onValueChange={(v: any) => setScope(v)}>
              <SelectTrigger className="sm:w-[160px]">
                <SelectValue placeholder="Ámbito" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="todos">Todos</SelectItem>
                <SelectItem value="internos">Internos</SelectItem>
                <SelectItem value="externos">Externos</SelectItem>
              </SelectContent>
            </Select>

            <Button onClick={() => setUploadOpen(true)}>
              <Icons.Upload className="w-4 h-4 mr-2" /> Nuevo
            </Button>
          </div>
        </CardHeader>

        <CardContent>
          <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
            {filtered.map((r) => (
              <article
                key={r.fine_tuning_referencias_id}
                className="rounded-2xl border bg-white/70 dark:bg-neutral-900/60 p-4 flex flex-col gap-3"
              >
                <header className="min-w-0">
                  <div className="flex items-center justify-between gap-2">
                    <h3 className="font-semibold truncate">{r.titulo_archivo ?? "(Sin título)"}</h3>
                    <span className={`text-[10px] px-2 py-0.5 rounded-full border ${chipTint(r.procesado)}`}>
                      {r.procesado ? "Procesado" : "Pendiente"}
                    </span>
                  </div>
                  <div className="mt-1 text-xs text-neutral-600 flex flex-wrap gap-2">
                    {r.tipo_contenido && <Badge variant="outline">{r.tipo_contenido}</Badge>}
                    {r.interno != null && (
                      <Badge variant="outline">{r.interno ? "Interno" : "Externo"}</Badge>
                    )}
                    {r.fecha_subida && (
                      <span className="inline-flex items-center gap-1">
                        <Icons.CalendarClock className="w-3 h-3" />
                        {new Date(r.fecha_subida).toLocaleDateString()}
                      </span>
                    )}
                  </div>
                </header>

                {r.descripcion && (
                  <p className="text-sm text-neutral-700 line-clamp-3">{r.descripcion}</p>
                )}

                {r.tags && r.tags.length > 0 && (
                  <div className="flex flex-wrap gap-1.5">
                    {r.tags.map((t, i) => (
                      <span key={i} className="text-[10px] px-2 py-0.5 rounded-full border bg-white/60">
                        #{t}
                      </span>
                    ))}
                  </div>
                )}

                <div className="mt-auto flex items-center justify-between gap-2">
                  <Button variant="ghost" size="sm" onClick={() => setViewing(r)}>
                    <Icons.Eye className="w-4 h-4 mr-1" /> Ver
                  </Button>
                  <Button variant="ghost" size="sm" onClick={() => remove(r.fine_tuning_referencias_id)}>
                    <Icons.Trash2 className="w-4 h-4 mr-1" /> Eliminar
                  </Button>
                </div>
              </article>
            ))}
          </div>

          {!filtered.length && (
            <div className="text-center text-sm text-neutral-500 py-10">No hay archivos</div>
          )}
        </CardContent>
      </Card>

      {/* Detalle */}
      <DetailDialog row={viewing} onClose={() => setViewing(null)} />

      {/* Subida */}
      <UploadDialog open={uploadOpen} onOpenChange={setUploadOpen} onDone={() => router.invalidate()} />
    </div>
  )
}

/* ========= Subida ========= */
function UploadDialog({
  open, onOpenChange, onDone,
}: { open: boolean; onOpenChange: (o: boolean) => void; onDone: () => void }) {
  const [file, setFile] = useState<File | null>(null)
  const [instrucciones, setInstrucciones] = useState("")
  const [tags, setTags] = useState("")
  const [interno, setInterno] = useState(true)
  const [fuente, setFuente] = useState("")
  const [subiendo, setSubiendo] = useState(false)

  async function toBase64(f: File): Promise<string> {
    const buf = await f.arrayBuffer()
    const bytes = new Uint8Array(buf)
    let binary = ""
    for (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i])
    return btoa(binary)
  }

  async function upload() {
    if (!file) { alert("Selecciona un archivo"); return }
    if (!instrucciones.trim()) { alert("Escribe las instrucciones"); return }

    setSubiendo(true)
    try {
      const fileBase64 = await toBase64(file)
      // Enviamos al motor (inserta en la tabla si insert=true)
      const res = await fetch(`${import.meta.env.VITE_BACK_ORIGIN}/api/upload/documento`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          prompt: instrucciones,
          fileBase64,
          insert: true,
        }),
      })
      if (!res.ok) {
        const txt = await res.text()
        throw new Error(txt || "Error al subir")
      }
      // Ajustes extra (tags, interno, fuente) si el motor no los llenó
      // Intentamos leer el id que regrese el servicio; si no, solo invalidamos.
      let createdId: string | null = null
      try {
        const payload = await res.json()
        createdId =
          payload?.fine_tuning_referencias_id ||
          payload?.id ||
          payload?.data?.fine_tuning_referencias_id ||
          null
      } catch { /* noop */ }

      if (createdId && (tags.trim() || fuente.trim() || typeof interno === "boolean")) {
        await supabase
          .from("fine_tuning_referencias")
          .update({
            tags: tags.trim() ? tags.split(",").map((s) => s.trim()).filter(Boolean) : undefined,
            fuente_autoridad: fuente.trim() || undefined,
            interno,
          })
          .eq("fine_tuning_referencias_id", createdId)
      }

      onOpenChange(false)
      onDone()
    } catch (e: any) {
      alert(e?.message ?? "Error al subir el documento")
    } finally {
      setSubiendo(false)
    }
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-xl">
        <DialogHeader>
          <DialogTitle className="font-mono" >Nuevo archivo de referencia</DialogTitle>
          <DialogDescription>
            Sube un documento y escribe instrucciones para su procesamiento. Se guardará en la base y se marcará como
            <em> procesado </em> cuando termine el flujo.
          </DialogDescription>
        </DialogHeader>

        <div className="grid gap-3">
          <div className="space-y-1">
            <Label>Archivo</Label>
            <Input type="file" accept=".pdf,.doc,.docx,.txt,.md" onChange={(e) => setFile(e.target.files?.[0] ?? null)} />
            {file && (
              <div className="text-xs text-neutral-600">{file.name} · {(file.size / 1024).toFixed(1)} KB</div>
            )}
          </div>

          <div className="space-y-1">
            <Label>Instrucciones</Label>
            <Textarea
              value={instrucciones}
              onChange={(e) => setInstrucciones(e.target.value)}
              placeholder="Ej.: Extrae temario, resultados de aprendizaje y bibliografía; limpia ruido y normaliza formato."
              className="min-h-[120px]"
            />
          </div>

          <div className="grid sm:grid-cols-2 gap-3">
            <div className="space-y-1">
              <Label>Tags (separados por coma)</Label>
              <Input value={tags} onChange={(e) => setTags(e.target.value)} placeholder="normatividad, plan, lineamientos" />
            </div>
            <div className="space-y-1">
              <Label>Fuente de autoridad</Label>
              <Input value={fuente} onChange={(e) => setFuente(e.target.value)} placeholder="SEP, ANUIES…" />
            </div>
          </div>

          <div className="space-y-1">
            <Label>Ámbito</Label>
            <Select value={String(interno)} onValueChange={(v) => setInterno(v === "true")}>
              <SelectTrigger><SelectValue /></SelectTrigger>
              <SelectContent>
                <SelectItem value="true">Interno</SelectItem>
                <SelectItem value="false">Externo</SelectItem>
              </SelectContent>
            </Select>
          </div>
        </div>

        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange(false)}>Cancelar</Button>
          <Button onClick={upload} disabled={subiendo || !file || !instrucciones.trim()}>
            {subiendo ? "Subiendo…" : "Subir"}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  )
}
