"use client";

import { useEffect, useRef, useState, type ChangeEvent } from "react";
import PageLayout from "@/components/layout/PageLayout";
import Card from "@/components/ui/Card";
import Input from "@/components/ui/Input";
import Button from "@/components/ui/Button";

type Guia = {
  id?: string | number;
  estado?: string;
  numero?: string;
  numero_guia?: string;
  foto_entrega?: string;
  [key: string]: any;
};

type UsuarioSesion = {
  usuario?: string;
  tipo?: "admin" | "usuario" | "entregas";
  nombre?: string;
  accesoCompleto?: boolean;
};

const ESTADOS = [
  "EN_BODEGA",
  "EN_CONTENEDOR",
  "LLEGO_HONDURAS",
  "EN_RUTA",
  "ENTREGADA",
] as const;

const LABELS_ESTADO: Record<string, string> = {
  EN_BODEGA: "En bodega",
  EN_CONTENEDOR: "En contenedor",
  LLEGO_HONDURAS: "Llegó a Honduras",
  EN_RUTA: "En ruta",
  ENTREGADA: "Entregada",
};

function normalizarEstado(valor?: string) {
  return String(valor || "")
    .trim()
    .toUpperCase()
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .replace(/\s+/g, "_")
    .replace(/-/g, "_");
}

function estadoCanonico(valor?: string) {
  const n = normalizarEstado(valor);

  if (n === "EN_BODEGA") return "EN_BODEGA";
  if (n === "EN_CONTENEDOR") return "EN_CONTENEDOR";
  if (n === "LLEGO_HONDURAS" || n === "LLEGO_A_HONDURAS") return "LLEGO_HONDURAS";
  if (n === "EN_RUTA") return "EN_RUTA";
  if (n === "ENTREGADA") return "ENTREGADA";

  return null;
}

function labelEstado(valor?: string) {
  const canonico = estadoCanonico(valor);
  return canonico ? LABELS_ESTADO[canonico] : valor || "Sin estado";
}

function obtenerSiguienteEstado(estadoActual?: string) {
  const canonico = estadoCanonico(estadoActual);

  if (!canonico) return "EN_BODEGA";

  const indice = ESTADOS.indexOf(canonico as (typeof ESTADOS)[number]);
  if (indice < 0 || indice >= ESTADOS.length - 1) return null;

  return ESTADOS[indice + 1];
}

