"use client";

import { useEffect, useMemo, useRef, useState, type ReactNode } from "react";
import { AnimatePresence, motion } from "framer-motion";
import {
  CalendarClock,
  Check,
  Copy,
  Eye,
  LayoutGrid,
  Loader2,
  Percent,
  QrCode,
  Shuffle,
  Sparkles,
  Ticket,
  Truck,
  Users,
  Wallet,
  Wand2,
  X,
} from "lucide-react";
import { Switch } from "@/components/ui/switch";
import CaixaDeConfirmacao from "@/components/ui/caixa-de-confirmacao";
import { CampoDecimal } from "@/components/ui/campo-decimal";
import { ChaveDeAjuste, EscolhaDeAjuste, SecaoDeAjustes } from "@/components/ui/folha-de-ajustes";
import {
  avaliarCupom,
  condicoesDoCupom,
  ESTADOS,
  fraseDoCupom,
  gerarCodigo,
  nomeDoCupom,
  reais,
  rotuloDoBeneficio,
  type NomesDoCupom,
} from "@/lib/regras-do-cupom";
import { EscolhaDeVarios, type ItemParaEscolher } from "./escolha-de-varios";
import { cupomDoFormulario, erroDoFormulario, formularioVazio, type FormularioDoCupom } from "./formulario";

/*
  A gaveta do cupom: criar e editar.

  No computador entra pela direita, com o "como o cliente vê" preso ao lado;
  no celular sobe de baixo, quase da altura da tela, com a prévia no topo.
  As seções seguem a ordem em que a pessoa pensa o cupom: o que é, onde
  vale, quem pode usar, até quando, como entra no carrinho e se aparece na
  loja. A barra de atalhos no topo leva a cada uma.
*/

const SECOES = [
  { id: "cupom-sec-codigo", titulo: "Código e tipo", Icone: Ticket },
  { id: "cupom-sec-onde", titulo: "Onde vale", Icone: LayoutGrid },
  { id: "cupom-sec-quem", titulo: "Quem pode usar", Icone: Users },
  { id: "cupom-sec-limites", titulo: "Limites e validade", Icone: CalendarClock },
  { id: "cupom-sec-aplicar", titulo: "Como aplicar", Icone: Wand2 },
  { id: "cupom-sec-visivel", titulo: "Visibilidade", Icone: Eye },
] as const;

const DIAS_CURTOS = [
  { dia: 1, rotulo: "Seg" },
  { dia: 2, rotulo: "Ter" },
  { dia: 3, rotulo: "Qua" },
  { dia: 4, rotulo: "Qui" },
  { dia: 5, rotulo: "Sex" },
  { dia: 6, rotulo: "Sáb" },
  { dia: 0, rotulo: "Dom" },
];

export type ResultadoDoSalvar = { ok: true } | { ok: false; erro: string };

