/**
 * A assinatura do Ktalogu vista pela empresa: que plano é, se está valendo e
 * até quando. Puro, para a tela e os testes lerem a mesma regra.
 *
 * Os campos vêm do `users_app` (plan, plan_name, status, expires_at), que é
 * quem o aviso do pagamento atualiza. O `subscription_status` das `companies`
 * só entra quando o `users_app` não diz nada — a rota já faz essa mistura.
 */

export type DadosDaAssinatura = {
  plan?: string | null;
  plan_name?: string | null;
  status?: string | null;
  expires_at?: string | null;
};

export type SituacaoDaAssinatura = "ativa" | "teste" | "expirada" | "inativa" | "sem-registro";

export type Assinatura = {
  /** "Anual", "Mensal", "Personalizado" ou o nome que veio do pagamento. */
  plano: string;
  situacao: SituacaoDaAssinatura;
  /** O painel abre? A mesma conta que o middleware faz. */
  ativa: boolean;
  venceEm: Date | null;
  /** Dias inteiros até vencer; 0 quando vence hoje; null sem data. */
  diasRestantes: number | null;
};

const NOME_DO_PLANO: Record<string, string> = {
  anual: "Anual",
  mensal: "Mensal",
  custom: "Personalizado",
};

const DIA = 24 * 60 * 60 * 1000;

function textoOuNulo(valor: unknown) {
  return typeof valor === "string" && valor.trim() ? valor.trim() : null;
}

export function nomeDoPlano(dados: DadosDaAssinatura | null | undefined) {
  const chave = textoOuNulo(dados?.plan)?.toLowerCase() ?? "";
  if (NOME_DO_PLANO[chave]) return NOME_DO_PLANO[chave];
  /* "Ktalogu - Anual" vira "Anual": o nome do produto já está no cabeçalho. */
  const nome = textoOuNulo(dados?.plan_name)?.replace(/^ktalogu\s*[-–—:]\s*/i, "");
  return nome || "Ktalogu";
}

/** A mesma leitura de status do middleware e do layout, num lugar só. */
export function statusLibera(status: string | null | undefined) {
  const normalizado = String(status ?? "").trim().toLowerCase();
  if (!normalizado) return { libera: false, teste: false };
  const teste = normalizado === "trial" || normalizado === "teste" || normalizado.startsWith("trial");
  const libera = teste || normalizado === "active" || normalizado === "paid" || normalizado.startsWith("ativ");
  return { libera, teste };
}

/**
 * `users_app.expires_at` é timestamp sem fuso, gravado em UTC, e chega como
 * "2026-10-01T02:59:59". Sem o "Z", o `new Date` lê como hora local: no
 * navegador em Brasília o vencimento aparecia 3 horas depois do real.
 */
export function lerVencimento(valor: unknown): Date | null {
  const bruto = textoOuNulo(valor);
  if (!bruto) return null;
  const comFuso = /[zZ]$|[+-]\d{2}:?\d{2}$/.test(bruto) || !/\d{2}:\d{2}/.test(bruto) ? bruto : `${bruto}Z`;
  const data = new Date(comFuso);
  return Number.isFinite(data.getTime()) ? data : null;
}

export function situacaoDaAssinatura(dados: DadosDaAssinatura | null | undefined, agora = new Date()): Assinatura {
  const plano = nomeDoPlano(dados);
  const status = textoOuNulo(dados?.status);
  const venceEm = lerVencimento(dados?.expires_at);

  if (!status && !venceEm) {
    return { plano, situacao: "sem-registro", ativa: false, venceEm: null, diasRestantes: null };
  }

  const expirada = venceEm ? venceEm.getTime() <= agora.getTime() : false;
  const { libera, teste } = statusLibera(status);
  const ativa = libera && !expirada;
  const diasRestantes = venceEm ? Math.max(0, Math.ceil((venceEm.getTime() - agora.getTime()) / DIA)) : null;

  const situacao: SituacaoDaAssinatura = ativa ? (teste ? "teste" : "ativa") : expirada ? "expirada" : "inativa";
  return { plano, situacao, ativa, venceEm, diasRestantes };
}

/**
 * Os dois jeitos de pagar: as duas ofertas do produto "Ktalogu Gestão -
 * Gráficas, Brindes e Personalizados" na Cakto (planos novos, 29/09/2026).
 * Os valores são os mesmos da página pública de preços. O link sem marca é o
 * de reserva; o painel pede a `/api/assinatura/link` o link com a marca da
 * empresa, que faz a compra cair na conta certa.
 */
export const PLANOS = {
  mensal: {
    chave: "mensal" as const,
    nome: "Mensal",
    preco: 69.9,
    periodo: "por mês",
    oferta: "b9jcqix",
    link: "https://pay.cakto.com.br/b9jcqix",
  },
  anual: {
    chave: "anual" as const,
    nome: "Anual",
    preco: 597,
    periodo: "por ano",
    oferta: "gvndd3a",
    link: "https://pay.cakto.com.br/gvndd3a",
  },
};