function normalizarCodigo(valor: string) {
  let texto = String(valor || "").trim();
  if (!texto) return "";

  const coincidenciaParametro = texto.match(
    /[?&](?:guia|numero_guia|codigo|code)=([^&#]+)/i
  );

  if (coincidenciaParametro?.[1]) {
    try {
      const extraido = decodeURIComponent(coincidenciaParametro[1])
        .trim()
        .toUpperCase()
        .replace(/\s+/g, "");
      if (extraido) return extraido;
    } catch {}
  }

  const codigoHce = texto.match(/HCE\d+/i);
  if (codigoHce?.[0]) return codigoHce[0].toUpperCase();

  return texto.toUpperCase().replace(/\s+/g, "");
}

export default function EscaneoPage() {
  const [codigo, setCodigo] = useState("");
  const [mensaje, setMensaje] = useState("");
  const [camaraActiva, setCamaraActiva] = useState(false);
  const [cargandoCamara, setCargandoCamara] = useState(false);
  const [buscando, setBuscando] = useState(false);
  const [actualizando, setActualizando] = useState(false);
  const [guiaEncontrada, setGuiaEncontrada] = useState<Guia | null>(null);
  const [usuario, setUsuario] = useState<UsuarioSesion | null>(null);
  const [sesionCargada, setSesionCargada] = useState(false);

  const [fotoEntrega, setFotoEntrega] = useState<File | null>(null);
  const [vistaPreviaFoto, setVistaPreviaFoto] = useState("");

  const scannerRef = useRef<any>(null);
  const scannerActivoRef = useRef(false);
  const buscandoRef = useRef(false);
  const inputFotoRef = useRef<HTMLInputElement | null>(null);

  useEffect(() => {
    try {
      const posiblesSesiones = [
        "dg_cargo_usuario_sesion",
        "usuario_sesion",
        "hce_usuario_sesion",
        "cargo_usuario_sesion",
      ];

      let sesionEncontrada: string | null = null;

      for (const clave of posiblesSesiones) {
        const valor = localStorage.getItem(clave);
        if (valor) {
          sesionEncontrada = valor;
          break;
        }
      }

      if (sesionEncontrada) {
        const usuarioParseado = JSON.parse(sesionEncontrada);
        console.log("USUARIO CARGADO:", usuarioParseado);
        setUsuario(usuarioParseado);
      }
    } catch (error) {
      console.error("ERROR CARGANDO SESIÓN:", error);
    } finally {
      setSesionCargada(true);
    }
  }, []);

  useEffect(() => {
    return () => {
      if (vistaPreviaFoto) {
        URL.revokeObjectURL(vistaPreviaFoto);
      }
    };
  }, [vistaPreviaFoto]);

  async function cerrarSesion() {
    try {
      await fetch("/cargoerp/api/logout", { method: "POST", credentials: "include" });
    } catch (error) {
      console.error("ERROR CERRANDO SESIÓN:", error);
    }

    const claves = [
      "dg_cargo_usuario_sesion",
      "usuario_sesion",
      "hce_usuario_sesion",
      "cargo_usuario_sesion",
      "dg_cargo_usuario",
      "dg_cargo_password",
      "usuario",
      "password",
    ];

    claves.forEach((clave) => localStorage.removeItem(clave));
    window.location.href = "/cargoerp/login";
  }

  async function detenerCamara() {
    scannerActivoRef.current = false;
    const scanner = scannerRef.current;

    if (scanner) {
      try {
        await scanner.stop();
      } catch (error) {}
      try {
        await scanner.clear();
      } catch (error) {}
      scannerRef.current = null;
    }

    setCamaraActiva(false);
  }

  function seleccionarFoto(event: ChangeEvent<HTMLInputElement>) {
    const archivo = event.target.files?.[0];
    if (!archivo) return;

    if (!archivo.type.startsWith("image/")) {
      setMensaje("❌ Debes seleccionar una imagen.");
      return;
    }

    if (archivo.size > 10 * 1024 * 1024) {
      setMensaje("❌ La imagen es demasiado grande. Máximo 10 MB.");
      return;
    }

    if (vistaPreviaFoto) {
      URL.revokeObjectURL(vistaPreviaFoto);
    }

    const url = URL.createObjectURL(archivo);
    setFotoEntrega(archivo);
    setVistaPreviaFoto(url);
    setMensaje("📸 Foto de entrega lista.");
  }

  function tomarFotoEntrega() {
    if (!inputFotoRef.current) return;
    inputFotoRef.current.click();
  }

  async function buscarGuia(codigoBuscar?: string) {
    const codigoFinal = normalizarCodigo(codigoBuscar || codigo);

    if (!codigoFinal) {
      setMensaje("⚠️ Ingresa o escanea un código primero.");
      return;
    }

    if (buscandoRef.current) return;

    try {
      buscandoRef.current = true;
      setBuscando(true);
      setGuiaEncontrada(null);
      setFotoEntrega(null);

      if (vistaPreviaFoto) {
        URL.revokeObjectURL(vistaPreviaFoto);
      }
      setVistaPreviaFoto("");
      setMensaje(`🔎 Buscando guía: ${codigoFinal}`);

      const respuesta = await fetch(
        `/cargoerp/api/guias/buscar?codigo=${encodeURIComponent(codigoFinal)}`,
        { method: "GET", cache: "no-store", credentials: "include" }
      );

      let resultado: any | null = null;
      try {
        resultado = await respuesta.json();
      } catch (error) {
        resultado = null;
      }

      if (!respuesta.ok) {
        setMensaje(`❌ ${resultado?.error || "No se pudo buscar la guía."}`);
        return;
      }

      if (!resultado || !resultado.encontrada || !resultado.guia) {
        setMensaje(`❌ No se encontró ninguna guía con el código: ${codigoFinal}`);
        return;
      }

      setGuiaEncontrada({ ...resultado.guia });

      setMensaje("✅ Guía encontrada correctamente.");
    } catch (error) {
      console.error("ERROR BUSCANDO GUÍA:", error);
      setMensaje("❌ Ocurrió un error al buscar la guía.");
    } finally {
      buscandoRef.current = false;
      setBuscando(false);
    }
  }

  async function subirFotoEntrega() {
    if (!fotoEntrega || !guiaEncontrada?.id) return null;

    const formData = new FormData();
    formData.append("foto", fotoEntrega);
    formData.append("guiaId", String(guiaEncontrada.id));

    const respuesta = await fetch("/cargoerp/api/foto-entrega", {
      method: "POST",
      body: formData,
      credentials: "include",
    });

    let resultado: any | null = null;
    try {
      resultado = await respuesta.json();
    } catch (error) {}

    if (!respuesta.ok || !resultado?.success) {
      throw new Error(resultado?.error || "No se pudo guardar la foto de entrega.");
    }

    return resultado;
  }

  async function actualizarEstado() {
    if (!guiaEncontrada) return;
    if (guiaEncontrada.id === undefined || guiaEncontrada.id === null) {
      setMensaje("❌ No se encontró el ID de la guía.");
      return;
    }

    const siguienteEstado = obtenerSiguienteEstado(guiaEncontrada.estado);
    if (!siguienteEstado) {
      setMensaje("ℹ️ Esta guía ya fue entregada.");
      return;
    }

    const esEntregasLocal = usuario?.tipo === "entregas";
    const esEntregaFinalLocal = siguienteEstado.trim().toLowerCase() === "entregada";

    if (esEntregasLocal && esEntregaFinalLocal && !fotoEntrega) {
      setMensaje("📸 Debes tomar una foto de la entrega antes de marcar la guía como entregada.");
      return;
    }

    try {
      setActualizando(true);
      let fotoGuardadaUrl = "";

      if (esEntregasLocal && esEntregaFinalLocal && fotoEntrega) {
        setMensaje("📤 Guardando evidencia de entrega...");
        const fotoGuardada = await subirFotoEntrega();
        fotoGuardadaUrl = fotoGuardada?.fotoUrl || "";

        if (!fotoGuardadaUrl) {
          setMensaje("❌ No se pudo guardar la evidencia. No se actualizará el estado.");
          return;
        }

        setGuiaEncontrada((actual) =>
          actual ? { ...actual, foto_entrega: fotoGuardadaUrl } : actual
        );
      }

      setMensaje("⏳ Actualizando estado...");

      const respuesta = await fetch("/cargoerp/api/actualizar-estado", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        credentials: "include",
        body: JSON.stringify({
          id: guiaEncontrada.id,
          estado: siguienteEstado,
          fotoUrl: fotoGuardadaUrl || guiaEncontrada.foto_entrega || "",
        }),
      });

      const resultado = await respuesta.json();

      if (!respuesta.ok || !resultado?.success) {
        setMensaje(`❌ ${resultado?.error || "No se pudo actualizar la guía."}`);
        return;
      }

      setGuiaEncontrada(resultado.guia);
      setMensaje(`✅ Guía actualizada a: ${resultado.guia.estado}`);
    } catch (error: any) {
      console.error("ERROR ACTUALIZANDO ESTADO:", error);
      setMensaje(`❌ ${error?.message || "Ocurrió un error al actualizar la guía."}`);
    } finally {
      setActualizando(false);
    }
  }

  async function iniciarCamara() {
    if (cargandoCamara || camaraActiva) return;

    try {
      setMensaje("");
      setGuiaEncontrada(null);
      setCargandoCamara(true);

      if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
        setMensaje("❌ Tu navegador no permite acceder a la cámara.");
        return;
      }

      await detenerCamara();

      const stream = await navigator.mediaDevices.getUserMedia({
        video: { facingMode: { ideal: "environment" } },
        audio: false,
      });

      stream.getTracks().forEach((track) => track.stop());

      const { Html5Qrcode, Html5QrcodeSupportedFormats } = await import("html5-qrcode");

      const scanner = new Html5Qrcode("reader", {
        formatsToSupport: [
          Html5QrcodeSupportedFormats.QR_CODE,
          Html5QrcodeSupportedFormats.CODE_128,
          Html5QrcodeSupportedFormats.CODE_39,
          Html5QrcodeSupportedFormats.EAN_13,
          Html5QrcodeSupportedFormats.EAN_8,
          Html5QrcodeSupportedFormats.UPC_A,
          Html5QrcodeSupportedFormats.UPC_E,
        ],
        verbose: false,
      });

      scannerRef.current = scanner;

      const cameras = await Html5Qrcode.getCameras();
      if (!cameras || cameras.length === 0) {
        setMensaje("❌ No se encontró ninguna cámara.");
        return;
      }

      let cameraId = cameras[0].id;
      const camaraTrasera = cameras.find((camera) => {
        const nombre = camera.label?.toLowerCase() || "";
        return (
          nombre.includes("back") ||
          nombre.includes("rear") ||
          nombre.includes("environment") ||
          nombre.includes("trasera")
        );
      });

      if (camaraTrasera) cameraId = camaraTrasera.id;

      scannerActivoRef.current = true;

      await scanner.start(
        cameraId,
        { fps: 10, qrbox: { width: 300, height: 200 }, aspectRatio: 1.7778 },
        async (decodedText: string) => {
          if (!scannerActivoRef.current || buscandoRef.current) return;

          const codigoDetectado = normalizarCodigo(decodedText);
          if (!codigoDetectado) return;

          scannerActivoRef.current = false;
          setCodigo(codigoDetectado);
          await detenerCamara();
          await buscarGuia(codigoDetectado);
        },
        () => {}
      );

      setCamaraActiva(true);
      setMensaje("📷 Cámara activada. Apunta al código de barras o QR.");
    } catch (error) {
      console.error("ERROR COMPLETO DE CÁMARA:", error);
      scannerActivoRef.current = false;
      setCamaraActiva(false);
      setMensaje("❌ No se pudo activar la cámara. Revisa los permisos.");
    } finally {
      setCargandoCamara(false);
    }
  }

  async function buscarCodigo() {
    await buscarGuia(codigo);
  }

  async function nuevoEscaneo() {
    await detenerCamara();
    setCodigo("");
    setMensaje("");
    setGuiaEncontrada(null);
    setFotoEntrega(null);
    if (vistaPreviaFoto) URL.revokeObjectURL(vistaPreviaFoto);
    setVistaPreviaFoto("");
  }

  useEffect(() => {
    return () => {
      scannerActivoRef.current = false;
      const scanner = scannerRef.current;
      if (scanner) {
        scanner.stop().catch(() => {});
        scanner.clear().catch(() => {});
      }
    };
  }, []);

  const siguienteEstado = guiaEncontrada ? obtenerSiguienteEstado(guiaEncontrada.estado) : null;
  const esEntregas = usuario?.tipo === "entregas";
  const esEntregaFinal = siguienteEstado?.trim().toLowerCase() === "entregada";

  if (!sesionCargada) {
    return (
      <PageLayout>
        <div className="flex min-h-[200px] items-center justify-center text-sm text-[var(--text-muted)]">
          Cargando...
        </div>
      </PageLayout>
    );
  }

  return (
    <PageLayout>
      <input
        ref={inputFotoRef}
        type="file"
        accept="image/*"
        capture="environment"
        onChange={seleccionarFoto}
        className="hidden"
      />

      {esEntregas ? (
        <Button variant="danger" size="sm" onClick={cerrarSesion} className="mb-4">
          Cerrar sesión
        </Button>
      ) : null}

      {/* Encabezado */}
      <section className="mb-4 text-center lg:mb-5">
        <div className="text-3xl">📦</div>
        <h1 className="mt-2 text-xl font-black text-[var(--text-primary)] lg:text-2xl">
          Escanear Guía
        </h1>
        <p className="mt-0.5 text-xs text-[var(--text-muted)]">
          Escanea el código de barras o QR de la etiqueta
        </p>
      </section>

      {/* Cámara */}
      <Card className="mx-auto max-w-2xl overflow-hidden p-0" padding="none">
        <div id="reader" className="min-h-[260px] w-full bg-black" />

        {!camaraActiva && !cargandoCamara && (
          <div className="flex h-[260px] items-center justify-center bg-black text-sm text-[var(--text-muted)]">
            📷 Cámara apagada
          </div>
        )}

        {cargandoCamara && (
          <div className="flex h-[260px] items-center justify-center bg-black text-sm text-[var(--text-muted)]">
            Activando cámara...
          </div>
        )}

        <div className="border-t border-[var(--border)] bg-[var(--bg-primary)] p-3">
          {!camaraActiva ? (
            <Button
              size="sm"
              fullWidth
              onClick={iniciarCamara}
              disabled={cargandoCamara || buscando || actualizando}
            >
              {cargandoCamara ? "Activando cámara..." : "📷 Escanear con cámara"}
            </Button>
          ) : (
            <Button variant="danger" size="sm" fullWidth onClick={detenerCamara}>
              Detener cámara
            </Button>
          )}
        </div>
      </Card>

      {/* Búsqueda manual */}
      <Card className="mx-auto mt-3 max-w-2xl" padding="sm">
        <p className="mb-2 text-xs font-semibold text-[var(--text-secondary)]">
          También puedes ingresar el código manualmente
        </p>
        <div className="flex gap-2">
          <Input
            placeholder="Ingresa el número de guía"
            value={codigo}
            onChange={(e) => {
              setCodigo(e.target.value);
              setMensaje("");
            }}
            onKeyDown={(e) => {
              if (e.key === "Enter") buscarCodigo();
            }}
            disabled={buscando || actualizando}
            className="flex-1"
          />
          <Button
            size="sm"
            onClick={buscarCodigo}
            disabled={buscando || actualizando}
            className="shrink-0"
          >
            {buscando ? "..." : "Buscar"}
          </Button>
        </div>
      </Card>

      {mensaje && (
        <Card className="mx-auto mt-3 max-w-2xl p-3 text-center">
          <p className="text-xs text-[var(--text-secondary)]">{mensaje}</p>
        </Card>
      )}

      {guiaEncontrada && (
        <Card className="mx-auto mt-3 max-w-2xl" padding="sm">
          <div className="mb-3 text-center">
            <div className="text-2xl">📦</div>
            <h2 className="mt-1 text-base font-black text-emerald-500">Guía encontrada</h2>
          </div>

          <div className="mb-3 rounded-lg border border-[var(--border)] bg-[var(--bg-primary)] p-3 text-center">
            <p className="text-[10px] font-bold uppercase tracking-wider text-[var(--text-muted)]">
              Estado actual
            </p>
            <p className="mt-1 text-lg font-black text-[var(--accent)]">
              {labelEstado(guiaEncontrada.estado)}
            </p>
            {siguienteEstado && (
              <>
                <p className="mt-2 text-[10px] font-bold uppercase tracking-wider text-[var(--text-muted)]">
                  Siguiente paso
                </p>
                <p className="text-sm font-bold text-[var(--text-primary)]">{labelEstado(siguienteEstado)}</p>
              </>
            )}
          </div>

          <div className="grid gap-2">
            {Object.entries(guiaEncontrada).map(([clave, valor]) => {
              if (
                clave === "estado" ||
                valor === null ||
                valor === undefined ||
                typeof valor === "object"
              ) {
                return null;
              }

              return (
                <div
                  key={clave}
                  className="flex flex-col rounded-lg border border-[var(--border)] bg-[var(--bg-primary)] p-2.5 text-xs sm:flex-row sm:justify-between"
                >
                  <span className="font-semibold capitalize text-[var(--text-muted)]">
                    {clave.replace(/_/g, " ")}
                  </span>
                  <span className="mt-0.5 break-all text-[var(--text-primary)] sm:mt-0">
                    {String(valor)}
                  </span>
                </div>
              );
            })}
          </div>

          {esEntregas && esEntregaFinal && (
            <div className="mt-3 rounded-lg border border-blue-500/30 bg-blue-500/10 p-3 text-center">
              <div className="text-2xl">📸</div>
              <h3 className="mt-1 text-sm font-black text-blue-500">Evidencia de entrega</h3>
              <p className="mt-1 text-xs text-[var(--text-secondary)]">
                Toma una fotografía de cómo fue entregada la caja antes de confirmar.
              </p>

              {vistaPreviaFoto && (
                <div className="mt-2 overflow-hidden rounded-lg border border-[var(--border)] bg-black">
                  <img
                    src={vistaPreviaFoto}
                    alt="Evidencia de entrega"
                    className="max-h-[260px] w-full object-contain"
                  />
                </div>
              )}

              <Button
                size="sm"
                fullWidth
                onClick={tomarFotoEntrega}
                disabled={actualizando}
                className="mt-2"
              >
                {fotoEntrega ? "Cambiar foto" : "Tomar foto de entrega"}
              </Button>
            </div>
          )}

          {siguienteEstado && (
            <Button
              size="sm"
              fullWidth
              onClick={actualizarEstado}
              disabled={actualizando || (esEntregas && esEntregaFinal && !fotoEntrega)}
              className="mt-3"
            >
              {actualizando
                ? "Actualizando..."
                : esEntregas && esEntregaFinal
                ? fotoEntrega
                  ? "✅ Confirmar entrega"
                  : "📸 Toma la foto para continuar"
                : `➡️ Mover a ${labelEstado(siguienteEstado).toUpperCase()}`}
            </Button>
          )}

          {!siguienteEstado && (
            <div className="mt-3 rounded-lg border border-emerald-500/30 bg-emerald-500/10 p-3 text-center text-xs font-bold text-emerald-500">
              ✅ Esta guía ya fue entregada
            </div>
          )}

          <Button
            variant="secondary"
            size="sm"
            fullWidth
            onClick={nuevoEscaneo}
            disabled={actualizando}
            className="mt-2"
          >
            📷 Escanear otra guía
          </Button>
        </Card>
      )}
    </PageLayout>
  );
}
