import { otsApi } from "./api";
import { db } from "./db";
import { getLocalOtByRouteId, putRemoteOtIfNewer } from "./offline-ots";

export const otEstadoColors: Record<string, string> = {
  borrador: "border-slate-200 bg-slate-100 text-slate-700",
  en_proceso: "border-amber-200 bg-amber-50 text-amber-700",
  cotizada: "border-violet-200 bg-violet-50 text-violet-700",
  aprobada: "border-emerald-200 bg-emerald-50 text-emerald-700",
  terminada: "border-cyan-200 bg-cyan-50 text-cyan-700",
  facturada: "border-indigo-200 bg-indigo-50 text-indigo-700",
  entregada: "border-green-200 bg-green-50 text-green-700",
};

const otNextEstado: Record<string, { next: string; label: string }> = {
  borrador: { next: "cotizada", label: "Marcar cotizada" },
  cotizada: { next: "aprobada", label: "Marcar aprobada" },
  aprobada: { next: "en_proceso", label: "Iniciar trabajo" },
  en_proceso: { next: "terminada", label: "Marcar terminada" },
  terminada: { next: "entregada", label: "Registrar entrega" },
  facturada: { next: "entregada", label: "Registrar entrega" },
};

// Con facturación aplicando, terminada -> facturada lo dispara el sistema (o
// el botón de reintento) y la entrega solo se registra desde facturada.
export function getOtNextEstado(
  estado: string,
  facturacionAplica: boolean,
): { next: string; label: string } | null {
  if (facturacionAplica && estado === "terminada") return null;
  return otNextEstado[estado] ?? null;
}

export const OT_DETAIL_REFRESH_INTERVAL_MS = 15000;

export function isOtLocked(ot: any): boolean {
  return String(ot?.estado || "") === "entregada";
}

export function canMutateOtRemotely(ot: any): boolean {
  if (typeof navigator === "undefined") return false;
  return Boolean(
    Number.isFinite(Number(ot?.serverId)) &&
    navigator.onLine &&
    !isOtLocked(ot),
  );
}

export async function refreshOtDetail(routeId: string) {
  const numericId = Number(routeId);

  if (
    Number.isFinite(numericId) &&
    numericId > 0 &&
    typeof navigator !== "undefined" &&
    navigator.onLine
  ) {
    try {
      const remote = await otsApi.get(numericId);
      await putRemoteOtIfNewer(remote);

      if (remote?.cliente?.tarjeta && remote?.cliente?.nombre) {
        await db.clientes.put({
          tarjeta: String(remote.cliente.tarjeta),
          nombre: String(remote.cliente.nombre || ""),
          nit: remote.cliente.nit,
          direccion: remote.cliente.direccion,
          telefono: remote.cliente.telefono,
          celular: remote.cliente.celular,
          email: remote.cliente.email,
          syncStatus: "synced",
          lastModified: Date.now(),
        });
      }
    } catch (error) {
      console.warn("Using local OT detail cache", error);
    }
  }

  const ot = await getLocalOtByRouteId(routeId);
  if (!ot) return null;

  const [cliente, catalogRows] = await Promise.all([
    ot.clienteTarjeta
      ? db.clientes.where("tarjeta").equals(ot.clienteTarjeta).first()
      : null,
    db.catalogos.toArray(),
  ]);

  const cosasTrae = catalogRows
    .filter((row) => row.tipo === "cosa_trae")
    .sort((a, b) => (a.nombre || "").localeCompare(b.nombre || ""));
  const tiposDano = catalogRows
    .filter((row) => row.tipo === "tipo_dano")
    .sort((a, b) => (a.nombre || "").localeCompare(b.nombre || ""))
    .map((row) => ({
      id: row.id,
      nombre: row.nombre,
      icono: row.extra?.icono || "",
      color: row.extra?.color || "#ef4444",
    }));

  const inventario = (ot.cosasTrae || []).map((value: any) => {
    const numericValue = Number(value?.cosaTraeId || value?.id || value);
    const match = cosasTrae.find((row) => Number(row.id) === numericValue);
    return match?.nombre || String(value?.nombre || value || numericValue);
  });

  return {
    ot,
    cliente,
    cosasTrae,
    tiposDano,
    inventario,
  };
}