export function EditorDoCupom({
  aberto,
  id,
  inicial,
  codigoOriginal,
  categorias,
  produtos,
  buscarClientes,
  nomesDosClientes,
  linkDoCupom,
  aoAbrirQr,
  aoFechar,
  aoSalvar,
}: {
  aberto: boolean;
  /** Null = cupom novo. */
  id: string | null;
  inicial: FormularioDoCupom | null;
  codigoOriginal: string | null;
  categorias: ItemParaEscolher[];
  produtos: ItemParaEscolher[];
  buscarClientes: (termo: string) => Promise<ItemParaEscolher[]>;
  nomesDosClientes: Record<string, string>;
  linkDoCupom: (codigo: string) => string;
  aoAbrirQr: (codigo: string) => void;
  aoFechar: () => void;
  aoSalvar: (formulario: FormularioDoCupom) => Promise<ResultadoDoSalvar>;
}) {
  const [f, setF] = useState<FormularioDoCupom>(() => inicial ?? formularioVazio());
  const [salvando, setSalvando] = useState(false);
  const [erro, setErro] = useState("");
  const [atual, setAtual] = useState<string>(SECOES[0].id);
  const [copiado, setCopiado] = useState(false);
  const corpo = useRef<HTMLDivElement>(null);
  const [mostrarExclusoes, setMostrarExclusoes] = useState(false);
  /* No computador a gaveta entra pela direita; no celular, sobe de baixo. */
  const [noComputador, setNoComputador] = useState(false);
  useEffect(() => {
    const consulta = window.matchMedia("(min-width: 768px)");
    const ler = () => setNoComputador(consulta.matches);
    ler();
    consulta.addEventListener("change", ler);
    return () => consulta.removeEventListener("change", ler);
  }, []);

  useEffect(() => {
    if (!aberto) return;
    setF(inicial ?? formularioVazio());
    setErro("");
    setSalvando(false);
    setAtual(SECOES[0].id);
    setMostrarExclusoes(Boolean(inicial && (inicial.exclude_category_ids.length || inicial.exclude_product_ids.length)));
    corpo.current?.scrollTo({ top: 0 });
  }, [aberto, inicial]);

  /* Fechar com mudança não salva pergunta antes: um Esc ou um clique fora
     não joga fora o cupom montado. */
  const [perguntarSaida, setPerguntarSaida] = useState(false);
  const mexido = aberto && JSON.stringify(f) !== JSON.stringify(inicial ?? formularioVazio());
  const pedirParaFechar = () => {
    if (salvando || perguntarSaida) return;
    if (mexido) setPerguntarSaida(true);
    else aoFechar();
  };
  const pedirParaFecharRef = useRef(pedirParaFechar);
  pedirParaFecharRef.current = pedirParaFechar;

  useEffect(() => {
    if (!aberto) return;
    const aoTeclar = (e: KeyboardEvent) => {
      if (e.key !== "Escape") return;
      /* Com uma lista de escolha aberta, o Esc fecha só a lista. */
      if (document.querySelector('[role="dialog"] [data-lista-aberta="sim"]')) return;
      pedirParaFecharRef.current();
    };
    window.addEventListener("keydown", aoTeclar);
    const corpoDaPagina = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    return () => {
      window.removeEventListener("keydown", aoTeclar);
      document.body.style.overflow = corpoDaPagina;
    };
  }, [aberto]);

  useEffect(() => {
    if (!aberto) setPerguntarSaida(false);
  }, [aberto]);

  /* A seção atual, pela rolagem do corpo da gaveta. */
  useEffect(() => {
    const raiz = corpo.current;
    if (!aberto || !raiz || typeof IntersectionObserver === "undefined") return;
    const visiveis = new Set<string>();
    const obs = new IntersectionObserver(
      (entradas) => {
        for (const e of entradas) {
          if (e.isIntersecting) visiveis.add(e.target.id);
          else visiveis.delete(e.target.id);
        }
        const primeira = SECOES.find((s) => visiveis.has(s.id));
        if (primeira) setAtual(primeira.id);
      },
      { root: raiz, rootMargin: "0px 0px -65% 0px", threshold: 0 }
    );
    const t = window.setTimeout(() => {
      for (const s of SECOES) {
        const alvo = document.getElementById(s.id);
        if (alvo) obs.observe(alvo);
      }
    }, 50);
    return () => {
      window.clearTimeout(t);
      obs.disconnect();
    };
  }, [aberto]);

  const mudar = (parcial: Partial<FormularioDoCupom>) => {
    setF((antes) => ({ ...antes, ...parcial }));
    setErro("");
  };

  const nomes: NomesDoCupom = useMemo(
    () => ({
      categorias: Object.fromEntries(categorias.map((c) => [c.id, c.nome])),
      produtos: Object.fromEntries(produtos.map((p) => [p.id, p.nome])),
    }),
    [categorias, produtos]
  );
  const cupom = useMemo(() => cupomDoFormulario(f), [f]);
  const problema = erroDoFormulario(f, codigoOriginal);

  const irPara = (secao: string) => {
    setAtual(secao);
    document.getElementById(secao)?.scrollIntoView({ behavior: "smooth", block: "start" });
  };

  const salvar = async () => {
    if (problema) {
      setErro(problema);
      return;
    }
    setSalvando(true);
    const r = await aoSalvar(f);
    setSalvando(false);
    if (!r.ok) setErro(r.erro);
  };

  const copiarLink = async () => {
    try {
      await navigator.clipboard.writeText(linkDoCupom(f.code.trim().toUpperCase()));
      setCopiado(true);
      window.setTimeout(() => setCopiado(false), 1600);
    } catch {
      setErro("Não deu para copiar: selecione o link e copie.");
    }
  };

  const codigoDoLink = f.code.trim().toUpperCase();

  return (
    <>
    <AnimatePresence>
      {aberto ? (
        <motion.div
          key="fundo"
          className="fixed inset-0 z-[120] bg-[rgba(12,8,24,0.42)] backdrop-blur-[2px]"
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          onClick={pedirParaFechar}
        >
          <motion.aside
            role="dialog"
            aria-modal="true"
            aria-label={id ? `Editar cupom ${codigoOriginal ?? ""}` : "Novo cupom"}
            onClick={(e) => e.stopPropagation()}
            className="absolute inset-x-0 bottom-0 flex h-[94dvh] flex-col overflow-hidden rounded-t-[22px] bg-[var(--ks-color-bg-body)] shadow-[var(--ks-shadow-overlay)] md:inset-y-0 md:left-auto md:right-0 md:h-full md:w-[min(1080px,100vw)] md:rounded-none md:rounded-l-[22px]"
            initial={noComputador ? { x: "100%" } : { y: "100%" }}
            animate={{ x: 0, y: 0 }}
            exit={noComputador ? { x: "100%" } : { y: "100%" }}
            transition={{ type: "spring", stiffness: 360, damping: 36 }}
          >
            {/* Cabeçalho e atalhos das seções */}
            <header className="shrink-0 border-b border-[var(--ks-color-border-subtle)] bg-white">
              <div className="mx-auto mt-2 h-1.5 w-10 rounded-full bg-[var(--ks-n-200)] md:hidden" aria-hidden />
              <div className="flex items-center justify-between gap-3 px-5 pb-2 pt-3 sm:px-6 md:pt-5">
                <div className="min-w-0">
                  <p className="text-[11px] font-bold uppercase tracking-[0.14em] text-[var(--ks-color-text-soft)]">{id ? "Editar cupom" : "Novo cupom"}</p>
                  <h2 className="truncate text-lg font-extrabold tracking-tight text-[var(--ks-color-text-primary)]">
                    {f.code.trim() ? f.code.trim().toUpperCase() : "Sem código ainda"}
                  </h2>
                </div>
                <button type="button" onClick={pedirParaFechar} className="ks-icon-button" aria-label="Fechar">
                  <X size={18} />
                </button>
              </div>
              <nav aria-label="Seções do cupom" className="flex gap-1 overflow-x-auto px-4 pb-2.5 sm:px-5">
                {SECOES.map(({ id: secao, titulo, Icone }) => {
                  const ativa = atual === secao;
                  return (
                    <button
                      key={secao}
                      type="button"
                      onClick={() => irPara(secao)}
                      aria-current={ativa ? "location" : undefined}
                      className={`flex shrink-0 items-center gap-1.5 rounded-full px-3 py-1.5 text-[12.5px] font-semibold transition-colors ${
                        ativa ? "bg-[var(--ks-brand-600)] text-white" : "text-[var(--ks-color-text-secondary)] hover:bg-[var(--ks-color-bg-hover)]"
                      }`}
                    >
                      <Icone size={14} />
                      {titulo}
                    </button>
                  );
                })}
              </nav>
            </header>

            <div ref={corpo} className="min-h-0 flex-1 overflow-y-auto">
              <div className="grid gap-5 p-4 sm:p-6 xl:grid-cols-[minmax(0,1fr)_340px] xl:items-start">
                <div className="hidden xl:sticky xl:top-0 xl:order-2 xl:block">
                  <ComoOClienteVe f={f} nomes={nomes} />
                </div>
                <div className="xl:hidden">
                  <PreviaCompacta f={f} nomes={nomes} />
                </div>

                <div className="min-w-0 overflow-hidden rounded-2xl border border-[var(--ks-color-border-subtle)] bg-white shadow-[var(--ks-shadow-subtle)] xl:order-1">
                  {/* 1. Código e tipo */}
                  <SecaoDeAjustes id="cupom-sec-codigo" Icone={Ticket} titulo="Código e tipo" texto="O que o cliente digita e o que ele ganha.">
                    <Campo rotulo="Código" ajuda="Letras, números e hífen. O cliente digita sem diferença de maiúscula.">
                      <div className="flex gap-2">
                        <input
                          value={f.code}
                          onChange={(e) => mudar({ code: e.target.value.toUpperCase().replace(/\s+/g, codigoOriginal?.includes(" ") ? " " : "") })}
                          placeholder="BEMVINDO10"
                          maxLength={30}
                          autoCapitalize="characters"
                          spellCheck={false}
                          className="ks-field font-mono text-[15px] font-bold tracking-[0.08em]"
                          aria-label="Código do cupom"
                        />
                        <button
                          type="button"
                          onClick={() => mudar({ code: gerarCodigo(f.name || "") })}
                          className="ks-button ks-button-secondary shrink-0"
                          title="Gerar um código aleatório"
                        >
                          <Shuffle size={15} /> <span className="hidden sm:inline">Gerar</span>
                        </button>
                      </div>
                    </Campo>
                    <Campo rotulo="Nome que o cliente vê" ajuda='Opcional. No automático aparece "Desconto aplicado: Semana da caneca".'>
                      <input
                        value={f.name}
                        onChange={(e) => mudar({ name: e.target.value.slice(0, 80) })}
                        placeholder="Ex.: Semana da caneca"
                        className="ks-field"
                        aria-label="Nome do cupom"
                      />
                    </Campo>
                    <Campo rotulo="O que o cliente ganha">
                      <div role="radiogroup" aria-label="Tipo do cupom" className="grid grid-cols-3 gap-1 rounded-2xl bg-[var(--ks-color-bg-inset)] p-1">
                        {([
                          { valor: "percent", titulo: "Percentual", Icone: Percent },
                          { valor: "value", titulo: "Valor fixo", Icone: Wallet },
                          { valor: "free_shipping", titulo: "Frete grátis", Icone: Truck },
                        ] as const).map(({ valor, titulo, Icone }) => {
                          const ativo = f.type === valor;
                          return (
                            <button
                              key={valor}
                              type="button"
                              role="radio"
                              aria-checked={ativo}
                              onClick={() => mudar({ type: valor, value: valor === "free_shipping" ? 0 : f.value || 10 })}
                              className={`flex flex-col items-center gap-1 rounded-xl px-2 py-2.5 text-[12.5px] font-bold transition sm:flex-row sm:justify-center sm:gap-2 ${
                                ativo ? "bg-white text-[var(--ks-brand-600)] shadow-[var(--ks-shadow-soft)]" : "text-[var(--ks-color-text-secondary)] hover:text-[var(--ks-color-text-primary)]"
                              }`}
                            >
                              <Icone size={16} />
                              {titulo}
                            </button>
                          );
                        })}
                      </div>
                    </Campo>
                    {f.type === "percent" ? (
                      <div className="grid gap-3 pb-4 sm:grid-cols-2">
                        <Campo rotulo="Desconto" sem>
                          <ComSufixo sufixo="%">
                            <CampoDecimal valor={f.value} aoMudar={(n) => mudar({ value: n })} casas={2} className="ks-field" aria-label="Percentual de desconto" placeholder="10" />
                          </ComSufixo>
                        </Campo>
                        <Campo rotulo="Desconto máximo" ajuda="Opcional: 10% até R$ 50." sem>
                          <ComPrefixo prefixo="R$">
                            <CampoDecimal valor={f.max_discount} aoMudar={(n) => mudar({ max_discount: n })} casas={2} zeroVazio className="ks-field" aria-label="Desconto máximo em reais" placeholder="sem teto" />
                          </ComPrefixo>
                        </Campo>
                      </div>
                    ) : f.type === "value" ? (
                      <div className="grid gap-3 pb-4 sm:grid-cols-2">
                        <Campo rotulo="Desconto" ajuda="Nunca passa do valor dos produtos que entram no cupom." sem>
                          <ComPrefixo prefixo="R$">
                            <CampoDecimal valor={f.value} aoMudar={(n) => mudar({ value: n })} casas={2} className="ks-field" aria-label="Desconto em reais" placeholder="20" />
                          </ComPrefixo>
                        </Campo>
                      </div>
                    ) : (
                      <div className="space-y-3 pb-4">
                        <Campo rotulo="Abater até" ajuda="Vazio: o frete todo sai grátis. Com valor: abate até ele, e o cliente paga o resto." sem>
                          <ComPrefixo prefixo="R$">
                            <CampoDecimal valor={f.shipping_max} aoMudar={(n) => mudar({ shipping_max: n })} casas={2} zeroVazio className="ks-field" aria-label="Abater até quanto do frete" placeholder="o frete todo" />
                          </ComPrefixo>
                        </Campo>
                        <Campo rotulo="Para quais estados" ajuda="Nenhum marcado: vale para o Brasil todo. Retirada no balcão não muda." sem>
                          <div className="flex flex-wrap gap-1.5">
                            {ESTADOS.map((uf) => {
                              const dentro = f.shipping_states.includes(uf);
                              return (
                                <button
                                  key={uf}
                                  type="button"
                                  aria-pressed={dentro}
                                  onClick={() =>
                                    mudar({ shipping_states: dentro ? f.shipping_states.filter((x) => x !== uf) : [...f.shipping_states, uf].sort() })
                                  }
                                  className={`h-8 w-11 rounded-lg text-xs font-bold transition ${
                                    dentro ? "bg-[var(--ks-emerald)] text-white shadow-sm" : "bg-[var(--ks-color-bg-inset)] text-[var(--ks-color-text-secondary)] hover:bg-[var(--ks-n-100)]"
                                  }`}
                                >
                                  {uf}
                                </button>
                              );
                            })}
                          </div>
                        </Campo>
                      </div>
                    )}
                  </SecaoDeAjustes>

                  {/* 2. Onde vale */}
                  <SecaoDeAjustes id="cupom-sec-onde" Icone={LayoutGrid} titulo="Onde vale" texto="O desconto é calculado só sobre os produtos que entram no cupom.">
                    <div className="pb-3">
                      <EscolhaDeAjuste
                        rotulo="Onde o cupom vale"
                        valor={f.scope}
                        aoEscolher={(v) => mudar({ scope: v })}
                        opcoes={[
                          { valor: "all", titulo: "Na loja toda", texto: "Todos os produtos entram (menos os que você excluir)." },
                          { valor: "categories", titulo: "Só em categorias escolhidas", texto: "As subcategorias entram junto." },
                          { valor: "products", titulo: "Só em produtos escolhidos" },
                        ]}
                      />
                    </div>
                    {f.scope === "categories" ? (
                      <Campo rotulo="Categorias" sem>
                        <EscolhaDeVarios rotulo="Categorias onde vale" itens={categorias} escolhidos={f.scope_category_ids} aoMudar={(ids) => mudar({ scope_category_ids: ids })} placeholder="Buscar categoria" vazio="Nenhuma categoria com esse nome." />
                      </Campo>
                    ) : null}
                    {f.scope === "products" ? (
                      <Campo rotulo="Produtos" sem>
                        <EscolhaDeVarios rotulo="Produtos onde vale" itens={produtos} escolhidos={f.scope_product_ids} aoMudar={(ids) => mudar({ scope_product_ids: ids })} placeholder="Buscar produto" vazio="Nenhum produto com esse nome." />
                      </Campo>
                    ) : null}
                    <div className="border-t border-[var(--ks-n-100)] py-3">
                      {mostrarExclusoes ? (
                        <div className="space-y-3">
                          <p className="text-sm font-semibold text-[var(--ks-color-text-primary)]">Nunca vale em</p>
                          <EscolhaDeVarios rotulo="Categorias excluídas" itens={categorias} escolhidos={f.exclude_category_ids} aoMudar={(ids) => mudar({ exclude_category_ids: ids })} placeholder="Excluir categoria" cor="var(--ks-rose)" />
                          <EscolhaDeVarios rotulo="Produtos excluídos" itens={produtos} escolhidos={f.exclude_product_ids} aoMudar={(ids) => mudar({ exclude_product_ids: ids })} placeholder="Excluir produto" cor="var(--ks-rose)" />
                        </div>
                      ) : (
                        <button type="button" onClick={() => setMostrarExclusoes(true)} className="text-sm font-semibold text-[var(--ks-brand-600)] hover:underline">
                          + Excluir categorias ou produtos
                        </button>
                      )}
                    </div>
                    <div className="grid gap-3 border-t border-[var(--ks-n-100)] py-4 sm:grid-cols-2">
                      <Campo rotulo="Compra mínima" ajuda="Vazio: sem mínimo." sem>
                        <ComPrefixo prefixo="R$">
                          <CampoDecimal valor={f.min_total} aoMudar={(n) => mudar({ min_total: n })} casas={2} zeroVazio className="ks-field" aria-label="Compra mínima em reais" placeholder="sem mínimo" />
                        </ComPrefixo>
                      </Campo>
                      <Campo rotulo="Itens mínimos" ajuda="Unidades no carrinho." sem>
                        <CampoDecimal valor={f.min_items} aoMudar={(n) => mudar({ min_items: n })} casas={0} zeroVazio className="ks-field" aria-label="Itens mínimos" placeholder="sem mínimo" />
                      </Campo>
                    </div>
                    {(f.min_total > 0 || f.min_items > 0) && (f.scope !== "all" || f.exclude_category_ids.length || f.exclude_product_ids.length) ? (
                      <div className="pb-4">
                        <EscolhaDeAjuste
                          rotulo="O mínimo olha"
                          valor={f.min_scope}
                          aoEscolher={(v) => mudar({ min_scope: v })}
                          opcoes={[
                            { valor: "cart", titulo: "O carrinho todo", texto: "R$ 100 em qualquer produto liberam o cupom." },
                            { valor: "eligible", titulo: "Só os produtos que entram no cupom", texto: "Precisa de R$ 100 nos produtos participantes." },
                          ]}
                        />
                      </div>
                    ) : null}
                  </SecaoDeAjustes>

                  {/* 3. Quem pode usar */}
                  <SecaoDeAjustes id="cupom-sec-quem" Icone={Users} titulo="Quem pode usar" texto="Conta na loja é o cadastro do cliente no portal (Entrar, na loja).">
                    <div className="pb-3">
                      <EscolhaDeAjuste
                        rotulo="Quem pode usar"
                        valor={f.audience}
                        aoEscolher={(v) => mudar({ audience: v })}
                        opcoes={[
                          { valor: "all", titulo: "Todo mundo", texto: "Com ou sem conta na loja." },
                          { valor: "logged", titulo: "Só clientes com conta", texto: "Precisa entrar na conta para usar." },
                          { valor: "first_purchase", titulo: "Só na primeira compra", texto: "Quem ainda não tem pedido confirmado na loja. Um uso por cliente." },
                          { valor: "clients", titulo: "Clientes escolhidos", texto: "Só os clientes que você marcar." },
                        ]}
                      />
                    </div>
                    {f.audience === "clients" ? (
                      <Campo rotulo="Clientes" sem>
                        <EscolhaDeVarios
                          rotulo="Clientes que podem usar"
                          escolhidos={f.audience_client_ids}
                          aoMudar={(ids) => mudar({ audience_client_ids: ids })}
                          buscar={buscarClientes}
                          nomesConhecidos={nomesDosClientes}
                          placeholder="Buscar por nome, e-mail ou telefone"
                          vazio="Nenhum cliente encontrado."
                        />
                      </Campo>
                    ) : null}
                  </SecaoDeAjustes>

                  {/* 4. Limites e validade */}
                  <SecaoDeAjustes id="cupom-sec-limites" Icone={CalendarClock} titulo="Limites e validade" texto="Quantas vezes, de quando a quando, em que dias e horários (Brasília).">
                    <div className="grid gap-3 py-3 sm:grid-cols-2">
                      <Campo rotulo="Usos no total" ajuda="Ex.: os primeiros 100. Vazio: sem limite." sem>
                        <CampoDecimal valor={f.usage_limit} aoMudar={(n) => mudar({ usage_limit: n })} casas={0} zeroVazio className="ks-field" aria-label="Usos no total" placeholder="sem limite" />
                      </Campo>
                      <Campo rotulo="Usos por cliente" ajuda={f.audience === "first_purchase" ? "Na primeira compra é sempre um." : "Exige conta na loja. Vazio: sem limite."} sem>
                        <CampoDecimal
                          valor={f.audience === "first_purchase" ? 1 : f.usage_limit_per_client}
                          aoMudar={(n) => mudar({ usage_limit_per_client: n })}
                          casas={0}
                          zeroVazio
                          disabled={f.audience === "first_purchase"}
                          className="ks-field"
                          aria-label="Usos por cliente"
                          placeholder="sem limite"
                        />
                      </Campo>
                    </div>
                    <div className="grid gap-3 border-t border-[var(--ks-n-100)] py-4 sm:grid-cols-2">
                      <Campo rotulo="Começa" ajuda="Vazio: já vale." sem>
                        <input type="datetime-local" value={f.starts_at} onChange={(e) => mudar({ starts_at: e.target.value })} className="ks-field" aria-label="Começa em" />
                      </Campo>
                      <Campo rotulo="Termina" ajuda="Vazio: sem data para acabar." sem>
                        <input type="datetime-local" value={f.ends_at} onChange={(e) => mudar({ ends_at: e.target.value })} className="ks-field" aria-label="Termina em" />
                      </Campo>
                    </div>
                    <div className="border-t border-[var(--ks-n-100)] py-4">
                      <div className="mb-2 flex flex-wrap items-center justify-between gap-2">
                        <p className="text-sm font-semibold text-[var(--ks-color-text-primary)]">Dias da semana</p>
                        <div className="flex gap-1 text-xs font-semibold">
                          <Atalho onClick={() => mudar({ weekdays: [] })} ativo={!f.weekdays.length}>Todos</Atalho>
                          <Atalho onClick={() => mudar({ weekdays: [1, 2, 3, 4, 5] })} ativo={f.weekdays.join() === "1,2,3,4,5"}>Dias úteis</Atalho>
                          <Atalho onClick={() => mudar({ weekdays: [0, 6] })} ativo={f.weekdays.join() === "0,6"}>Fim de semana</Atalho>
                        </div>
                      </div>
                      <div className="grid grid-cols-7 gap-1.5">
                        {DIAS_CURTOS.map(({ dia, rotulo }) => {
                          const dentro = !f.weekdays.length || f.weekdays.includes(dia);
                          return (
                            <button
                              key={dia}
                              type="button"
                              aria-pressed={dentro}
                              onClick={() => {
                                const base = f.weekdays.length ? f.weekdays : [0, 1, 2, 3, 4, 5, 6];
                                const novo = base.includes(dia) ? base.filter((d) => d !== dia) : [...base, dia];
                                mudar({ weekdays: novo.length === 7 || !novo.length ? [] : novo.sort() });
                              }}
                              className={`h-10 rounded-xl text-xs font-bold transition ${
                                dentro ? "bg-[var(--ks-brand-600)] text-white shadow-sm" : "bg-[var(--ks-color-bg-inset)] text-[var(--ks-color-text-soft)] hover:bg-[var(--ks-n-100)]"
                              }`}
                            >
                              {rotulo}
                            </button>
                          );
                        })}
                      </div>
                    </div>
                    <div className="border-t border-[var(--ks-n-100)] py-4">
                      <p className="mb-2 text-sm font-semibold text-[var(--ks-color-text-primary)]">Horário</p>
                      <div className="flex flex-wrap items-center gap-2">
                        <span className="text-sm text-[var(--ks-color-text-muted)]">das</span>
                        <input type="time" value={f.hours_start} onChange={(e) => mudar({ hours_start: e.target.value })} className="ks-field" style={{ width: 128 }} aria-label="Horário de início" />
                        <span className="text-sm text-[var(--ks-color-text-muted)]">às</span>
                        <input type="time" value={f.hours_end} onChange={(e) => mudar({ hours_end: e.target.value })} className="ks-field" style={{ width: 128 }} aria-label="Horário de fim" />
                        {f.hours_start || f.hours_end ? (
                          <button type="button" onClick={() => mudar({ hours_start: "", hours_end: "" })} className="text-xs font-semibold text-[var(--ks-color-text-muted)] hover:text-[var(--ks-color-text-primary)]">
                            O dia todo
                          </button>
                        ) : (
                          <span className="text-xs text-[var(--ks-color-text-soft)]">vazio: o dia todo</span>
                        )}
                      </div>
                      <p className="mt-1.5 text-xs text-[var(--ks-color-text-muted)]">Pode virar a noite: das 22h às 2h vale até a madrugada seguinte.</p>
                    </div>
                  </SecaoDeAjustes>

                  {/* 5. Como aplicar */}
                  <SecaoDeAjustes
                    id="cupom-sec-aplicar"
                    Icone={Wand2}
                    titulo="Como aplicar"
                    texto="Um pedido leva até dois cupons: um de desconto e um de frete grátis. Com dois do mesmo tipo, fica o que der mais ao cliente."
                  >
                    <div className="pb-3">
                      <EscolhaDeAjuste
                        rotulo="Como o cupom entra no carrinho"
                        valor={f.application}
                        aoEscolher={(v) => mudar({ application: v })}
                        opcoes={[
                          { valor: "code", titulo: "Com código", texto: "O cliente digita, toca no cupom do carrinho ou abre o link." },
                          { valor: "automatic", titulo: "Automático", texto: "Entra sozinho no carrinho de quem cumprir as regras, sem digitar nada." },
                        ]}
                      />
                    </div>
                    <ChaveDeAjuste
                      titulo={f.type === "free_shipping" ? "Pode ser usado junto com um cupom de desconto" : "Pode ser usado junto com um cupom de frete grátis"}
                      texto={
                        f.combinable
                          ? "Os dois entram no mesmo pedido. O mínimo do frete grátis olha os produtos antes dos descontos."
                          : "Desligado: este cupom é usado sozinho no pedido."
                      }
                      ligado={f.combinable}
                      aoMudar={(v) => mudar({ combinable: v })}
                    />
                    {f.application === "code" && codigoDoLink ? (
                      <div className="border-t border-[var(--ks-n-100)] py-4">
                        <p className="text-sm font-semibold text-[var(--ks-color-text-primary)]">Link do cupom</p>
                        <p className="mt-0.5 text-xs text-[var(--ks-color-text-muted)]">Quem abre o link chega na loja com o cupom guardado no carrinho.{id ? "" : " Salve o cupom antes de divulgar."}</p>
                        <div className="mt-2 flex flex-col gap-2 sm:flex-row">
                          <input readOnly value={linkDoCupom(codigoDoLink)} onFocus={(e) => e.currentTarget.select()} className="ks-field font-mono text-xs" aria-label="Link do cupom" />
                          <div className="flex shrink-0 gap-2">
                            <button type="button" onClick={copiarLink} className="ks-button ks-button-secondary">
                              {copiado ? <Check size={15} /> : <Copy size={15} />} {copiado ? "Copiado" : "Copiar"}
                            </button>
                            <button type="button" onClick={() => aoAbrirQr(codigoDoLink)} className="ks-button ks-button-secondary" title="QR code do link">
                              <QrCode size={15} /> QR
                            </button>
                          </div>
                        </div>
                      </div>
                    ) : null}
                  </SecaoDeAjustes>

                  {/* 6. Visibilidade */}
                  <SecaoDeAjustes id="cupom-sec-visivel" Icone={Eye} titulo="Visibilidade" texto="Secreto: só quem tem o código ou o link usa.">
                    <ChaveDeAjuste
                      titulo="Mostrar no carrinho"
                      texto={
                        f.application === "automatic"
                          ? "O automático já entra sozinho no carrinho de quem pode usar."
                          : 'Aparece em "Cupons da loja" no carrinho, para o cliente tocar e usar.'
                      }
                      ligado={f.application === "code" && f.show_in_store}
                      desabilitado={f.application === "automatic"}
                      aoMudar={(v) => mudar({ show_in_store: v })}
                    />
                    <div className="h-2" />
                  </SecaoDeAjustes>
                </div>
              </div>
            </div>

            {/* Rodapé fixo: ligado, cancelar e salvar */}
            <footer className="shrink-0 border-t border-[var(--ks-color-border-subtle)] bg-white px-4 py-3 sm:px-6">
              {erro ? (
                <p role="alert" className="mb-2 rounded-xl bg-[var(--ks-rose-soft)] px-3 py-2 text-[13px] font-semibold text-[var(--ks-color-status-danger)]">
                  {erro}
                </p>
              ) : null}
              <div className="flex items-center justify-between gap-3">
                <label className="flex items-center gap-2.5 text-sm font-semibold text-[var(--ks-color-text-primary)]">
                  <Switch checked={f.active} onCheckedChange={(v) => mudar({ active: v })} aria-label="Cupom ligado" />
                  {f.active ? "Ligado" : "Pausado"}
                </label>
                <div className="flex items-center gap-2">
                  <button type="button" onClick={pedirParaFechar} className="ks-button ks-button-ghost">
                    Cancelar
                  </button>
                  <button type="button" onClick={salvar} disabled={salvando} className="ks-button ks-button-primary">
                    {salvando ? <Loader2 size={16} className="animate-spin" /> : <Check size={16} />}
                    {id ? "Salvar cupom" : "Criar cupom"}
                  </button>
                </div>
              </div>
            </footer>
          </motion.aside>
        </motion.div>
      ) : null}
    </AnimatePresence>
    <CaixaDeConfirmacao
      pedido={
        perguntarSaida
          ? {
              titulo: "Sair sem salvar?",
              texto: "O que você mudou neste cupom vai ser perdido.",
              confirmar: "Sair sem salvar",
              cancelar: "Continuar editando",
              tom: "perigo",
              aoConfirmar: () => {
                setPerguntarSaida(false);
                aoFechar();
              },
            }
          : null
      }
      aoFechar={() => setPerguntarSaida(false)}
    />
    </>
  );
}

