import { lerConfigDoCurso, type ConfigDoCurso } from "./curso.ts";

/*
 * O que a página de um produto digital mostra na loja, lido de
 * `products.digital_config` (só dado público: o painel nunca põe ali endereço
 * de arquivo, link de acesso nem instruções).
 *
 * É o mesmo leitor do painel (apps/admin/src/lib/digitais/produto.ts), só com
 * o que a loja usa. Mudou lá, confere aqui.
 */

export type TipoDigital = "arquivos" | "link" | "codigo" | "curso" | "live";

export type ItemRecebido = { titulo: string; detalhe: string | null; selo: string };
export type Pergunta = { pergunta: string; resposta: string };
export type Licenca = { tipo: "pessoal" | "comercial" | "livre" | "texto"; texto: string | null };

/* Como o comprador recebe: na hora ou sob encomenda (prazo em dias úteis). */
export type ComoEntrega = { modo: "na_hora" | "encomenda"; prazoDias: number };

export type ConfigDigitalDaLoja = {
  tipo: TipoDigital;
  /* Só nos cursos: a página de venda e o resumo público do conteúdo. */
  curso: ConfigDoCurso | null;
  resumo: string | null;
  recebe: ItemRecebido[];
  perguntas: Pergunta[];
  funcionaCom: string[];
  licenca: Licenca | null;
  prazoDias: number | null | undefined;
  amostras: string[];
  entrega: ComoEntrega;
  /* Pré-venda: libera sozinho nesta data (ISO); null = sem pré-venda. */
  preVenda: { em: string } | null;
  /* Vezes que cada arquivo pode ser baixado (null: sem limite, com o freio). */
  limiteDeDownloads: number | null;
  /* Marcar o PDF com o comprador: null segue as Configurações da loja. */
  marcaNoPdf: boolean | null;
};

function inteiroNaFaixa(valor: unknown, padrao: number, minimo: number, maximo: number): number {
  const numero = typeof valor === "number" ? valor : typeof valor === "string" && valor.trim() ? Number(valor) : NaN;
  if (!Number.isFinite(numero)) return padrao;
  return Math.min(maximo, Math.max(minimo, Math.round(numero)));
}

/* A data da pré-venda guardada (ISO), ou null quando não vale. */
export function lerPreVenda(valor: unknown): { em: string } | null {
  const bruto = valor && typeof valor === "object" && !Array.isArray(valor) ? (valor as Record<string, unknown>).em : null;
  if (typeof bruto !== "string" || !/^\d{4}-\d{2}-\d{2}/.test(bruto)) return null;
  const t = new Date(bruto).getTime();
  return Number.isFinite(t) ? { em: new Date(t).toISOString() } : null;
}

/* A pré-venda ainda vale (a data é no futuro)? */
export function emPreVenda(config: { preVenda: { em: string } | null }, agora = Date.now()): boolean {
  return Boolean(config.preVenda && new Date(config.preVenda.em).getTime() > agora);
}

function objeto(valor: unknown): Record<string, unknown> {
  return valor && typeof valor === "object" && !Array.isArray(valor) ? (valor as Record<string, unknown>) : {};
}

function textoLimpo(valor: unknown, teto: number): string | null {
  if (typeof valor !== "string") return null;
  const limpo = valor.replace(/\u0000/g, "").trim();
  return limpo ? limpo.slice(0, teto) : null;
}

function enderecoHttps(valor: unknown): string | null {
  const bruto = textoLimpo(valor, 1000);
  if (!bruto) return null;
  try {
    const url = new URL(bruto);
    return url.protocol === "https:" ? url.toString() : null;
  } catch {
    return null;
  }
}

const TIPOS: readonly TipoDigital[] = ["arquivos", "link", "codigo", "curso", "live"];

