"use client";

import { useMemo, useState, type ReactNode } from "react";

import type { PainelFiscal } from "@/lib/fiscal-owner";

import type { Avisar } from "./painel-client";
import {
  BOTAO_PRIMARIO,
  BOTAO_SECUNDARIO,
  CLASSE_DO_CAMPO,
  Campo,
  dataEHora,
  decimalDoCampo,
  decimalParaCampo,
  Interruptor,
  moeda,
  pedir,
  Recado,
} from "./ui";

type Formulario = {
  vendas_abertas: boolean;
  limite_emissores: string;
  notas_teste_por_mes: string;
  aviso_saldo_baixo: string;
  plano_spedy_notas: string;
  plano_spedy_valor: string;
  plano_spedy_nota_excedente: string;
};

function paraFormulario(regras: PainelFiscal["regras"]): Formulario {
  return {
    vendas_abertas: regras.vendas_abertas,
    limite_emissores: String(regras.limite_emissores),
    notas_teste_por_mes: String(regras.notas_teste_por_mes),
    aviso_saldo_baixo: String(regras.aviso_saldo_baixo),
    plano_spedy_notas: String(regras.plano_spedy_notas),
    plano_spedy_valor: decimalParaCampo(regras.plano_spedy_valor),
    plano_spedy_nota_excedente: decimalParaCampo(regras.plano_spedy_nota_excedente, 3),
  };
}

const soDigitos = (valor: string, maximo = 7) => valor.replace(/\D/g, "").slice(0, maximo);
const soDecimal = (valor: string) => valor.replace(/[^\d.,]/g, "").slice(0, 12);

