﻿import * as kv from "./kv_store.tsx";

export interface RegraDescontoValidade {
  diasLimite: number;
  desconto: number;
  etiqueta: string;
}

export type FaixaValidadePosCodigo =
  | "expirado"
  | "uma_semana"
  | "duas_semanas"
  | "um_mes"
  | "dois_meses";

export interface PoliticaFaixaValidadePos {
  codigo: FaixaValidadePosCodigo;
  titulo: string;
  diasMin?: number;
  diasMax?: number;
  mostrarNoPos: boolean;
  permitirVenda: boolean;
  exigirSupervisor: boolean;
  desconto: number;
  etiqueta: string;
}

export interface PoliticaPersonalizadaPos {
  id: string;
  titulo: string;
  ativo: boolean;
  tipo: "validade" | "promocao";
  diasMin?: number;
  diasMax?: number;
  dataInicio?: string;
  dataFim?: string;
  criterioArtigo: "todos" | "codigo" | "nome" | "tipo";
  termoArtigo?: string;
  mostrarNoPos: boolean;
  permitirVenda: boolean;
  exigirSupervisor: boolean;
  desconto: number;
  etiqueta: string;
}

export type LarguraPapelPosMm = 58 | 80;

export interface PosValidadeConfig {
  empresaId: string;
  ativo: boolean;
  aplicarDescontoAutomatico: boolean;
  exigirSupervisorParaRemoverDesconto: boolean;
  bloquearExpirado: boolean;
  diasAlertaCritico: number;
  diasAlertaAtencao: number;
  diasMonitorizacao: number;
  regrasPromocao: RegraDescontoValidade[];
  politicasFaixa: PoliticaFaixaValidadePos[];
  politicasCustomizadas: PoliticaPersonalizadaPos[];
  // ✅ Largura do papel da impressora de recibos do POS (58mm ou 80mm).
  // Antes fixa em 80mm no CSS de impressao; agora configuravel por empresa,
  // ja que cada terminal pode ter uma impressora termica diferente.
  larguraPapelMm: LarguraPapelPosMm;
  atualizadoEm: string;
}

const POS_VALIDADE_PREFIX = "pos_validade_config:";

export function obterPoliticasFaixaPadrao(): PoliticaFaixaValidadePos[] {
  return [
    {
      codigo: "expirado",
      titulo: "Ja expirado",
      diasMax: -1,
      mostrarNoPos: false,
      permitirVenda: false,
      exigirSupervisor: true,
      desconto: 0,
      etiqueta: "Expirado",
    },
    {
      codigo: "uma_semana",
      titulo: "Expira em 1 semana",
      diasMin: 0,
      diasMax: 7,
      mostrarNoPos: true,
      permitirVenda: true,
      exigirSupervisor: true,
      desconto: 0,
      etiqueta: "1 semana",
    },
    {
      codigo: "duas_semanas",
      titulo: "Expira em 2 semanas",
      diasMin: 8,
      diasMax: 14,
      mostrarNoPos: true,
      permitirVenda: true,
      exigirSupervisor: true,
      desconto: 0,
      etiqueta: "2 semanas",
    },
    {
      codigo: "um_mes",
      titulo: "Expira em 1 mes",
      diasMin: 15,
      diasMax: 30,
      mostrarNoPos: true,
      permitirVenda: true,
      exigirSupervisor: false,
      desconto: 0,
      etiqueta: "1 mes",
    },
    {
      codigo: "dois_meses",
      titulo: "Expira em 2 meses",
      diasMin: 31,
      diasMax: 60,
      mostrarNoPos: true,
      permitirVenda: true,
      exigirSupervisor: false,
      desconto: 0,
      etiqueta: "2 meses",
    },
  ];
}

export function obterConfiguracaoPosValidadePadrao(empresaId: string): PosValidadeConfig {
  return {
    empresaId,
    ativo: true,
    aplicarDescontoAutomatico: false,
    exigirSupervisorParaRemoverDesconto: true,
    bloquearExpirado: true,
    diasAlertaCritico: 3,
    diasAlertaAtencao: 7,
    diasMonitorizacao: 60,
    regrasPromocao: [],
    politicasFaixa: obterPoliticasFaixaPadrao(),
    politicasCustomizadas: [],
    larguraPapelMm: 80,
    atualizadoEm: new Date().toISOString(),
  };
}

function normalizarLarguraPapel(valor?: unknown): LarguraPapelPosMm {
  return Number(valor) === 58 ? 58 : 80;
}

function normalizarRegras(regras?: RegraDescontoValidade[]): RegraDescontoValidade[] {
  return (regras || [])
    .filter((regra) =>
      Number.isFinite(regra?.diasLimite) &&
      Number.isFinite(regra?.desconto) &&
      regra.diasLimite >= 0 &&
      regra.desconto >= 0,
    )
    .map((regra) => ({
      diasLimite: Number(regra.diasLimite),
      desconto: Number(regra.desconto),
      etiqueta: regra.etiqueta?.trim() || `Ate ${regra.diasLimite} dias`,
    }))
    .sort((a, b) => a.diasLimite - b.diasLimite);
}