export function lerConfigDigitalDaLoja(bruto: unknown): ConfigDigitalDaLoja {
  const raiz = objeto(bruto);
  const licenca = objeto(raiz.licenca);
  const acesso = raiz.acesso === undefined || raiz.acesso === null ? null : objeto(raiz.acesso);
  const tipoDaLicenca = ["pessoal", "comercial", "livre", "texto"].includes(String(licenca.tipo))
    ? (licenca.tipo as Licenca["tipo"])
    : null;
  const prazo = acesso ? acesso.prazoDias : undefined;

  const tipo = TIPOS.includes(raiz.tipo as TipoDigital) ? (raiz.tipo as TipoDigital) : "arquivos";
  return {
    tipo,
    curso: tipo === "curso" ? lerConfigDoCurso(raiz.curso) : null,
    resumo: textoLimpo(raiz.resumo, 160),
    recebe: (Array.isArray(raiz.recebe) ? raiz.recebe : [])
      .slice(0, 30)
      .map((item) => {
        const o = objeto(item);
        const titulo = textoLimpo(o.titulo, 160);
        if (!titulo) return null;
        return { titulo, detalhe: textoLimpo(o.detalhe, 200), selo: (textoLimpo(o.selo, 8) ?? "ITEM").toUpperCase() };
      })
      .filter((item): item is ItemRecebido => item !== null),
    perguntas: (Array.isArray(raiz.perguntas) ? raiz.perguntas : [])
      .slice(0, 12)
      .map((item) => {
        const o = objeto(item);
        const pergunta = textoLimpo(o.pergunta, 200);
        const resposta = textoLimpo(o.resposta, 1200);
        return pergunta && resposta ? { pergunta, resposta } : null;
      })
      .filter((item): item is Pergunta => item !== null),
    funcionaCom: (Array.isArray(raiz.funcionaCom) ? raiz.funcionaCom : [])
      .map((item) => textoLimpo(item, 40))
      .filter((item): item is string => Boolean(item))
      .slice(0, 12),
    licenca: tipoDaLicenca ? { tipo: tipoDaLicenca, texto: textoLimpo(licenca.texto, 2000) } : null,
    /* undefined = o produto segue o prazo da loja; null = sem prazo. */
    prazoDias:
      prazo === undefined
        ? undefined
        : typeof prazo === "number" && Number.isFinite(prazo) && prazo > 0
          ? Math.min(3650, Math.round(prazo))
          : null,
    amostras: (Array.isArray(raiz.amostras) ? raiz.amostras : [])
      .map(enderecoHttps)
      .filter((item): item is string => Boolean(item))
      .slice(0, 8),
    entrega: (() => {
      const entrega = objeto(raiz.entrega);
      return {
        modo: entrega.modo === "encomenda" ? "encomenda" : "na_hora",
        prazoDias: inteiroNaFaixa(entrega.prazoDias, 3, 0, 90),
      } satisfies ComoEntrega;
    })(),
    preVenda: lerPreVenda(raiz.preVenda),
    limiteDeDownloads:
      raiz.limiteDeDownloads === null || raiz.limiteDeDownloads === undefined ? null : inteiroNaFaixa(raiz.limiteDeDownloads, 0, 0, 1000) || null,
    marcaNoPdf: typeof raiz.marcaNoPdf === "boolean" ? raiz.marcaNoPdf : null,
  };
}

/* "até 14/10" para o prazo da encomenda, e "em 01/11" para a pré-venda. */
export function dataCurtaDeBrasilia(iso: string): string {
  try {
    return new Intl.DateTimeFormat("pt-BR", { day: "2-digit", month: "2-digit", timeZone: "America/Sao_Paulo" }).format(new Date(iso));
  } catch {
    return iso.slice(0, 10);
  }
}

/* A promessa da entrega na página e na compra: na hora, sob encomenda (dias
   úteis) ou na pré-venda (a data em que libera). */
export type EntregaNaVitrine = { modo: "na_hora" | "encomenda" | "pre_venda"; prazoDias: number; liberaEm: string | null };

export const ENTREGA_NA_HORA: EntregaNaVitrine = { modo: "na_hora", prazoDias: 0, liberaEm: null };

export function entregaNaVitrine(config: { entrega: ComoEntrega; preVenda: { em: string } | null }, agora = Date.now()): EntregaNaVitrine {
  if (config.preVenda && emPreVenda(config, agora)) return { modo: "pre_venda", prazoDias: 0, liberaEm: dataCurtaDeBrasilia(config.preVenda.em) };
  if (config.entrega.modo === "encomenda") return { modo: "encomenda", prazoDias: config.entrega.prazoDias, liberaEm: null };
  return ENTREGA_NA_HORA;
}

/* "até 3 dias úteis" (no chip) e "em até 3 dias úteis" (na frase). */
export function prazoDaEncomenda(dias: number): { curto: string; frase: string } {
  if (dias <= 0) return { curto: "no mesmo dia útil", frase: "no mesmo dia útil" };
  const unidade = dias === 1 ? "dia útil" : "dias úteis";
  return { curto: `até ${dias} ${unidade}`, frase: `em até ${dias} ${unidade}` };
}