/* ------------------------------------------------------------ peças */

function Campo({ rotulo, ajuda, sem = false, children }: { rotulo: string; ajuda?: ReactNode; sem?: boolean; children: ReactNode }) {
  return (
    <div className={sem ? "" : "border-t border-[var(--ks-n-100)] py-4 first:border-t-0"}>
      <p className="mb-1.5 text-sm font-semibold text-[var(--ks-color-text-primary)]">{rotulo}</p>
      {children}
      {ajuda ? <p className="mt-1.5 text-xs leading-relaxed text-[var(--ks-color-text-muted)]">{ajuda}</p> : null}
    </div>
  );
}

function ComPrefixo({ prefixo, children }: { prefixo: string; children: ReactNode }) {
  return (
    <div className="relative [&_input]:!pl-10">
      <span className="pointer-events-none absolute left-3.5 top-1/2 -translate-y-1/2 text-sm font-semibold text-[var(--ks-color-text-soft)]">{prefixo}</span>
      {children}
    </div>
  );
}

function ComSufixo({ sufixo, children }: { sufixo: string; children: ReactNode }) {
  return (
    <div className="relative [&_input]:!pr-9">
      {children}
      <span className="pointer-events-none absolute right-3.5 top-1/2 -translate-y-1/2 text-sm font-bold text-[var(--ks-color-text-soft)]">{sufixo}</span>
    </div>
  );
}

