"use client"

import { useEffect, useMemo, useState } from "react"
import { useRouter } from "next/navigation"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Badge } from "@/components/ui/badge"
import { toast } from "@/hooks/use-toast"
import { useAuthStore } from "@/lib/auth-store"
import { hasPermission } from "@/lib/permissions"
import { AdminProtected } from "@/components/admin-protected"
import { ArrowLeft, Loader2, Plug, Printer, RefreshCw, Save, Search } from "lucide-react"

/**
 * Integración INVU POS — estado de conexión y mapeo de productos.
 *
 * El mapeo traduce cada producto nuestro al código del catálogo INVU
 * (MEN-###). El precio real siempre sale de la venta; acá solo se decide QUÉ
 * código lleva. Los productos sin mapeo caen al genérico de su categoría.
 * Fuente de verdad de la integración: documentacion/PLAN-INVU.md.
 */

interface Mapping {
  id: string
  productType: "PRODUCT" | "DELIVERY" | "TIP" | "GENERIC_CATEGORY"
  reference: string
  name: string
  invuCode: string
  invuItemName: string
  invuTaxRate: number
  locationId: string | null
  isActive: boolean
}

interface TestResult {
  ok: boolean
  sede: string
  enabled?: boolean
  configCompleta?: boolean
  catalogoItems?: number
  cuotaRestante?: { perSecond: number | null; perMinute: number | null; perDay: number | null } | null
  error?: string
}

/**
 * Hallazgo de la auditoría de ruteo: producto que se puede vender pero no llega
 * a la estación que debería. El caso grave es el silencioso — INVU acepta la
 * orden y responde `ok`, pero nadie prepara el plato.
 */
interface HallazgoRuteo {
  motivo: "SIN_ESTACION" | "CODIGO_INEXISTENTE" | "SOLO_FUERA_DEL_RESTAURANTE" | "PROMOCION_SIN_COCINA"
  severidad: "ALTA" | "MEDIA"
  invuCode: string
  nombreWeb: string
  nombreInvu: string | null
  subcategoria: string | null
  disponibleEnLaWeb: boolean
  detalle: string
}

interface ResultadoAuditoria {
  ok: boolean
  motivo?: string
  mapeosRevisados: number
  categoriasActualizadas: number
  hallazgos: HallazgoRuteo[]
  resumen: string
  tablaDeImpresorasRevisadaEl?: string
}

const TIPO_LABEL: Record<Mapping["productType"], string> = {
  PRODUCT: "Producto",
  GENERIC_CATEGORY: "Genérico de categoría",
  DELIVERY: "Envío",
  TIP: "Propina",
}

function FilaMapeo({ mapping, onSaved }: { mapping: Mapping; onSaved: () => void }) {
  const [invuCode, setInvuCode] = useState(mapping.invuCode)
  const [saving, setSaving] = useState(false)

  const guardar = async () => {
    setSaving(true)
    try {
      const res = await fetch(`/api/invu/mappings/${mapping.id}`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ invuCode }),
      })
      if (!res.ok) throw new Error((await res.json()).error || "Error")
      toast({ title: "Mapeo guardado", description: `${mapping.name} → ${invuCode}` })
      onSaved()
    } catch (e: any) {
      toast({ title: "No se pudo guardar", description: String(e?.message ?? e), variant: "destructive" })
    } finally {
      setSaving(false)
    }
  }

  const toggle = async () => {
    try {
      const res = await fetch(`/api/invu/mappings/${mapping.id}`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ isActive: !mapping.isActive }),
      })
      if (!res.ok) throw new Error((await res.json()).error || "Error")
      onSaved()
    } catch (e: any) {
      toast({ title: "No se pudo cambiar", description: String(e?.message ?? e), variant: "destructive" })
    }
  }

  return (
    <div className="flex flex-col sm:flex-row sm:items-center gap-2 py-2 border-b last:border-0">
      <div className="flex-1 min-w-0">
        <p className={`text-sm font-medium truncate ${mapping.isActive ? "" : "line-through opacity-50"}`}>
          {mapping.name}
        </p>
        <p className="text-xs text-muted-foreground truncate">
          {TIPO_LABEL[mapping.productType]} · {mapping.invuItemName || "sin item INVU"}
        </p>
      </div>
      <div className="flex items-center gap-2">
        <Input
          value={invuCode}
          onChange={(e) => setInvuCode(e.target.value)}
          placeholder="MEN-000"
          className="w-28 h-8 text-sm font-mono"
        />
        <Button size="sm" variant="outline" onClick={guardar} disabled={saving || invuCode === mapping.invuCode}>
          {saving ? <Loader2 className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />}
        </Button>
        <Button size="sm" variant="ghost" onClick={toggle}>
          <Badge variant={mapping.isActive ? "default" : "secondary"}>
            {mapping.isActive ? "Activo" : "Inactivo"}
          </Badge>
        </Button>
      </div>
    </div>
  )
}