/* Os textos da promessa (null: a entrega é na hora e vale o texto de sempre). */
export function textosDaEntrega(entrega: EntregaNaVitrine, curso = false): { chip: string; linha: string; botao: string } | null {
  if (entrega.modo === "pre_venda") {
    const quando = entrega.liberaEm ? `em ${entrega.liberaEm}` : "no lançamento";
    return {
      chip: `Pré-venda · libera ${quando}`,
      linha: curso
        ? `Pré-venda: garanta agora e comece ${quando}. O acesso chega no seu e-mail.`
        : `Pré-venda: garanta agora e receba ${quando}, no seu e-mail e em Minhas compras.`,
      botao: "Garantir na pré-venda",
    };
  }
  if (entrega.modo === "encomenda") {
    const prazo = prazoDaEncomenda(entrega.prazoDias);
    return {
      chip: `Sob encomenda · ${prazo.curto}`,
      linha: `Feito para você: a loja produz e entrega ${prazo.frase}, no seu e-mail e em Minhas compras.`,
      botao: "Encomendar",
    };
  }
  return null;
}

/* A cor do selo de cada item (PDF vermelho, imagem azul, link roxo...). */
export function corDoSelo(selo: string): string {
  const s = selo.toUpperCase();
  if (s === "PDF") return "#E5484D";
  if (["PNG", "JPG", "JPEG", "WEBP", "SVG", "GIF", "PSD", "AI", "CDR", "EPS", "TIF", "TIFF"].includes(s)) return "#2F80ED";
  if (s === "LINK") return "#7B61FF";
  if (["ZIP", "RAR", "7Z"].includes(s)) return "#F2994A";
  if (["MP4", "MOV", "WEBM", "MKV", "MP3", "WAV", "M4A"].includes(s)) return "#0E9E70";
  if (s === "VÍDEO" || s === "CURSO") return "#1B2440";
  if (s === "CÓD" || s === "COD") return "#0F766E";
  if (s === "SOB") return "#B45309";
  return "#4F5B76";
}

/* "PDF + PNG": os formatos do que vem, para o chip do topo. */
export function formatosDoQueRecebe(recebe: ItemRecebido[]): string | null {
  const formatos = Array.from(new Set(recebe.map((r) => r.selo).filter((s) => s && !["ITEM", "TEXTO"].includes(s))));
  if (!formatos.length) return null;
  return formatos.slice(0, 3).join(" + ") + (formatos.length > 3 ? " +" : "");
}

/* O prazo que vale: o do produto; sem ele, o da loja; sem os dois, sem prazo. */
export function prazoQueVale(doProduto: number | null | undefined, daLoja: number | null | undefined): number | null {
  if (doProduto !== undefined) return doProduto ?? null;
  return typeof daLoja === "number" && daLoja > 0 ? daLoja : null;
}

export function textoDoPrazo(dias: number | null): string {
  if (!dias) return "Acesso sem prazo. Baixe quantas vezes precisar.";
  if (dias % 365 === 0) {
    const anos = dias / 365;
    return `Acesso por ${anos} ${anos === 1 ? "ano" : "anos"} a partir da compra.`;
  }
  if (dias % 30 === 0) {
    const meses = dias / 30;
    return `Acesso por ${meses} ${meses === 1 ? "mês" : "meses"} a partir da compra.`;
  }
  return `Acesso por ${dias} ${dias === 1 ? "dia" : "dias"} a partir da compra.`;
}

/* O prazo, dito para um curso ("assista", não "baixe"). */
export function textoDoPrazoDoCurso(dias: number | null): string {
  if (!dias) return "Acesso para sempre. Assista quantas vezes quiser.";
  return textoDoPrazo(dias);
}

/* O prazo do jeito de cada tipo: o curso se assiste, o código se copia, o resto se baixa. */
export function textoDoPrazoDoTipo(tipo: TipoDigital, dias: number | null): string {
  if (tipo === "curso") return textoDoPrazoDoCurso(dias);
  if (tipo === "codigo" && !dias) return "Acesso sem prazo. Copie o código quando precisar.";
  return textoDoPrazo(dias);
}

/* O chip curto do prazo: "Acesso para sempre", "Acesso por 1 ano". */
export function chipDoPrazo(dias: number | null): string {
  if (!dias) return "Acesso para sempre";
  return textoDoPrazo(dias).replace(/ a partir da compra\.$/, "").replace(/\.$/, "");
}

export const NOME_DA_LICENCA: Record<Licenca["tipo"], string> = {
  pessoal: "Licença pessoal",
  comercial: "Licença comercial",
  livre: "Uso livre",
  texto: "Licença de uso",
};