export type ChaveDoPlano = keyof typeof PLANOS;

export type EstadoDaConta = {
  /** De onde vem o acesso de hoje: plano novo (rota da Cakto), plano antigo, dado à mão, ou nada. */
  origem: "nova" | "antiga" | "manual" | "nenhuma";
  plano: ChaveDoPlano | null;
  ativa: boolean;
  renovaSozinha: boolean;
  diasRestantes: number;
};

export type AcaoDoPlano = {
  tipo: "assinar" | "migrar" | "upgrade" | "downgrade" | "downgrade-bloqueado" | "renovar-antes";
  podeComprar: boolean;
  botao: string;
  explicacao: string | null;
};

/** Trocar do anual para o mensal só nos últimos dias do anual (decisão de 29/09/2026). */
export const DIAS_PARA_TROCAR_PARA_O_MENSAL = 30;

function dias(n: number) {
  return `${n} ${n === 1 ? "dia" : "dias"}`;
}

/**
 * O que o botão de pagar faz para esta conta e este plano escolhido. Toda
 * compra com dias sobrando soma esses dias (crédito) e cancela a assinatura
 * anterior na Cakto; o que muda aqui é o que é permitido e como é dito.
 */
export function acaoDoPlano(conta: EstadoDaConta, escolhido: ChaveDoPlano): AcaoDoPlano {
  const nome = PLANOS[escolhido].nome.toLowerCase();
  const sobra = conta.ativa ? Math.max(0, conta.diasRestantes) : 0;
  const somados = sobra ? `Os ${dias(sobra)} que você ainda tem são somados ao novo período.` : null;

  if (!conta.ativa || conta.origem === "nenhuma") {
    return { tipo: "assinar", podeComprar: true, botao: `Assinar o ${nome}`, explicacao: null };
  }

  if (conta.plano === "anual" && escolhido === "mensal" && sobra > DIAS_PARA_TROCAR_PARA_O_MENSAL) {
    return {
      tipo: "downgrade-bloqueado",
      podeComprar: false,
      botao: "Trocar para o mensal",
      explicacao: `A troca para o mensal fica disponível nos últimos ${DIAS_PARA_TROCAR_PARA_O_MENSAL} dias do seu anual. Até lá, seu acesso segue normal.`,
    };
  }

  if (conta.origem !== "nova") {
    const antigo = conta.origem === "antiga" ? "Seu plano atual, com o preço antigo, é encerrado" : "Seu acesso atual é encerrado";
    return {
      tipo: "migrar",
      podeComprar: true,
      botao: `Assinar o ${nome}`,
      explicacao: `${antigo} e passa a valer o novo.${somados ? ` ${somados}` : ""}`,
    };
  }

  /* Mesmo plano: pagar antes é vender mais um período, nunca é bloqueado. O
     tempo que ainda falta não se perde: o novo período entra depois dele. */
  if (conta.plano === escolhido) {
    const periodo = escolhido === "anual" ? "um ano" : "um mês";
    const automatica = conta.renovaSozinha ? " A renovação automática continua, contando a partir de hoje." : "";
    return {
      tipo: "renovar-antes",
      podeComprar: true,
      botao: escolhido === "anual" ? "Renovar por mais um ano" : "Pagar mais um mês",
      explicacao: `Você paga agora e ganha mais ${periodo}, somado aos ${dias(sobra)} que ainda tem.${automatica}`,
    };
  }

  if (conta.plano === "mensal" && escolhido === "anual") {
    return {
      tipo: "upgrade",
      podeComprar: true,
      botao: "⚡ Fazer upgrade para o anual",
      explicacao: `${somados ?? ""}${somados ? " " : ""}O mensal é cancelado sozinho: nada de cobrança em dobro.`,
    };
  }

  return {
    tipo: "downgrade",
    podeComprar: true,
    botao: "Trocar para o mensal",
    explicacao: `${somados ?? ""}${somados ? " " : ""}O anual é cancelado sozinho: nada de cobrança em dobro.`,
  };
}

const centavos = (valor: number) => Math.round(valor * 100) / 100;

/* 12 × 69,90 = 838,80, e 838,80 − 597 = 241,80: a economia sem inventar número. */
export const ANO_NO_MENSAL = centavos(PLANOS.mensal.preco * 12);
export const ECONOMIA_DO_ANUAL = centavos(ANO_NO_MENSAL - PLANOS.anual.preco);
export const ECONOMIA_DO_ANUAL_PORCENTO = Math.round((ECONOMIA_DO_ANUAL / ANO_NO_MENSAL) * 100);
export const ANUAL_POR_MES = centavos(PLANOS.anual.preco / 12);