function Atalho({ ativo, onClick, children }: { ativo: boolean; onClick: () => void; children: ReactNode }) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={`rounded-full px-2.5 py-1 transition ${ativo ? "bg-[var(--ks-brand-50)] text-[var(--ks-brand-600)]" : "text-[var(--ks-color-text-muted)] hover:bg-[var(--ks-color-bg-hover)]"}`}
    >
      {children}
    </button>
  );
}

/* ------------------------------------------------------------ como o cliente vê */

/* A frase do cupom, sem repetir o selo: "Frete grátis" sozinho vira "Vale para qualquer compra na loja". */
function fraseSemRepetir(cupom: ReturnType<typeof cupomDoFormulario>, nomes: NomesDoCupom) {
  const frase = fraseDoCupom(cupom, Date.now(), nomes);
  return frase.toLowerCase() === rotuloDoBeneficio(cupom).toLowerCase() || frase === "Frete grátis" ? "Vale para qualquer compra na loja" : frase;
}

const COR_DO_TIPO = { percent: "var(--ks-brand-600)", value: "#d63a8a", free_shipping: "#0e9e70" } as const;

/* No celular e no tablet: uma faixa com o que o cliente ganha, a frase e,
   num toque, a prévia inteira com o simulador. */
function PreviaCompacta({ f, nomes }: { f: FormularioDoCupom; nomes: NomesDoCupom }) {
  const [aberta, setAberta] = useState(false);
  const cupom = useMemo(() => cupomDoFormulario(f), [f]);
  const cor = COR_DO_TIPO[f.type];
  return (
    <div className="space-y-3">
      <button
        type="button"
        onClick={() => setAberta((v) => !v)}
        aria-expanded={aberta}
        className="flex w-full items-center gap-3 rounded-2xl px-3.5 py-3 text-left text-white shadow-[var(--ks-shadow-soft)]"
        style={{ backgroundColor: cor }}
      >
        <span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-white/20">
          {f.application === "automatic" ? <Sparkles size={18} /> : f.type === "free_shipping" ? <Truck size={18} /> : <Ticket size={18} />}
        </span>
        <span className="min-w-0 flex-1">
          <span className="block text-[17px] font-black leading-tight">{rotuloDoBeneficio(cupom)}</span>
          <span className="line-clamp-2 text-xs font-medium text-white/85">{fraseSemRepetir(cupom, nomes)}</span>
        </span>
        <span className="shrink-0 rounded-full bg-white/20 px-2.5 py-1 text-[11px] font-bold">{aberta ? "Fechar" : "Prévia"}</span>
      </button>
      {aberta ? <ComoOClienteVe f={f} nomes={nomes} /> : null}
    </div>
  );
}