function normalizarPoliticasFaixa(politicas?: PoliticaFaixaValidadePos[]): PoliticaFaixaValidadePos[] {
  const padrao = obterPoliticasFaixaPadrao();
  const mapa = new Map(
    (politicas || [])
      .filter((politica) => politica?.codigo)
      .map((politica) => [
        politica.codigo,
        {
          ...politica,
          desconto: Number.isFinite(politica.desconto) ? Number(politica.desconto) : 0,
          mostrarNoPos: politica.mostrarNoPos !== false,
          permitirVenda: politica.permitirVenda !== false,
          exigirSupervisor: Boolean(politica.exigirSupervisor),
          etiqueta: politica.etiqueta?.trim() || politica.titulo || politica.codigo,
        },
      ]),
  );

  return padrao.map((item) => ({
    ...item,
    ...(mapa.get(item.codigo) || {}),
    codigo: item.codigo,
    titulo: mapa.get(item.codigo)?.titulo || item.titulo,
    diasMin: mapa.get(item.codigo)?.diasMin ?? item.diasMin,
    diasMax: mapa.get(item.codigo)?.diasMax ?? item.diasMax,
  }));
}

function normalizarPoliticasCustomizadas(politicas?: PoliticaPersonalizadaPos[]): PoliticaPersonalizadaPos[] {
  return (politicas || [])
    .filter((politica) => politica?.id && politica?.titulo)
    .map((politica) => ({
      id: politica.id,
      titulo: politica.titulo?.trim() || "Nova politica",
      ativo: politica.ativo !== false,
      tipo: politica.tipo === "promocao" ? "promocao" : "validade",
      diasMin: Number.isFinite(politica.diasMin) ? Number(politica.diasMin) : undefined,
      diasMax: Number.isFinite(politica.diasMax) ? Number(politica.diasMax) : undefined,
      dataInicio: politica.dataInicio || undefined,
      dataFim: politica.dataFim || undefined,
      criterioArtigo: ["codigo", "nome", "tipo"].includes(politica.criterioArtigo) ? politica.criterioArtigo : "todos",
      termoArtigo: politica.termoArtigo?.trim() || "",
      mostrarNoPos: politica.mostrarNoPos !== false,
      permitirVenda: politica.permitirVenda !== false,
      exigirSupervisor: Boolean(politica.exigirSupervisor),
      desconto: Number.isFinite(politica.desconto) ? Math.max(0, Number(politica.desconto)) : 0,
      etiqueta: politica.etiqueta?.trim() || politica.titulo?.trim() || "Politica personalizada",
    }));
}

export async function obterConfiguracaoPosValidade(empresaId: string): Promise<PosValidadeConfig> {
  const chave = `${POS_VALIDADE_PREFIX}${empresaId}`;
  const guardado = await kv.get<Partial<PosValidadeConfig>>(chave);
  const padrao = obterConfiguracaoPosValidadePadrao(empresaId);

  if (!guardado) {
    return padrao;
  }

  return {
    ...padrao,
    ...guardado,
    empresaId,
    regrasPromocao: normalizarRegras(guardado.regrasPromocao) || padrao.regrasPromocao,
    politicasFaixa: normalizarPoliticasFaixa(guardado.politicasFaixa),
    politicasCustomizadas: normalizarPoliticasCustomizadas(guardado.politicasCustomizadas),
    larguraPapelMm: normalizarLarguraPapel(guardado.larguraPapelMm),
    atualizadoEm: guardado.atualizadoEm || padrao.atualizadoEm,
  };
}

export async function salvarConfiguracaoPosValidade(
  empresaId: string,
  dados: Partial<PosValidadeConfig>,
): Promise<PosValidadeConfig> {
  const atual = await obterConfiguracaoPosValidade(empresaId);

  const configuracao: PosValidadeConfig = {
    ...atual,
    ...dados,
    empresaId,
    regrasPromocao: normalizarRegras(dados.regrasPromocao || atual.regrasPromocao),
    politicasFaixa: normalizarPoliticasFaixa(dados.politicasFaixa || atual.politicasFaixa),
    politicasCustomizadas: normalizarPoliticasCustomizadas(dados.politicasCustomizadas || atual.politicasCustomizadas),
    larguraPapelMm: normalizarLarguraPapel(dados.larguraPapelMm ?? atual.larguraPapelMm),
    atualizadoEm: new Date().toISOString(),
  };

  await kv.set(`${POS_VALIDADE_PREFIX}${empresaId}`, configuracao);
  return configuracao;
}