export const RESUMO_DA_LICENCA: Record<Licenca["tipo"], string> = {
  pessoal: "Para uso próprio. Não pode revender nem repassar o arquivo.",
  comercial: "Pode usar para vender o que produzir com ele. Não pode repassar o arquivo.",
  livre: "Use como quiser.",
  texto: "",
};

/* Os três passos de "como você recebe", conforme o jeito de comprar. */
export function passosDaEntrega(params: {
  jeito: "comprar" | "entrar" | "whatsapp" | "fechado";
  gratis: boolean;
  meios: Array<"pix" | "cartao">;
  prazoDias: number | null;
  /* Curso: o acesso chega no e-mail e a pessoa assiste na área de membros. */
  curso?: boolean;
  /* Código ou licença: a pessoa recebe um código para copiar, não um arquivo. */
  codigo?: boolean;
  /* Sob encomenda ou pré-venda: o segundo e o terceiro passo mudam. */
  entrega?: EntregaNaVitrine;
}): Array<{ titulo: string; texto: string }> {
  const { jeito, gratis, meios, prazoDias, curso, codigo, entrega } = params;
  const preVenda = entrega?.modo === "pre_venda";
  const quando = entrega?.liberaEm ? `em ${entrega.liberaEm}` : "no lançamento";
  const primeiro =
    gratis
      ? { titulo: "Peça o seu", texto: "Na mesma tela, sem precisar criar senha." }
      : jeito === "whatsapp"
        ? { titulo: "Combine com a loja", texto: "Pelo WhatsApp, do jeito de pagar que a loja aceitar." }
        : {
            titulo: meios.length === 1 ? (meios[0] === "pix" ? "Pague com Pix" : "Pague com cartão") : "Pague com Pix ou cartão",
            texto: "Na mesma tela, sem precisar criar senha.",
          };
  if (curso) {
    return [
      primeiro,
      preVenda
        ? { titulo: `Comece ${quando}`, texto: "No dia do lançamento, o botão para entrar no conteúdo chega no seu e-mail." }
        : jeito === "whatsapp" && !gratis
        ? { titulo: "Receba o acesso quando a loja confirmar", texto: "O botão para entrar no conteúdo chega no seu e-mail." }
        : { titulo: "Receba o acesso no e-mail", texto: "Um botão leva direto para a área de membros, já com o seu conteúdo." },
      { titulo: "Assista no seu ritmo", texto: "A área marca o que você já viu e volta de onde parou, em qualquer aparelho." },
    ];
  }
  if (codigo) {
    const usar = {
      titulo: "Use quando quiser",
      texto: prazoDias ? textoDoPrazo(prazoDias) : "Fica guardado em Minhas compras, para copiar quando precisar.",
    };
    if (preVenda) {
      return [primeiro, { titulo: `Receba ${quando}`, texto: "No dia do lançamento, o seu código aparece em Minhas compras e chega no seu e-mail." }, usar];
    }
    return [
      primeiro,
      jeito === "whatsapp" && !gratis
        ? { titulo: "Receba quando a loja confirmar", texto: "O seu código chega no seu e-mail assim que o pagamento for confirmado." }
        : { titulo: "Receba o código na hora", texto: "Ele aparece na tela e chega no seu e-mail." },
      usar,
    ];
  }
  const segundo =
    jeito === "whatsapp" && !gratis
      ? { titulo: "Receba quando a loja confirmar", texto: "Os itens chegam no seu e-mail assim que o pagamento for confirmado." }
      : { titulo: "Receba na hora", texto: "Os itens aparecem na tela e chegam no seu e-mail." };
  const terceiro = {
    titulo: "Baixe quando quiser",
    texto: prazoDias ? textoDoPrazo(prazoDias) : "Ficam guardados em Minhas compras, sem prazo.",
  };
  if (preVenda) {
    return [primeiro, { titulo: `Receba ${quando}`, texto: "No dia do lançamento, os itens aparecem em Minhas compras e chegam no seu e-mail." }, terceiro];
  }
  if (entrega?.modo === "encomenda") {
    const prazo = prazoDaEncomenda(entrega.prazoDias);
    return [
      primeiro,
      { titulo: "A loja produz o seu", texto: `Com o que você informar na compra, ${prazo.frase}.` },
      { titulo: "Receba e baixe", texto: "O arquivo pronto chega no seu e-mail e fica guardado em Minhas compras." },
    ];
  }
  return [primeiro, segundo, terceiro];
}
