/**
 * Loja VTEX: a busca pública do catálogo,
 * `/api/catalog_system/pub/products/search` (de 50 em 50). Cada produto traz
 * os itens (as variações), com preço, preço cheio, foto e código.
 */

import { absoluto, atributosDasVariantes, dentroDoTeto, linha, menorPreco, precoDoDado, produtoVazio, TETOS, type ProdutoLido, type VarianteLida } from "../modelo.ts";
import { lista, objeto, primeiroTexto, texto, type Objeto } from "./dado.ts";

function produto(bruto: unknown, origem: string): ProdutoLido | null {
  const dado = objeto(bruto);
  if (!dado) return null;
  const nome = linha(dado.productName, 300);
  if (!nome) return null;
  const referencia = absoluto(dado.link, origem) ?? (texto(dado.linkText) ? `${origem}/${texto(dado.linkText)}/p` : null);
  if (!referencia) return null;

  const lido = produtoVazio(referencia, nome);
  lido.descricao = texto(dado.description);
  lido.marca = linha(dado.brand, 120) || null;
  /* "/Roupas/Camisetas/": o primeiro caminho é o mais completo. */
  const caminho = texto(lista(dado.categories)[0]);
  lido.categorias = caminho
    .split("/")
    .map((parte) => linha(parte, 120))
    .filter(Boolean);

  const itens = lista(dado.items)
    .slice(0, TETOS.variantes)
    .map((item) => objeto(item))
    .filter((item): item is Objeto => Boolean(item));

  /* Cada item (tamanho, cor) repete as mesmas fotos com outro número no
     endereço (/arquivos/ids/6822985/49FP-C1.jpg e /ids/6823048/49FP-C1.jpg):
     a foto é a mesma quando o arquivo tem o mesmo nome. */
  const nomeDoArquivo = (endereco: string) => {
    try {
      return decodeURIComponent(new URL(endereco).pathname.split("/").pop() ?? endereco).toLowerCase();
    } catch {
      return endereco;
    }
  };
  const fotoPeloNome = new Map<string, string>();
  for (const item of itens) {
    for (const foto of lista(item.images).slice(0, 20)) {
      const endereco = absoluto(objeto(foto)?.imageUrl, referencia);
      if (endereco && !fotoPeloNome.has(nomeDoArquivo(endereco))) fotoPeloNome.set(nomeDoArquivo(endereco), endereco);
    }
  }
  const primeiraFoto = (item: Objeto) => {
    const endereco = absoluto(objeto(lista(item.images)[0])?.imageUrl, referencia);
    return endereco ? (fotoPeloNome.get(nomeDoArquivo(endereco)) ?? endereco) : null;
  };

  const variantes: VarianteLida[] = itens.map((item) => {
    const oferta = objeto(objeto(lista(item.sellers)[0])?.commertialOffer) ?? {};
    const opcoes: Record<string, string> = {};
    for (const nomeDaVariacao of lista(item.variations).map((valor) => texto(valor))) {
      const valor = linha(lista(item[nomeDaVariacao])[0], 80);
      if (nomeDaVariacao && valor) opcoes[linha(nomeDaVariacao, 60)] = valor;
    }
    const preco = precoDoDado(oferta.Price);
    const cheio = precoDoDado(oferta.ListPrice);
    return {
      opcoes,
      preco: preco && preco > 0 ? preco : null,
      precoAntigo: cheio && preco && cheio > preco ? cheio : null,
      foto: primeiraFoto(item),
      codigo: primeiroTexto(objeto(lista(item.referenceId)[0])?.Value, item.itemId) || null,
    };
  });

  lido.fotos = [...fotoPeloNome.values()];
  lido.preco = menorPreco(variantes.map((variante) => variante.preco));
  const maisBarata = variantes.find((variante) => variante.preco === lido.preco);
  lido.precoAntigo = maisBarata?.precoAntigo ?? null;
  if (itens.length === 1) {
    lido.codigo = variantes[0]?.codigo ?? null;
    lido.codigoDeBarras = primeiroTexto(itens[0].ean) || null;
  }
  const comOpcoes = variantes.filter((variante) => Object.keys(variante.opcoes).length > 0);
  if (comOpcoes.length > 1) {
    lido.variantes = comOpcoes;
    lido.atributos = atributosDasVariantes(comOpcoes);
  }
  return dentroDoTeto(lido);
}

export function lerVtex(dado: unknown, origem: string): ProdutoLido[] {
  return lista(dado)
    .map((bruto) => produto(bruto, origem))
    .filter((lido): lido is ProdutoLido => Boolean(lido));
}

/** O apelido do produto num endereço VTEX (`/<apelido>/p`), ou null. */
export function apelidoDaVtex(endereco: string): string | null {
  try {
    const achado = /^\/([^/]+)\/p\/?$/.exec(new URL(endereco).pathname);
    return achado ? decodeURIComponent(achado[1]) : null;
  } catch {
    return null;
  }
}

/** O total que a VTEX informa no cabeçalho `resources` ("0-49/1234"). */
export function totalDaVtex(cabecalho: string | undefined): number | null {
  const total = /\/(\d+)\s*$/.exec(cabecalho ?? "")?.[1];
  return total ? Number(total) : null;
}
