import {
  FUNDO_PADRAO,
  comAgendamento,
  comDispositivo,
  comFundo,
  lerAgendamento,
  lerDispositivo,
  lerFundo,
  problemaDaExibicao,
  textoDoAgendamento,
  type Espaco,
  type FundoDaSecao,
  type TipoDeFundo,
} from "@/lib/exibicao-da-secao";
import { instanteDeBrasilia } from "@/lib/widgets-da-home";

import type { Campos } from "../esquema";

/*
 * Agendar, aparelho e fundo de uma seção pelo assistente (criar_secao e
 * alterar_secao): o mesmo que o editor faz em "Como e quando aparece"
 * (lib/exibicao-da-secao.ts, guardado em config.agendamento,
 * config.dispositivo e config.fundo_da_secao). Regras sem banco: a imagem do
 * fundo volta como pendência para quem chama subir.
 */

const ESPACOS = ["nenhum", "p", "m", "g"] as const;

export const CAMPOS_DA_EXIBICAO: Campos = {
  agendamento: {
    tipo: "objeto",
    descricao:
      'Agendar a seção: ela entra e sai da loja sozinha. Hora de Brasília, "AAAA-MM-DD HH:MM". Mande inicio e/ou fim; texto vazio tira aquele lado (os dois vazios tiram o agendamento).',
    campos: {
      inicio: { tipo: "texto", max: 20, descricao: 'Quando passa a aparecer ("2026-11-27 00:00"). Vazio = já aparece.' },
      fim: { tipo: "texto", max: 20, descricao: 'Quando sai da loja ("2026-11-30 23:59"). Vazio = não sai.' },
    },
  },
  dispositivo: {
    tipo: "opcao",
    descricao: "Em que aparelho a seção aparece: ambos (padrão), celular (só no celular) ou computador (só no computador).",
    opcoes: ["ambos", "celular", "computador"],
  },
  fundo: {
    tipo: "objeto",
    descricao:
      "O fundo da seção e o espaço em volta dela (vale para qualquer tipo). tipo nenhum tira o fundo. Mande só o que muda.",
    campos: {
      tipo: { tipo: "opcao", opcoes: ["nenhum", "cor", "gradiente", "imagem"], descricao: "nenhum, cor (uma cor), gradiente (duas cores) ou imagem." },
      cor: { tipo: "texto", max: 9, descricao: "Cor (ou a primeira do gradiente), como #F4F0FF." },
      cor_2: { tipo: "texto", max: 9, descricao: "A segunda cor do gradiente." },
      angulo: { tipo: "inteiro", min: 0, max: 359, descricao: "Direção do gradiente em graus (90 = da esquerda para a direita, 180 = de cima para baixo). Padrão 135." },
      imagem: { tipo: "texto", max: 2000, descricao: 'A imagem do fundo (link https, "envio:..." ou "produto:<id>"). Ela cobre a seção, cortada pelo centro.' },
      escurecer: { tipo: "inteiro", min: 0, max: 80, descricao: "Imagem: quanto escurecer (0 a 80%) para o texto aparecer. Padrão 35." },
      largura: { tipo: "opcao", opcoes: ["inteira", "contida"], descricao: "inteira (de ponta a ponta) ou contida (caixa arredondada no centro)." },
      texto_claro: { tipo: "booleano", descricao: "Textos da seção em branco (sobre fundo escuro). Sem mandar, é automático: branco sobre imagem escurecida (35% ou mais) e sobre cor escura." },
      espaco_acima: { tipo: "opcao", opcoes: [...ESPACOS], descricao: "Espaço a mais acima da seção: nenhum, p, m ou g." },
      espaco_abaixo: { tipo: "opcao", opcoes: [...ESPACOS], descricao: "Espaço a mais abaixo da seção: nenhum, p, m ou g." },
    },
  },
};

/** O pedido trouxe imagem de fundo (vira parte da cara pública da loja: passa pela aprovação). */
export function fundoTemImagem(args: Record<string, unknown>) {
  const fundo = args.fundo && typeof args.fundo === "object" ? (args.fundo as Record<string, unknown>) : null;
  return Boolean(fundo && fundo.imagem !== undefined && String(fundo.imagem).trim());
}

function hexValido(valor: unknown) {
  const texto = String(valor ?? "").trim();
  return /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(texto) ? texto : null;
}

function dataDoPedido(valor: unknown): string | null {
  const texto = String(valor ?? "").trim().replace(" ", "T");
  if (!texto) return "";
  if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/.test(texto) || instanteDeBrasilia(texto) === null) return null;
  return texto;
}

export type PedidoDeExibicao =
  | { ok: true; config: Record<string, unknown>; mudancas: string[]; imagemDoFundo: unknown | null }
  | { ok: false; erro: string };