export default function InvuPage() {
  const router = useRouter()
  const { user } = useAuthStore()
  const puedeEditar = user?.role && hasPermission(user.role, "settings.update")

  const [mappings, setMappings] = useState<Mapping[]>([])
  const [loading, setLoading] = useState(true)
  const [q, setQ] = useState("")
  const [test, setTest] = useState<TestResult | null>(null)
  const [testing, setTesting] = useState(false)

  const cargar = async () => {
    try {
      const res = await fetch("/api/invu/mappings")
      if (res.ok) setMappings(await res.json())
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    cargar()
  }, [])

  const [syncing, setSyncing] = useState(false)

  const sincronizarPrecios = async () => {
    setSyncing(true)
    try {
      const res = await fetch("/api/invu/sync-prices?sede=sport-bar", { method: "POST" })
      const data = await res.json()
      if (data.ok) {
        toast({
          title: `Precios sincronizados (${data.cambiados} cambios)`,
          description:
            data.cambiados > 0
              ? data.cambios.map((c: any) => `${c.producto}: $${c.antes}→$${c.ahora}`).slice(0, 5).join(" · ")
              : "La web ya estaba al día con INVU.",
        })
      } else {
        toast({ title: "No se pudo sincronizar", description: data.motivo, variant: "destructive" })
      }
    } catch (e: any) {
      toast({ title: "Error de red", description: String(e?.message ?? e), variant: "destructive" })
    } finally {
      setSyncing(false)
    }
  }

  const [auditoria, setAuditoria] = useState<ResultadoAuditoria | null>(null)
  const [auditando, setAuditando] = useState(false)

  const revisarRuteo = async () => {
    setAuditando(true)
    try {
      const res = await fetch("/api/invu/auditar-ruteo?sede=sport-bar")
      const data: ResultadoAuditoria = await res.json()
      setAuditoria(data)
      if (!data.ok) {
        toast({ title: "No se pudo revisar el ruteo", description: data.motivo, variant: "destructive" })
      }
    } catch (e: any) {
      toast({ title: "Error de red", description: String(e?.message ?? e), variant: "destructive" })
    } finally {
      setAuditando(false)
    }
  }

  const probarConexion = async () => {
    setTesting(true)
    setTest(null)
    try {
      const res = await fetch("/api/invu/test?sede=sport-bar")
      setTest(await res.json())
    } catch {
      setTest({ ok: false, sede: "sport-bar", error: "No se pudo consultar" })
    } finally {
      setTesting(false)
    }
  }

  const filtrados = useMemo(() => {
    const texto = q.trim().toLowerCase()
    if (!texto) return mappings
    return mappings.filter(
      (m) =>
        m.name.toLowerCase().includes(texto) ||
        m.invuCode.toLowerCase().includes(texto) ||
        m.invuItemName.toLowerCase().includes(texto)
    )
  }, [mappings, q])

  const resumen = useMemo(() => {
    const activos = mappings.filter((m) => m.isActive)
    return {
      total: activos.length,
      sinCodigo: activos.filter((m) => !m.invuCode).length,
      genericos: activos.filter((m) => m.productType === "GENERIC_CATEGORY").length,
    }
  }, [mappings])

  return (
    <AdminProtected>
      <div className="max-w-4xl mx-auto p-4 sm:p-6 space-y-6">
        <div className="flex items-center gap-3">
          <Button variant="ghost" size="icon" onClick={() => router.push("/admin/dashboard")}>
            <ArrowLeft className="h-5 w-5" />
          </Button>
          <div>
            <h1 className="text-2xl font-bold flex items-center gap-2">
              <Plug className="h-6 w-6 text-naranja-vip" />
              INVU POS
            </h1>
            <p className="text-sm text-muted-foreground">
              Mapeo de productos y estado de la conexión con el punto de venta
            </p>
          </div>
        </div>

        {!puedeEditar ? (
          <Card>
            <CardContent className="py-10 text-center text-muted-foreground">
              No tienes permisos para gestionar la integración INVU.
            </CardContent>
          </Card>
        ) : (
          <>
            <Card>
              <CardHeader className="flex flex-row items-center justify-between space-y-0">
                <CardTitle className="text-lg">Conexión (Sport Bar)</CardTitle>
                <div className="flex gap-2">
                  <Button size="sm" variant="outline" onClick={sincronizarPrecios} disabled={syncing}>
                    {syncing ? <Loader2 className="h-4 w-4 animate-spin mr-1" /> : <RefreshCw className="h-4 w-4 mr-1" />}
                    Sincronizar precios
                  </Button>
                  <Button size="sm" variant="outline" onClick={probarConexion} disabled={testing}>
                    {testing ? <Loader2 className="h-4 w-4 animate-spin mr-1" /> : <RefreshCw className="h-4 w-4 mr-1" />}
                    Probar conexión
                  </Button>
                </div>
              </CardHeader>
              <CardContent className="text-sm space-y-1">
                {!test && !testing && (
                  <p className="text-muted-foreground">
                    El smoke test gasta cuota de la API (~2.000 requests/día): usarlo solo cuando haga falta.
                  </p>
                )}
                {test && test.ok && (
                  <div className="space-y-1">
                    <p>
                      <Badge>Conectado</Badge> Catálogo INVU: <strong>{test.catalogoItems}</strong> items
                    </p>
                    <p>
                      Integración: {test.enabled ? <Badge>ENCENDIDA</Badge> : <Badge variant="secondary">apagada (kill-switch)</Badge>}{" "}
                      · Config del tenant: {test.configCompleta ? "completa" : <span className="text-destructive">falta invu_config_sport-bar</span>}
                    </p>
                    {test.cuotaRestante && (
                      <p className="text-muted-foreground">
                        Cuota restante — min: {test.cuotaRestante.perMinute ?? "?"} · día: {test.cuotaRestante.perDay ?? "?"}
                      </p>
                    )}
                  </div>
                )}
                {test && !test.ok && (
                  <p className="text-destructive">
                    <Badge variant="destructive">Error</Badge> {test.error}
                  </p>
                )}
              </CardContent>
            </Card>

            <Card>
              <CardHeader className="flex flex-row items-center justify-between space-y-0">
                <CardTitle className="text-lg">¿Todo llega a cocina o a la barra?</CardTitle>
                <Button size="sm" variant="outline" onClick={revisarRuteo} disabled={auditando}>
                  {auditando ? <Loader2 className="h-4 w-4 animate-spin mr-1" /> : <Printer className="h-4 w-4 mr-1" />}
                  Revisar ruteo
                </Button>
              </CardHeader>
              <CardContent className="text-sm space-y-3">
                {!auditoria && !auditando && (
                  <p className="text-muted-foreground">
                    INVU decide a qué impresora va cada plato según la categoría que tenga en su
                    catálogo. Si una categoría no tiene impresora asignada,{" "}
                    <strong>la orden se cobra y nadie la prepara</strong>: INVU responde «ok» igual, así
                    que el fallo no se nota. Esta revisión lo busca antes de que pase.
                  </p>
                )}
                {auditoria?.ok && (
                  <>
                    <p className="text-muted-foreground">
                      {auditoria.mapeosRevisados} mapeos revisados
                      {auditoria.tablaDeImpresorasRevisadaEl
                        ? ` · tabla de impresoras mirada por última vez el ${auditoria.tablaDeImpresorasRevisadaEl}`
                        : ""}
                    </p>
                    {auditoria.hallazgos.length === 0 ? (
                      <p>
                        <Badge>Todo bien</Badge> Todo lo que se vende imprime en alguna estación.
                      </p>
                    ) : (
                      <div className="space-y-2">
                        {auditoria.hallazgos.map((h, i) => (
                          <div
                            key={`${h.invuCode}-${i}`}
                            className="rounded-md border p-2 space-y-1"
                          >
                            <div className="flex flex-wrap items-center gap-2">
                              <Badge variant={h.severidad === "ALTA" ? "destructive" : "secondary"}>
                                {h.severidad === "ALTA" ? "Se puede pedir hoy" : "Apagado en la web"}
                              </Badge>
                              <span className="font-medium">{h.nombreWeb}</span>
                              <span className="text-muted-foreground">{h.invuCode}</span>
                              {h.subcategoria && (
                                <span className="text-muted-foreground">· {h.subcategoria}</span>
                              )}
                            </div>
                            <p className="text-muted-foreground">{h.detalle}</p>
                          </div>
                        ))}
                        <p className="text-muted-foreground">
                          Esto se arregla en el catálogo de INVU (asignándole una impresora a esa
                          categoría), no acá.
                        </p>
                      </div>
                    )}
                  </>
                )}
                {auditoria && !auditoria.ok && (
                  <p className="text-destructive">
                    <Badge variant="destructive">Error</Badge> {auditoria.motivo}
                  </p>
                )}
              </CardContent>
            </Card>

            <Card>
              <CardHeader>
                <CardTitle className="text-lg">
                  Mapeos ({resumen.total} activos · {resumen.sinCodigo} sin código · {resumen.genericos} genéricos)
                </CardTitle>
                <div className="relative">
                  <Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
                  <Input
                    value={q}
                    onChange={(e) => setQ(e.target.value)}
                    placeholder="Buscar por producto o código INVU…"
                    className="pl-8"
                  />
                </div>
              </CardHeader>
              <CardContent>
                {loading ? (
                  <div className="py-10 text-center">
                    <Loader2 className="h-6 w-6 animate-spin mx-auto" />
                  </div>
                ) : filtrados.length === 0 ? (
                  <p className="py-6 text-center text-muted-foreground text-sm">
                    Sin mapeos. Se cargan con <code>npx tsx scripts/seed-invu-mappings.ts</code>.
                  </p>
                ) : (
                  filtrados.map((m) => <FilaMapeo key={m.id} mapping={m} onSaved={cargar} />)
                )}
              </CardContent>
            </Card>
          </>
        )}
      </div>
    </AdminProtected>
  )
}
