"use client";

import {
  useEffect,
  useRef,
  useState,
} from "react";

type Guia = {
  id?: string | number;
  estado?: string;
  numero_guia?: string;
  [key: string]: any;
};

type UsuarioSesion = {
  usuario?: string;
  tipo?: string;
  nombre?: string;
  accesoCompleto?: boolean;
};

const ESTADOS = [
  "Recolectada",
  "En Bodega",
  "Ingreso en el contenedor",
  "En tránsito",
  "Llegó a Honduras",
  "Ruta de entrega",
  "Entregada",
];

function obtenerSiguienteEstado(
  estadoActual?: string
) {
  const indice = ESTADOS.findIndex(
    (estado) =>
      estado.toLowerCase() ===
      (estadoActual || "")
        .trim()
        .toLowerCase()
  );

  if (indice === -1) {
    return "En Bodega";
  }

  if (indice >= ESTADOS.length - 1) {
    return null;
  }

  return ESTADOS[indice + 1];
}

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);

  /*
  ==========================================
  FOTO DE ENTREGA
  ==========================================
  */

  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);

  /*
  ==========================================
  CARGAR USUARIO
  ==========================================
  */

  useEffect(() => {
    try {
      const usuarioGuardado =
        localStorage.getItem(
          "dg_cargo_usuario_sesion"
        );

      if (usuarioGuardado) {
        const usuarioParseado =
          JSON.parse(usuarioGuardado);

        console.log(
          "USUARIO DE SESIÓN:",
          usuarioParseado
        );

        setUsuario(
          usuarioParseado
        );
      }
    } catch (error) {
      console.error(
        "ERROR CARGANDO USUARIO:",
        error
      );
    } finally {
      setSesionCargada(true);
    }
  }, []);

  /*
  ==========================================
  LIMPIAR FOTO
  ==========================================
  */

  useEffect(() => {
    return () => {
      if (vistaPreviaFoto) {
        URL.revokeObjectURL(
          vistaPreviaFoto
        );
      }
    };
  }, [vistaPreviaFoto]);

  /*
  ==========================================
  CERRAR SESIÓN
  ==========================================
  */

  async function cerrarSesion() {
    await detenerCamara();

    try {
      await fetch(
        "/api/logout",
        {
          method: "POST",
          credentials: "include",
        }
      );
    } catch (error) {
      console.error(
        "ERROR CERRANDO SESIÓN:",
        error
      );
    }

    localStorage.removeItem(
      "dg_cargo_usuario_sesion"
    );

    localStorage.removeItem(
      "dg_cargo_usuario"
    );

    localStorage.removeItem(
      "dg_cargo_password"
    );

    window.location.href = "/";
  }

  /*
  ==========================================
  DETENER CÁMARA
  ==========================================
  */

  async function detenerCamara() {
    const scanner =
      scannerRef.current;

    scannerActivoRef.current =
      false;

    if (scanner) {
      try {
        const estado =
          scanner.getState?.();

        if (
          estado === 2 ||
          estado === 3
        ) {
          await scanner.stop();
        }
      } catch (error) {
        console.log(
          "La cámara ya estaba detenida."
        );
      }

      try {
        await scanner.clear();
      } catch (error) {
        console.log(
          "No se pudo limpiar el lector."
        );
      }

      scannerRef.current =
        null;
    }

    setCamaraActiva(false);
  }

  /*
  ==========================================
  BUSCAR GUÍA
  ==========================================
  */

  async function buscarGuia(
    codigoBuscar?: string
  ) {
    const codigoFinal =
      (codigoBuscar || codigo)
        .trim()
        .toUpperCase();

    if (!codigoFinal) {
      setMensaje(
        "⚠️ Ingresa o escanea un código primero."
      );

      return;
    }

    if (buscandoRef.current) {
      return;
    }

    try {
      buscandoRef.current =
        true;

      setBuscando(true);

      setGuiaEncontrada(null);

      if (vistaPreviaFoto) {
        URL.revokeObjectURL(
          vistaPreviaFoto
        );
      }

      setFotoEntrega(null);

      setVistaPreviaFoto("");

      setMensaje(
        "🔎 Buscando guía: " +
          codigoFinal
      );

      const respuesta =
        await fetch(
          `/api/guias/buscar?codigo=${encodeURIComponent(
            codigoFinal
          )}`,
          {
            method: "GET",
            cache: "no-store",
            credentials: "include",
          }
        );

      const resultado =
        await respuesta.json();

      if (!respuesta.ok) {
        setMensaje(
          "❌ " +
            (
              resultado.error ||
              "No se pudo buscar la guía."
            )
        );

        return;
      }

      if (
        !resultado.encontrada ||
        !resultado.guia
      ) {
        setMensaje(
          "❌ No se encontró la guía: " +
            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);
    }
  }

  /*
  ==========================================
  SELECCIONAR FOTO DE ENTREGA
  ==========================================
  */

  function seleccionarFoto(
    event: React.ChangeEvent<
      HTMLInputElement
    >
  ) {
    const archivo =
      event.target.files?.[0];

    if (!archivo) {
      return;
    }

    if (
      !archivo.type.startsWith(
        "image/"
      )
    ) {
      setMensaje(
        "❌ Debes seleccionar una imagen."
      );

      return;
    }

    if (
      vistaPreviaFoto
    ) {
      URL.revokeObjectURL(
        vistaPreviaFoto
      );
    }

    const url =
      URL.createObjectURL(
        archivo
      );

    setFotoEntrega(
      archivo
    );

    setVistaPreviaFoto(
      url
    );

    setMensaje(
      "📷 Foto de entrega lista. Ya puedes confirmar la entrega."
    );

    event.target.value = "";
  }

  /*
  ==========================================
  TOMAR FOTO
  ==========================================
  */

  function tomarFotoEntrega() {
    if (
      !inputFotoRef.current
    ) {
      return;
    }

    inputFotoRef.current.click();
  }

  /*
  ==========================================
  ACTUALIZAR ESTADO
  ==========================================
  */

  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 está entregada."
      );

      return;
    }

    const tipoUsuario =
      String(
        usuario?.tipo || ""
      )
        .trim()
        .toLowerCase();

    const esUsuarioEntregas =
      tipoUsuario === "entregas" ||
      usuario?.accesoCompleto === false;

    const esEntregaFinal =
      siguienteEstado
        .trim()
        .toLowerCase() ===
      "entregada";

    /*
    ========================================
    EXIGIR FOTO AL USUARIO DE ENTREGAS
    ========================================
    */

    if (
      esUsuarioEntregas &&
      esEntregaFinal &&
      !fotoEntrega
    ) {
      setMensaje(
        "📷 Debes tomar una foto de la entrega antes de marcar la guía como entregada."
      );

      return;
    }

    try {
      setActualizando(true);

      setMensaje(
        "⏳ Actualizando estado..."
      );

      /*
      ======================================
      POR AHORA ACTUALIZAMOS EL ESTADO.
      EN EL SIGUIENTE PASO CONECTAREMOS
      LA FOTO CON SUPABASE STORAGE.
      ======================================
      */

      const respuesta =
        await fetch(
          "/api/actualizar-estado",
          {
            method: "POST",

            headers: {
              "Content-Type":
                "application/json",
            },

            credentials: "include",

            body: JSON.stringify({
              id: guiaEncontrada.id,
              estado: siguienteEstado,
            }),
          }
        );

      const resultado =
        await respuesta.json();

      if (!respuesta.ok) {
        setMensaje(
          "❌ " +
            (
              resultado.error ||
              "No se pudo actualizar la guía."
            )
        );

        return;
      }

      if (!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) {
      console.error(
        "ERROR ACTUALIZANDO ESTADO:",
        error
      );

      setMensaje(
        "❌ Ocurrió un error al actualizar la guía."
      );

    } finally {
      setActualizando(false);
    }
  }

  /*
  ==========================================
  INICIAR CÁMARA
  ==========================================
  */

  async function iniciarCamara() {
    try {
      setMensaje("");

      setGuiaEncontrada(null);

      setCargandoCamara(true);

      if (
        !navigator.mediaDevices ||
        !navigator.mediaDevices.getUserMedia
      ) {
        setMensaje(
          "Tu navegador no permite acceder a la cámara."
        );

        return;
      }

      const stream =
        await navigator.mediaDevices.getUserMedia({
          video: {
            facingMode: {
              ideal: "environment",
            },
          },
          audio: false,
        });

      stream
        .getTracks()
        .forEach(
          (track) =>
            track.stop()
        );

      const {
        Html5Qrcode,
      } = await import(
        "html5-qrcode"
      );

      await detenerCamara();

      const scanner =
        new Html5Qrcode(
          "reader"
        );

      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;

      setCamaraActiva(true);

      await scanner.start(
        cameraId,
        {
          fps: 10,

          qrbox: {
            width: 300,
            height: 180,
          },

          aspectRatio: 1.7778,
        },

        async (
          decodedText: string
        ) => {
          if (
            !scannerActivoRef.current ||
            buscandoRef.current
          ) {
            return;
          }

          const codigoDetectado =
            decodedText
              .trim()
              .toUpperCase();

          if (!codigoDetectado) {
            return;
          }

          scannerActivoRef.current =
            false;

          setCodigo(
            codigoDetectado
          );

          await detenerCamara();

          await buscarGuia(
            codigoDetectado
          );
        },

        () => {}
      );

      setMensaje(
        "📷 Cámara activada. Apunta al código de barras o QR."
      );

    } catch (error: any) {
      console.error(
        "ERROR COMPLETO DE CÁMARA:",
        error
      );

      scannerActivoRef.current =
        false;

      setCamaraActiva(false);

      setMensaje(
        "❌ No se pudo activar la cámara."
      );

    } finally {
      setCargandoCamara(false);
    }
  }

  /*
  ==========================================
  BUSCAR CÓDIGO MANUAL
  ==========================================
  */

  async function buscarCodigo() {
    await buscarGuia(
      codigo
    );
  }

  /*
  ==========================================
  NUEVO ESCANEO
  ==========================================
  */

  async function nuevoEscaneo() {
    setCodigo("");

    setMensaje("");

    setGuiaEncontrada(null);

    setFotoEntrega(null);

    if (
      vistaPreviaFoto
    ) {
      URL.revokeObjectURL(
        vistaPreviaFoto
      );
    }

    setVistaPreviaFoto("");

    await iniciarCamara();
  }

  /*
  ==========================================
  REGRESAR
  ==========================================
  */

  async function regresar() {
    await detenerCamara();

    window.location.href =
      "/dashboard";
  }

  /*
  ==========================================
  LIMPIAR SCANNER AL SALIR
  ==========================================
  */

  useEffect(() => {
    return () => {
      scannerActivoRef.current =
        false;

      const scanner =
        scannerRef.current;

      if (scanner) {
        scanner
          .stop()
          .catch(() => {});

        scanner
          .clear()
          .catch(() => {});
      }
    };
  }, []);

  /*
  ==========================================
  SIGUIENTE ESTADO
  ==========================================
  */

  const siguienteEstado =
    guiaEncontrada
      ? obtenerSiguienteEstado(
          guiaEncontrada.estado
        )
      : null;

  /*
  ==========================================
  DETECTAR USUARIO DE ENTREGAS
  ==========================================
  */

  const tipoUsuario =
    String(
      usuario?.tipo || ""
    )
      .trim()
      .toLowerCase();

  const esEntregas =
    tipoUsuario === "entregas" ||
    usuario?.accesoCompleto === false;

  /*
  ==========================================
  DETECTAR ENTREGA FINAL
  ==========================================
  */

  const esEntregaFinal =
    siguienteEstado
      ?.trim()
      .toLowerCase() ===
    "entregada";

  if (!sesionCargada) {
    return (
      <main className="flex min-h-screen items-center justify-center bg-[#0b1424] text-white">
        Cargando...
      </main>
    );
  }

  return (
    <main className="min-h-screen bg-[#0b1424] px-4 py-8 text-white">

      <input
        ref={inputFotoRef}
        type="file"
        accept="image/*"
        capture="environment"
        onChange={seleccionarFoto}
        className="hidden"
      />

      <div className="mx-auto w-full max-w-2xl">

        {/*
        ======================================
        BOTÓN SUPERIOR
        ======================================
        */}

        {esEntregas ? (

          <button
            type="button"
            onClick={cerrarSesion}
            className="mb-6 rounded-xl border border-red-500 bg-red-600 px-5 py-3 font-bold text-white transition hover:bg-red-700"
          >
            🚪 CERRAR SESIÓN
          </button>

        ) : (

          <button
            type="button"
            onClick={regresar}
            className="mb-6 rounded-xl border border-slate-600 bg-[#172236] px-5 py-3 font-bold text-white transition hover:bg-slate-700"
          >
            ← REGRESAR AL DASHBOARD
          </button>

        )}

        <div className="mb-6 text-center">

          <div className="text-5xl">
            📷
          </div>

          <h1 className="mt-3 text-3xl font-black">
            Escanear Caja
          </h1>

          <p className="mt-2 text-slate-400">
            Escanea el código de barras o QR de una etiqueta.
          </p>

        </div>

        {/*
        ======================================
        CÁMARA
        ======================================
        */}

        <div className="overflow-hidden rounded-2xl border border-slate-600 bg-black">

          <div
            id="reader"
            className="min-h-[340px] w-full"
          />

          {!camaraActiva &&
            !cargandoCamara && (

              <div className="flex h-[340px] items-center justify-center bg-black text-slate-400">
                📷 Cámara apagada
              </div>

            )}

          {cargandoCamara && (

            <div className="flex h-[340px] items-center justify-center bg-black text-slate-400">
              Activando cámara...
            </div>

          )}

          <div className="border-t border-slate-700 bg-[#172236] p-4">

            {!camaraActiva ? (

              <button
                type="button"
                onClick={iniciarCamara}
                disabled={
                  cargandoCamara ||
                  buscando ||
                  actualizando
                }
                className="w-full rounded-xl bg-orange-500 px-5 py-4 text-lg font-bold text-white transition hover:bg-orange-600 disabled:opacity-50"
              >
                {cargandoCamara
                  ? "ACTIVANDO CÁMARA..."
                  : "📷 ESCANEAR CON CÁMARA"}
              </button>

            ) : (

              <button
                type="button"
                onClick={detenerCamara}
                className="w-full rounded-xl bg-red-600 px-5 py-4 text-lg font-bold text-white transition hover:bg-red-700"
              >
                DETENER CÁMARA
              </button>

            )}

          </div>

        </div>

        {/*
        ======================================
        BÚSQUEDA MANUAL
        ======================================
        */}

        <div className="mt-4 rounded-2xl border border-slate-600 bg-[#172236] p-4">

          <p className="mb-3 text-sm font-semibold text-slate-300">
            También puedes ingresar el código manualmente
          </p>

          <div className="flex gap-2">

            <input
              type="text"
              value={codigo}
              onChange={(e) => {
                setCodigo(
                  e.target.value
                );

                setMensaje("");
              }}
              onKeyDown={(e) => {
                if (
                  e.key === "Enter"
                ) {
                  buscarCodigo();
                }
              }}
              placeholder="Ejemplo: HCE000011"
              disabled={
                buscando ||
                actualizando
              }
              className="min-w-0 flex-1 rounded-xl border border-slate-600 bg-black px-4 py-3 text-white outline-none focus:border-orange-500 disabled:opacity-60"
            />

            <button
              type="button"
              onClick={buscarCodigo}
              disabled={
                buscando ||
                actualizando
              }
              className="rounded-xl bg-slate-600 px-6 py-3 font-bold transition hover:bg-slate-500 disabled:opacity-50"
            >
              {buscando
                ? "..."
                : "Buscar"}
            </button>

          </div>

        </div>

        {/*
        ======================================
        MENSAJE
        ======================================
        */}

        {mensaje && (

          <div className="mt-4 rounded-xl border border-slate-600 bg-[#172236] p-4 text-center text-slate-300">
            {mensaje}
          </div>

        )}

        {/*
        ======================================
        GUÍA ENCONTRADA
        ======================================
        */}

        {guiaEncontrada && (

          <div className="mt-4 rounded-2xl border border-green-500/40 bg-green-500/10 p-5">

            <div className="mb-4 text-center">

              <div className="text-3xl">
                📦
              </div>

              <h2 className="mt-2 text-xl font-black text-green-400">
                GUÍA ENCONTRADA
              </h2>

            </div>

            <div className="mb-4 rounded-xl border border-orange-500/40 bg-orange-500/10 p-4 text-center">

              <p className="text-xs font-bold uppercase text-slate-400">
                Estado actual
              </p>

              <p className="mt-1 text-xl font-black text-orange-400">
                {guiaEncontrada.estado ||
                  "Sin estado"}
              </p>

              {siguienteEstado && (

                <>

                  <p className="mt-4 text-xs font-bold uppercase text-slate-400">
                    Siguiente paso
                  </p>

                  <p className="mt-1 text-lg font-bold text-white">
                    {siguienteEstado}
                  </p>

                </>

              )}

            </div>

            {/*
            ==================================
            DATOS DE LA GUÍA
            ==================================
            */}

            <div className="grid gap-3">

              {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-xl border border-slate-600 bg-[#172236] p-3 sm:flex-row sm:justify-between"
                    >

                      <span className="font-semibold capitalize text-slate-400">
                        {clave.replaceAll(
                          "_",
                          " "
                        )}
                      </span>

                      <span className="mt-1 break-all text-white sm:mt-0">
                        {String(valor)}
                      </span>

                    </div>

                  );
                }
              )}

            </div>

            {/*
            ==================================
            FOTO DE ENTREGA

            SOLO USUARIO ENTREGAS
            SOLO CUANDO EL SIGUIENTE ESTADO
            ES ENTREGADA
            ==================================
            */}

            {esEntregas &&
              esEntregaFinal && (

                <div className="mt-5 rounded-2xl border border-blue-500/50 bg-blue-500/10 p-5">

                  <div className="text-center">

                    <div className="text-5xl">
                      📸
                    </div>

                    <h3 className="mt-2 text-xl font-black text-blue-400">
                      EVIDENCIA DE ENTREGA
                    </h3>

                    <p className="mt-2 text-sm text-slate-300">
                      Debes tomar una fotografía de cómo fue entregada la caja antes de confirmar la entrega.
                    </p>

                  </div>

                  {vistaPreviaFoto && (

                    <div className="mt-4 overflow-hidden rounded-xl border border-slate-600 bg-black">

                      <img
                        src={vistaPreviaFoto}
                        alt="Evidencia de entrega"
                        className="max-h-[400px] w-full object-contain"
                      />

                    </div>

                  )}

                  <button
                    type="button"
                    onClick={tomarFotoEntrega}
                    disabled={actualizando}
                    className="mt-4 w-full rounded-xl bg-blue-600 px-5 py-4 text-lg font-bold text-white transition hover:bg-blue-700 disabled:opacity-50"
                  >
                    {fotoEntrega
                      ? "📷 CAMBIAR FOTO DE ENTREGA"
                      : "📷 TOMAR FOTO DE ENTREGA"}
                  </button>

                </div>

              )}

            {/*
            ==================================
            ACTUALIZAR ESTADO
            ==================================
            */}

            {siguienteEstado && (

              <button
                type="button"
                onClick={actualizarEstado}
                disabled={
                  actualizando ||
                  (
                    esEntregas &&
                    esEntregaFinal &&
                    !fotoEntrega
                  )
                }
                className="mt-5 w-full rounded-xl bg-green-600 px-5 py-4 text-lg font-bold text-white transition hover:bg-green-700 disabled:opacity-50"
              >
                {actualizando
                  ? "ACTUALIZANDO..."
                  : esEntregas &&
                    esEntregaFinal
                  ? fotoEntrega
                    ? "✅ CONFIRMAR ENTREGA"
                    : "📷 TOMA LA FOTO PARA CONTINUAR"
                  : "➡️ MOVER A " +
                    siguienteEstado.toUpperCase()}
              </button>

            )}

            {!siguienteEstado && (

              <div className="mt-5 rounded-xl border border-green-500/40 bg-green-500/10 p-4 text-center font-bold text-green-400">
                ✅ ESTA GUÍA YA FUE ENTREGADA
              </div>

            )}

            <button
              type="button"
              onClick={nuevoEscaneo}
              disabled={actualizando}
              className="mt-3 w-full rounded-xl bg-orange-500 px-5 py-4 text-lg font-bold text-white transition hover:bg-orange-600 disabled:opacity-50"
            >
              📷 ESCANEAR OTRA CAJA
            </button>

          </div>

        )}

      </div>

    </main>
  );
}