/** Junta agendamento, dispositivo e fundo do pedido na configuração. */
export function aplicarPedidoDeExibicao(configDeHoje: Record<string, unknown>, args: Record<string, unknown>): PedidoDeExibicao {
  let config = { ...configDeHoje };
  const mudancas: string[] = [];
  let imagemDoFundo: unknown | null = null;

  if (args.agendamento !== undefined) {
    const pedido = (args.agendamento && typeof args.agendamento === "object" ? args.agendamento : {}) as Record<string, unknown>;
    const atual = lerAgendamento(config);
    const inicio = pedido.inicio === undefined ? atual.inicio : dataDoPedido(pedido.inicio);
    const fim = pedido.fim === undefined ? atual.fim : dataDoPedido(pedido.fim);
    if (inicio === null) return { ok: false, erro: 'agendamento.inicio: use "AAAA-MM-DD HH:MM" (hora de Brasília).' };
    if (fim === null) return { ok: false, erro: 'agendamento.fim: use "AAAA-MM-DD HH:MM" (hora de Brasília).' };
    config = comAgendamento(config, { inicio, fim });
    mudancas.push("agendamento");
  }

  if (args.dispositivo !== undefined) {
    const valor = String(args.dispositivo);
    config = comDispositivo(config, valor === "celular" ? "celular" : valor === "computador" ? "computador" : "todos");
    mudancas.push("aparelho");
  }

  if (args.fundo !== undefined) {
    const pedido = (args.fundo && typeof args.fundo === "object" ? args.fundo : {}) as Record<string, unknown>;
    const fundo: FundoDaSecao = { ...FUNDO_PADRAO, ...lerFundo(config) };
    if (pedido.tipo !== undefined) fundo.tipo = String(pedido.tipo) as TipoDeFundo;
    for (const campo of ["cor", "cor_2"] as const) {
      if (pedido[campo] === undefined) continue;
      const cor = hexValido(pedido[campo]);
      if (!cor) return { ok: false, erro: `fundo.${campo}: use a cor em hexadecimal, como #F4F0FF.` };
      fundo[campo] = cor;
    }
    if (pedido.angulo !== undefined) fundo.angulo = Math.round(Number(pedido.angulo)) || 0;
    if (pedido.escurecer !== undefined) fundo.escurecer = Math.min(80, Math.max(0, Math.round(Number(pedido.escurecer)) || 0));
    if (pedido.largura !== undefined) fundo.largura = pedido.largura === "contida" ? "contida" : "inteira";
    if (pedido.texto_claro !== undefined) fundo.texto_claro = pedido.texto_claro === true;
    for (const [campo, chave] of [
      ["espaco_acima", "acima"],
      ["espaco_abaixo", "abaixo"],
    ] as const) {
      if (pedido[campo] === undefined) continue;
      const valor = String(pedido[campo]);
      fundo[chave] = (valor === "p" || valor === "m" || valor === "g" ? valor : "") as Espaco;
    }
    if (pedido.imagem !== undefined && String(pedido.imagem).trim()) {
      imagemDoFundo = pedido.imagem;
      if (pedido.tipo === undefined) fundo.tipo = "imagem";
      /* O endereço entra quando a imagem subir; até lá, um marcador https. */
      fundo.imagem = "https://pendente.invalid/fundo";
    }
    if (fundo.tipo !== "imagem") imagemDoFundo = null;
    if (fundo.tipo === "imagem" && !imagemDoFundo && !/^https:\/\//i.test(fundo.imagem)) {
      return { ok: false, erro: 'fundo.imagem: mande a imagem do fundo (link https, "envio:..." ou "produto:<id>").' };
    }
    config = comFundo(config, fundo);
    mudancas.push("fundo");
  }

  const problema = problemaDaExibicao(config);
  if (problema) return { ok: false, erro: problema };
  return { ok: true, config, mudancas, imagemDoFundo };
}

/** Agendamento, aparelho e fundo em palavras, para a prévia e para ver_estrutura_da_loja. */
export function exibicaoEmPalavras(config: Record<string, unknown>): Record<string, unknown> {
  const saida: Record<string, unknown> = {};
  const agenda = lerAgendamento(config);
  if (agenda.inicio || agenda.fim) saida.agendamento = textoDoAgendamento(agenda);
  const dispositivo = lerDispositivo(config);
  if (dispositivo !== "todos") saida.aparelho = dispositivo === "celular" ? "só no celular" : "só no computador";
  const fundo = lerFundo(config);
  if (fundo.tipo !== "nenhum" || fundo.acima || fundo.abaixo) {
    saida.fundo = {
      tipo: fundo.tipo,
      ...(fundo.tipo === "cor" || fundo.tipo === "gradiente" ? { cor: fundo.cor } : {}),
      ...(fundo.tipo === "gradiente" ? { cor_2: fundo.cor_2, angulo: fundo.angulo } : {}),
      ...(fundo.tipo === "imagem" ? { imagem: fundo.imagem.startsWith("https://pendente.invalid") ? "nova (sobe ao gravar)" : fundo.imagem, escurecer: `${fundo.escurecer}%` } : {}),
      largura: fundo.largura,
      ...(fundo.acima ? { espaco_acima: fundo.acima } : {}),
      ...(fundo.abaixo ? { espaco_abaixo: fundo.abaixo } : {}),
    };
  }
  return saida;
}