function ComoOClienteVe({ f, nomes }: { f: FormularioDoCupom; nomes: NomesDoCupom }) {
  const cupom = useMemo(() => cupomDoFormulario(f), [f]);
  const [carrinho, setCarrinho] = useState(150);
  const [frete, setFrete] = useState(25);
  const agora = Date.now();
  const condicoes = condicoesDoCupom(cupom, agora, { nomes });
  const simulacao = avaliarCupom(
    { ...cupom, active: true, starts_at: null, ends_at: null, weekdays: [], hours_start: null, hours_end: null, scope: "all", exclude_category_ids: [], exclude_product_ids: [], audience: "all", usage_limit: null, usage_limit_per_client: null },
    { itens: [{ product_id: "p", category_id: null, total: carrinho, quantity: Math.max(f.min_items, 1) }], cliente: { id: "c" }, frete: f.type === "free_shipping" ? { valor: frete, cep: "", retirada: true } : null, agora }
  );
  const cor = COR_DO_TIPO[f.type];

  return (
    <div className="space-y-3">
      <p className="px-1 text-[11px] font-bold uppercase tracking-[0.14em] text-[var(--ks-color-text-soft)]">Como o cliente vê</p>
      <div className="overflow-hidden rounded-2xl bg-white shadow-[var(--ks-shadow-soft)] ring-1 ring-[var(--ks-color-border-subtle)]">
        <div className="relative flex items-center gap-3 px-4 py-4 text-white" style={{ backgroundColor: cor }}>
          <span className="flex h-11 w-11 shrink-0 items-center justify-center rounded-xl bg-white/20">
            {f.application === "automatic" ? <Sparkles size={20} /> : f.type === "free_shipping" ? <Truck size={20} /> : <Ticket size={20} />}
          </span>
          <div className="min-w-0">
            <p className="text-2xl font-black leading-none tracking-tight">{rotuloDoBeneficio(cupom)}</p>
            <p className="mt-1 truncate text-xs font-semibold text-white/85">
              {f.application === "automatic" ? `Desconto aplicado: ${nomeDoCupom({ name: f.name, code: f.code || "CUPOM" })}` : f.name || "Cupom de desconto"}
            </p>
          </div>
          <span aria-hidden className="absolute -bottom-2.5 left-6 h-5 w-5 rounded-full bg-white" />
          <span aria-hidden className="absolute -bottom-2.5 right-6 h-5 w-5 rounded-full bg-white" />
        </div>
        <div className="space-y-3 px-4 pb-4 pt-5">
          {f.application === "code" ? (
            <div className="flex h-11 items-center justify-center rounded-xl border-2 border-dashed font-mono text-lg font-black tracking-[0.14em]" style={{ borderColor: cor, color: cor }}>
              {f.code.trim().toUpperCase() || "CÓDIGO"}
            </div>
          ) : (
            <p className="flex items-center gap-1.5 rounded-xl bg-[var(--ks-color-bg-inset)] px-3 py-2 text-xs font-semibold text-[var(--ks-color-text-secondary)]">
              <Sparkles size={13} style={{ color: cor }} /> Entra sozinho no carrinho, sem código
            </p>
          )}
          <p className="text-sm font-semibold leading-snug text-[var(--ks-color-text-primary)]">{fraseSemRepetir(cupom, nomes)}</p>
          {condicoes.length ? (
            <ul className="space-y-1">
              {condicoes.map((c) => (
                <li key={c} className="flex items-start gap-1.5 text-xs text-[var(--ks-color-text-secondary)]">
                  <Check size={13} className="mt-0.5 shrink-0" style={{ color: cor }} strokeWidth={3} /> {c}
                </li>
              ))}
            </ul>
          ) : fraseSemRepetir(cupom, nomes) === "Vale para qualquer compra na loja" ? null : (
            <p className="text-xs text-[var(--ks-color-text-muted)]">Vale para qualquer compra na loja.</p>
          )}
        </div>
      </div>

      <div className="rounded-2xl bg-white px-4 py-3.5 shadow-[var(--ks-shadow-subtle)] ring-1 ring-[var(--ks-color-border-subtle)]">
        <p className="text-xs font-bold text-[var(--ks-color-text-primary)]">Simular um carrinho</p>
        <div className="mt-2 grid grid-cols-2 gap-2">
          <label className="text-[11px] font-semibold text-[var(--ks-color-text-muted)]">
            Produtos (R$)
            <CampoDecimal valor={carrinho} aoMudar={setCarrinho} casas={2} className="ks-field mt-1" aria-label="Valor dos produtos na simulação" />
          </label>
          {f.type === "free_shipping" ? (
            <label className="text-[11px] font-semibold text-[var(--ks-color-text-muted)]">
              Frete (R$)
              <CampoDecimal valor={frete} aoMudar={setFrete} casas={2} className="ks-field mt-1" aria-label="Valor do frete na simulação" />
            </label>
          ) : null}
        </div>
        <p className={`mt-2.5 text-[13px] font-bold ${simulacao.ok ? "text-[var(--ks-color-status-success)]" : "text-[var(--ks-color-text-muted)]"}`}>
          {simulacao.ok
            ? f.type === "free_shipping"
              ? `Frete de ${reais(frete)} sai por ${reais(Math.max(frete - simulacao.descontoNoFrete, 0))}`
              : `Desconto de ${reais(simulacao.desconto)}: paga ${reais(Math.max(carrinho - simulacao.desconto, 0))}`
            : simulacao.mensagem}
        </p>
      </div>
    </div>
  );
}