export default function AbaRegras({ painel, aoMudar, avisar }: { painel: PainelFiscal; aoMudar: () => Promise<void>; avisar: Avisar }) {
  const original = useMemo(() => paraFormulario(painel.regras), [painel.regras]);
  const [form, setForm] = useState<Formulario>(original);
  const [salvando, setSalvando] = useState(false);
  const [erro, setErro] = useState<string | null>(null);

  const mudou = (Object.keys(original) as Array<keyof Formulario>).some((chave) => {
    if (chave === "plano_spedy_valor" || chave === "plano_spedy_nota_excedente") {
      return decimalDoCampo(form[chave]) !== decimalDoCampo(original[chave]);
    }
    return form[chave] !== original[chave];
  });

  const empresasAcimaDoLimite = painel.resumo.vagasUsadas > Number(form.limite_emissores || 0);

  function mudar<K extends keyof Formulario>(chave: K, valor: Formulario[K]) {
    setErro(null);
    setForm((antes) => ({ ...antes, [chave]: valor }));
  }

  async function salvar() {
    const inteiros: Array<[keyof Formulario, string]> = [
      ["limite_emissores", "Vagas de empresas emissoras"],
      ["notas_teste_por_mes", "Notas de teste por mês"],
      ["aviso_saldo_baixo", "Aviso de saldo baixo"],
      ["plano_spedy_notas", "Notas do plano da Spedy"],
    ];
    for (const [chave, rotulo] of inteiros) {
      if (String(form[chave]).trim() === "") return setErro(`${rotulo}: preencha com um número.`);
    }
    for (const [chave, rotulo] of [
      ["plano_spedy_valor", "Valor do plano"],
      ["plano_spedy_nota_excedente", "Nota excedente"],
    ] as Array<[keyof Formulario, string]>) {
      const valor = decimalDoCampo(String(form[chave]));
      if (!Number.isFinite(valor) || valor < 0) return setErro(`${rotulo}: valor inválido.`);
    }

    setSalvando(true);
    setErro(null);
    try {
      await pedir("/api/fiscal/regras", {
        method: "PUT",
        body: JSON.stringify({
          vendas_abertas: form.vendas_abertas,
          limite_emissores: Number(form.limite_emissores),
          notas_teste_por_mes: Number(form.notas_teste_por_mes),
          aviso_saldo_baixo: Number(form.aviso_saldo_baixo),
          plano_spedy_notas: Number(form.plano_spedy_notas),
          plano_spedy_valor: form.plano_spedy_valor,
          plano_spedy_nota_excedente: form.plano_spedy_nota_excedente,
        }),
      });
      await aoMudar();
      avisar("ok", "Regras salvas. Valem na hora para todas as empresas.");
    } catch (falha) {
      setErro(falha instanceof Error ? falha.message : "Não foi possível salvar as regras.");
    } finally {
      setSalvando(false);
    }
  }

  return (
    <form
      className="grid grid-cols-1 gap-4"
      onSubmit={(evento) => {
        evento.preventDefault();
        if (mudou && !salvando) void salvar();
      }}
    >
      <div>
        <h2 className="text-base font-semibold text-slate-900">Regras da plataforma</h2>
        <p className="mt-0.5 text-sm text-slate-500">Valem para produção e sandbox, e para todas as empresas ao mesmo tempo.</p>
      </div>

      <Bloco titulo="Venda de pacotes">
        <div className="flex items-start justify-between gap-6">
          <div>
            <p className="text-sm font-medium text-slate-800">Vendas abertas</p>
            <p className="mt-0.5 max-w-xl text-xs leading-5 text-slate-500">
              Desligado, ninguém consegue comprar pacote novo. As notas já compradas no mês continuam valendo até a virada.
            </p>
          </div>
          <Interruptor ligado={form.vendas_abertas} rotulo="Vendas abertas" aoMudar={(ligado) => mudar("vendas_abertas", ligado)} />
        </div>
      </Bloco>

      <Bloco titulo="Limites" descricao="O que cada empresa pode usar e quando ela é avisada.">
        <div className="grid gap-5 md:grid-cols-3">
          <Campo
            rotulo="Vagas de empresas emissoras"
            ajuda={
              empresasAcimaDoLimite
                ? `Já há ${painel.resumo.vagasUsadas} empresas na Spedy neste ambiente: elas continuam, só não entra nenhuma nova.`
                : "CNPJs que podem ser cadastrados na Spedy. O plano 1k aceita até 30."
            }
          >
            {(id) => (
              <input
                id={id}
                value={form.limite_emissores}
                onChange={(e) => mudar("limite_emissores", soDigitos(e.target.value, 6))}
                inputMode="numeric"
                className={`${CLASSE_DO_CAMPO} tabular-nums`}
              />
            )}
          </Campo>
          <Campo rotulo="Notas de teste por mês" ajuda="Por empresa, em homologação no servidor de produção. Não gastam pacote.">
            {(id) => (
              <input
                id={id}
                value={form.notas_teste_por_mes}
                onChange={(e) => mudar("notas_teste_por_mes", soDigitos(e.target.value, 6))}
                inputMode="numeric"
                className={`${CLASSE_DO_CAMPO} tabular-nums`}
              />
            )}
          </Campo>
          <Campo rotulo="Aviso de saldo baixo" ajuda="A empresa é alertada quando sobrarem esta quantidade de notas ou menos.">
            {(id) => (
              <input
                id={id}
                value={form.aviso_saldo_baixo}
                onChange={(e) => mudar("aviso_saldo_baixo", soDigitos(e.target.value, 6))}
                inputMode="numeric"
                className={`${CLASSE_DO_CAMPO} tabular-nums`}
              />
            )}
          </Campo>
        </div>
      </Bloco>

      <Bloco titulo="Plano da Spedy" descricao="Só para calcular custo e margem neste painel. Não muda nada na Spedy.">
        <div className="grid gap-5 md:grid-cols-3">
          <Campo rotulo="Notas incluídas por mês">
            {(id) => (
              <input
                id={id}
                value={form.plano_spedy_notas}
                onChange={(e) => mudar("plano_spedy_notas", soDigitos(e.target.value))}
                inputMode="numeric"
                className={`${CLASSE_DO_CAMPO} tabular-nums`}
              />
            )}
          </Campo>
          <Campo rotulo="Valor mensal (R$)">
            {(id) => (
              <input
                id={id}
                value={form.plano_spedy_valor}
                onChange={(e) => mudar("plano_spedy_valor", soDecimal(e.target.value))}
                onBlur={() => {
                  const valor = decimalDoCampo(form.plano_spedy_valor);
                  if (Number.isFinite(valor)) mudar("plano_spedy_valor", decimalParaCampo(Math.round(valor * 100) / 100));
                }}
                inputMode="decimal"
                className={`${CLASSE_DO_CAMPO} tabular-nums`}
              />
            )}
          </Campo>
          <Campo
            rotulo="Nota excedente (R$)"
            ajuda={(() => {
              const notas = Number(form.plano_spedy_notas);
              const valor = decimalDoCampo(form.plano_spedy_valor);
              return notas > 0 && Number.isFinite(valor) ? `Dentro do plano, cada nota sai a ${moeda(valor / notas, 3)}.` : undefined;
            })()}
          >
            {(id) => (
              <input
                id={id}
                value={form.plano_spedy_nota_excedente}
                onChange={(e) => mudar("plano_spedy_nota_excedente", soDecimal(e.target.value))}
                inputMode="decimal"
                className={`${CLASSE_DO_CAMPO} tabular-nums`}
              />
            )}
          </Campo>
        </div>
      </Bloco>

      {erro ? <Recado tom="erro">{erro}</Recado> : null}

      <div
        className={`flex flex-wrap items-center justify-between gap-3 rounded-2xl border px-5 py-3 ${
          mudou ? "sticky bottom-4 z-10 border-slate-300 bg-white/95 shadow-lg backdrop-blur" : "border-slate-200 bg-white shadow-sm"
        }`}
      >
        <p className="text-xs text-slate-500">
          {mudou
            ? "Há alterações não salvas."
            : painel.regras.updated_by
              ? `Última alteração em ${dataEHora(painel.regras.updated_at)} por ${painel.regras.updated_by}.`
              : "Valores padrão do plano Spedy API 1k."}
        </p>
        <div className="flex gap-2">
          {mudou ? (
            <button
              type="button"
              onClick={() => {
                setForm(original);
                setErro(null);
              }}
              disabled={salvando}
              className={BOTAO_SECUNDARIO}
            >
              Desfazer
            </button>
          ) : null}
          <button type="submit" disabled={!mudou || salvando} className={BOTAO_PRIMARIO}>
            {salvando ? "Salvando…" : "Salvar regras"}
          </button>
        </div>
      </div>
    </form>
  );
}

function Bloco({ titulo, descricao, children }: { titulo: string; descricao?: string; children: ReactNode }) {
  return (
    <section className="rounded-2xl border border-slate-200 bg-white p-5 shadow-sm sm:p-6">
      <h3 className="text-sm font-semibold text-slate-900">{titulo}</h3>
      {descricao ? <p className="mt-0.5 text-xs text-slate-500">{descricao}</p> : null}
      <div className="mt-4">{children}</div>
    </section>
  );
}
