"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import {
  CalendarClock,
  Copy,
  CopyPlus,
  Eye,
  Link2,
  Loader2,
  MoreHorizontal,
  Pencil,
  Plus,
  QrCode,
  Search,
  Sparkles,
  Ticket,
  Trash2,
  Truck,
  Wallet,
  Percent,
  LayoutTemplate,
} from "lucide-react";
import { getSupabaseClient } from "@/lib/supabase";
import { getCompanyContext } from "@/lib/company-context";
import { buildPublicCatalogUrl, type PublicCatalogProfile } from "@/lib/public-catalog-url";
import CaixaDeConfirmacao, { type Confirmacao } from "@/components/ui/caixa-de-confirmacao";
import { Aviso } from "@/components/ui/aviso";
import { Input } from "@/components/ui/input";
import { Switch } from "@/components/ui/switch";
import { CustomSelect } from "@/components/ui/custom-select";
import {
  ROTULO_DA_SITUACAO,
  fraseDoCupom,
  gerarCodigo,
  lerCupom,
  reaisCurtos,
  relogioDeBrasilia,
  rotuloDoBeneficio,
  situacaoDoCupom,
  type Cupom,
  type NomesDoCupom,
  type SituacaoDoCupom,
} from "@/lib/regras-do-cupom";
import { EditorDoCupom, type ResultadoDoSalvar } from "./editor-do-cupom";
import { QrDoCupom } from "./qr-do-cupom";
import type { ItemParaEscolher } from "./escolha-de-varios";
import { MODELOS_DE_CUPOM, formularioDe, formularioVazio, linhaDoFormulario, type FormularioDoCupom, type LinhaDoCupom, type ModeloDeCupom } from "./formulario";

/*
  Os cupons da loja: lista corrida, números de cada cupom e a gaveta para
  criar e editar.

  Cada linha diz de relance o que o cupom dá, a situação (ativo, agendado,
  pausado, expirado, esgotado), os usos contra o limite, a receita dos
  pedidos confirmados e até quando vale. Os números vêm do banco
  (metricas_dos_cupons, migration 200): usos contam enquanto o pedido não for
  cancelado; receita só de pedido aprovado ou pago.
*/

type Metrica = { usos: number; pedidos: number; receita: number; desconto: number; ultimo_uso: string | null };
type Ordem = "recentes" | "usos" | "receita" | "vencimento" | "codigo";
type FiltroDeSituacao = "todos" | SituacaoDoCupom;
type FiltroDeTipo = "todos" | "percent" | "value" | "free_shipping" | "automatic";

const COR_DA_SITUACAO: Record<SituacaoDoCupom, { ponto: string; fundo: string; texto: string }> = {
  ativo: { ponto: "bg-[var(--ks-emerald)]", fundo: "bg-[var(--ks-emerald-soft)]", texto: "text-[var(--ks-color-status-success)]" },
  agendado: { ponto: "bg-[var(--ks-sky)]", fundo: "bg-[var(--ks-sky-soft)]", texto: "text-[var(--ks-color-status-info)]" },
  pausado: { ponto: "bg-[var(--ks-n-400)]", fundo: "bg-[var(--ks-n-100)]", texto: "text-[var(--ks-color-text-secondary)]" },
  expirado: { ponto: "bg-[var(--ks-rose)]", fundo: "bg-[var(--ks-rose-soft)]", texto: "text-[var(--ks-color-status-danger)]" },
  esgotado: { ponto: "bg-[var(--ks-amber)]", fundo: "bg-[var(--ks-amber-soft)]", texto: "text-[var(--ks-color-status-warning)]" },
};

const GRADIENTE_DO_TIPO: Record<Cupom["type"], string> = {
  percent: "linear-gradient(135deg, var(--ks-brand-500) 0%, var(--ks-brand-700) 100%)",
  value: "linear-gradient(135deg, #f0529c 0%, #c2307a 100%)",
  free_shipping: "linear-gradient(135deg, #1fd39b 0%, #0e9e70 100%)",
};

function IconeDoTipo({ cupom, tamanho = 40 }: { cupom: Cupom; tamanho?: number }) {
  const Icone = cupom.application === "automatic" ? Sparkles : cupom.type === "free_shipping" ? Truck : cupom.type === "value" ? Wallet : Percent;
  return (
    <span
      className="flex shrink-0 items-center justify-center rounded-xl text-white"
      style={{ width: tamanho, height: tamanho, background: GRADIENTE_DO_TIPO[cupom.type], boxShadow: "0 6px 14px rgba(45, 30, 105, 0.18)" }}
    >
      <Icone size={Math.round(tamanho * 0.45)} />
    </span>
  );
}

function SeloDaSituacao({ situacao }: { situacao: SituacaoDoCupom }) {
  const cor = COR_DA_SITUACAO[situacao];
  return (
    <span className={`inline-flex items-center gap-1.5 rounded-full px-2.5 py-1 text-xs font-semibold ${cor.fundo} ${cor.texto}`}>
      <span className={`h-1.5 w-1.5 rounded-full ${cor.ponto}`} />
      {ROTULO_DA_SITUACAO[situacao]}
    </span>
  );
}

function validadeCurta(cupom: Cupom, agora: number) {
  const dia = (iso: string) => {
    const r = relogioDeBrasilia(new Date(iso).getTime());
    const hoje = relogioDeBrasilia(agora);
    const dois = (n: number) => String(n).padStart(2, "0");
    return `${dois(r.dia)}/${dois(r.mes)}${r.ano !== hoje.ano ? `/${String(r.ano).slice(2)}` : ""}`;
  };
  if (cupom.starts_at && new Date(cupom.starts_at).getTime() > agora) return `de ${dia(cupom.starts_at)}${cupom.ends_at ? ` a ${dia(cupom.ends_at)}` : ""}`;
  if (cupom.ends_at) return `${new Date(cupom.ends_at).getTime() < agora ? "venceu" : "até"} ${dia(cupom.ends_at)}`;
  return "sem prazo";
}

function limparBusca(termo: string) {
  return termo.replace(/[,()%*\\]/g, " ").trim().slice(0, 60);
}

export function PainelDeCupons({ podeEditar, aoContar }: { podeEditar: boolean; aoContar?: (n: number) => void }) {
  const [carregando, setCarregando] = useState(true);
  const [linhas, setLinhas] = useState<LinhaDoCupom[]>([]);
  const [metricas, setMetricas] = useState<Record<string, Metrica>>({});
  const [categorias, setCategorias] = useState<ItemParaEscolher[]>([]);
  const [produtos, setProdutos] = useState<ItemParaEscolher[]>([]);
  const [nomesDosClientes, setNomesDosClientes] = useState<Record<string, string>>({});
  const [dono, setDono] = useState<string | null>(null);
  const [tenantIds, setTenantIds] = useState<string[]>([]);
  const [perfil, setPerfil] = useState<(PublicCatalogProfile & { slug?: string | null }) | null>(null);
  const [aviso, setAviso] = useState<{ tom: "bom" | "ruim"; texto: string } | null>(null);
  const [confirmacao, setConfirmacao] = useState<Confirmacao | null>(null);
  const [qrDe, setQrDe] = useState<string | null>(null);
  const [resumoGeral, setResumoGeral] = useState<{ usos: number; receita: number; desconto: number } | null>(null);

  const [busca, setBusca] = useState("");
  const [situacao, setSituacao] = useState<FiltroDeSituacao>("todos");
  const [tipo, setTipo] = useState<FiltroDeTipo>("todos");
  const [ordem, setOrdem] = useState<Ordem>("recentes");

  const [editor, setEditor] = useState<{ id: string | null; inicial: FormularioDoCupom; codigoOriginal: string | null } | null>(null);
  const [menuDe, setMenuDe] = useState<string | null>(null);
  const [modelosAbertos, setModelosAbertos] = useState(false);
  const agora = Date.now();

  const carregar = useCallback(async () => {
    const supabase = getSupabaseClient();
    const {
      data: { user },
    } = await supabase.auth.getUser();
    if (!user) return;
    const ctx = await getCompanyContext(supabase, user);
    const tenants = ctx.tenantIds?.length ? ctx.tenantIds : [user.id];
    const ownerId = ctx.ownerId ?? user.id;
    setDono(ownerId);
    setTenantIds(tenants);
    const [cupons, numeros, cats, prods, loja, dominio, resumo] = await Promise.all([
      supabase.from("catalog_coupons").select("*").eq("user_id", ownerId).order("created_at", { ascending: false }),
      supabase.rpc("metricas_dos_cupons", { p_loja: ownerId }),
      supabase.from("categories").select("id,name,parent_id").eq("user_id", ownerId).order("name").limit(2000),
      supabase.from("products").select("id,name,category_id").in("user_id", tenants).neq("product_kind", "digital").order("name").limit(3000),
      supabase.from("profiles").select("slug").eq("id", ownerId).maybeSingle(),
      supabase.from("profile_custom_domains").select("domain,verified").eq("profile_id", ownerId).eq("verified", true).limit(1).maybeSingle(),
      /* O topo sem contar duas vezes o pedido que usou dois cupons. */
      supabase.rpc("resumo_dos_cupons", { p_loja: ownerId }),
    ]);
    const linhaDoResumo = ((resumo.data ?? []) as Array<{ usos: number; pedidos: number; receita: number; desconto: number }>)[0];
    setResumoGeral(linhaDoResumo ? { usos: Number(linhaDoResumo.usos) || 0, receita: Number(linhaDoResumo.receita) || 0, desconto: Number(linhaDoResumo.desconto) || 0 } : null);
    if (cupons.error) setAviso({ tom: "ruim", texto: "Não deu para ler os cupons agora. Recarregue a página." });
    const lista = ((cupons.data ?? []) as LinhaDoCupom[]);
    setLinhas(lista);
    const mapa: Record<string, Metrica> = {};
    for (const m of (numeros.data ?? []) as Array<Metrica & { coupon_id: string }>) {
      mapa[m.coupon_id] = { usos: Number(m.usos) || 0, pedidos: Number(m.pedidos) || 0, receita: Number(m.receita) || 0, desconto: Number(m.desconto) || 0, ultimo_uso: m.ultimo_uso };
    }
    setMetricas(mapa);
    const linhasDeCategoria = (cats.data ?? []) as Array<{ id: string; name: string; parent_id: string | null }>;
    const nomeDaCategoria = new Map(linhasDeCategoria.map((c) => [c.id, c.name]));
    setCategorias(
      linhasDeCategoria.map((c) => ({ id: c.id, nome: c.name, detalhe: c.parent_id ? `dentro de ${nomeDaCategoria.get(c.parent_id) ?? "outra categoria"}` : null }))
    );
    setProdutos(
      ((prods.data ?? []) as Array<{ id: string; name: string; category_id: string | null }>).map((p) => ({
        id: p.id,
        nome: p.name,
        detalhe: p.category_id ? nomeDaCategoria.get(p.category_id) ?? null : null,
      }))
    );
    const dominioVerificado = dominio.data as { domain?: string | null; verified?: boolean | null } | null;
    setPerfil({
      slug: (loja.data as { slug?: string | null } | null)?.slug ?? null,
      custom_domain: dominioVerificado?.domain ?? null,
      custom_domain_verified: Boolean(dominioVerificado?.verified),
    });
    const idsDeClientes = Array.from(new Set(lista.flatMap((l) => lerCupom(l).audience_client_ids))).slice(0, 500);
    if (idsDeClientes.length) {
      const { data } = await supabase.from("clients").select("id,name").in("id", idsDeClientes);
      setNomesDosClientes(Object.fromEntries(((data ?? []) as Array<{ id: string; name: string | null }>).map((c) => [c.id, c.name || "Cliente sem nome"])));
    }
    setCarregando(false);
  }, []);

  useEffect(() => {
    void carregar();
  }, [carregar]);

  useEffect(() => {
    if (!carregando) aoContar?.(linhas.length);
  }, [carregando, linhas.length, aoContar]);

  useEffect(() => {
    if (!menuDe) return;
    const fechar = () => setMenuDe(null);
    window.addEventListener("click", fechar);
    return () => window.removeEventListener("click", fechar);
  }, [menuDe]);

  const cupons = useMemo(() => linhas.map((l) => ({ linha: l, cupom: lerCupom(l) })), [linhas]);
  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 situacaoDe = useCallback((c: Cupom) => situacaoDoCupom(c, agora, metricas[c.id]?.usos ?? 0), [agora, metricas]);

  const contagem = useMemo(() => {
    const conta: Record<SituacaoDoCupom, number> = { ativo: 0, agendado: 0, pausado: 0, expirado: 0, esgotado: 0 };
    for (const { cupom } of cupons) conta[situacaoDe(cupom)] += 1;
    return conta;
  }, [cupons, situacaoDe]);

  const totais = useMemo(() => {
    if (resumoGeral) return resumoGeral;
    let usos = 0;
    let receita = 0;
    let desconto = 0;
    for (const m of Object.values(metricas)) {
      usos += m.usos;
      receita += m.receita;
      desconto += m.desconto;
    }
    return { usos, receita, desconto };
  }, [metricas, resumoGeral]);

  const visiveis = useMemo(() => {
    const termo = busca.trim().toLowerCase();
    const lista = cupons.filter(({ cupom }) => {
      if (termo && !cupom.code.toLowerCase().includes(termo) && !(cupom.name ?? "").toLowerCase().includes(termo)) return false;
      if (situacao !== "todos" && situacaoDe(cupom) !== situacao) return false;
      if (tipo === "automatic" && cupom.application !== "automatic") return false;
      if (tipo !== "todos" && tipo !== "automatic" && cupom.type !== tipo) return false;
      return true;
    });
    const fim = (c: Cupom) => (c.ends_at ? new Date(c.ends_at).getTime() : Number.MAX_SAFE_INTEGER);
    return lista.sort((a, b) => {
      if (ordem === "usos") return (metricas[b.cupom.id]?.usos ?? 0) - (metricas[a.cupom.id]?.usos ?? 0);
      if (ordem === "receita") return (metricas[b.cupom.id]?.receita ?? 0) - (metricas[a.cupom.id]?.receita ?? 0);
      if (ordem === "vencimento") return fim(a.cupom) - fim(b.cupom);
      if (ordem === "codigo") return a.cupom.code.localeCompare(b.cupom.code);
      return String(b.linha.created_at ?? "").localeCompare(String(a.linha.created_at ?? ""));
    });
  }, [cupons, busca, situacao, tipo, ordem, metricas, situacaoDe]);

  const linkDoCupom = useCallback(
    (codigo: string) => {
      const origem = typeof window === "undefined" ? "" : window.location.origin;
      const cupomNaUrl = encodeURIComponent(codigo);
      return buildPublicCatalogUrl(origem, perfil, { slugPath: `/${perfil?.slug ?? ""}?cupom=${cupomNaUrl}`, customPath: `/?cupom=${cupomNaUrl}` });
    },
    [perfil]
  );

  const buscarClientes = useCallback(
    async (termo: string): Promise<ItemParaEscolher[]> => {
      const supabase = getSupabaseClient();
      let consulta = supabase.from("clients").select("id,name,email,phone").in("user_id", tenantIds).or("is_deleted.is.null,is_deleted.eq.false").order("name").limit(20);
      const limpo = limparBusca(termo);
      if (limpo) consulta = consulta.or(`name.ilike.%${limpo}%,email.ilike.%${limpo}%,phone.ilike.%${limpo}%`);
      const { data } = await consulta;
      return ((data ?? []) as Array<{ id: string; name: string | null; email: string | null; phone: string | null }>).map((c) => ({
        id: c.id,
        nome: c.name || "Cliente sem nome",
        detalhe: [c.email, c.phone].filter(Boolean).join(" · ") || null,
      }));
    },
    [tenantIds]
  );

  /* ------------------------------------------------------------ ações */

  const abrirNovo = (modelo?: ModeloDeCupom) => {
    setModelosAbertos(false);
    setEditor({ id: null, inicial: modelo ? modelo.montar() : { ...formularioVazio(), code: gerarCodigo() }, codigoOriginal: null });
  };

  const abrirEdicao = (linha: LinhaDoCupom) => {
    if (!podeEditar) return;
    setEditor({ id: linha.id, inicial: formularioDe(linha), codigoOriginal: String(linha.code) });
  };

  const duplicar = (linha: LinhaDoCupom) => {
    const base = formularioDe(linha);
    setEditor({ id: null, inicial: { ...base, code: gerarCodigo(String(linha.code).replace(/[^A-Z0-9]/gi, "").slice(0, 10)), active: false }, codigoOriginal: null });
  };

  const salvar = async (f: FormularioDoCupom): Promise<ResultadoDoSalvar> => {
    if (!dono || !editor) return { ok: false, erro: "Entre no painel de novo para salvar." };
    const supabase = getSupabaseClient();
    const carga = { ...linhaDoFormulario(f), updated_at: new Date().toISOString() };
    const resposta = editor.id
      ? await supabase.from("catalog_coupons").update(carga).eq("id", editor.id).eq("user_id", dono).select("*").single()
      : await supabase.from("catalog_coupons").insert({ ...carga, user_id: dono }).select("*").single();
    if (resposta.error) {
      if (resposta.error.code === "23505") return { ok: false, erro: `Já existe um cupom ${carga.code} nesta loja. Escolha outro código.` };
      return { ok: false, erro: "Não deu para salvar o cupom. Tente de novo." };
    }
    const salvo = resposta.data as LinhaDoCupom;
    setLinhas((antes) => (editor.id ? antes.map((l) => (l.id === editor.id ? salvo : l)) : [salvo, ...antes]));
    setEditor(null);
    setAviso({ tom: "bom", texto: editor.id ? `Cupom ${salvo.code} salvo.` : `Cupom ${salvo.code} criado.` });
    return { ok: true };
  };

  const alternar = async (linha: LinhaDoCupom, ligado: boolean) => {
    setLinhas((antes) => antes.map((l) => (l.id === linha.id ? { ...l, active: ligado } : l)));
    const { error } = await getSupabaseClient()
      .from("catalog_coupons")
      .update({ active: ligado, updated_at: new Date().toISOString() })
      .eq("id", linha.id);
    if (error) {
      setLinhas((antes) => antes.map((l) => (l.id === linha.id ? { ...l, active: !ligado } : l)));
      setAviso({ tom: "ruim", texto: "Não deu para mudar o cupom. Tente de novo." });
    }
  };

  const pedirExclusao = (linha: LinhaDoCupom) => {
    setConfirmacao({
      titulo: `Excluir o cupom ${linha.code}?`,
      texto: "Quem já usou continua com o desconto. O cupom para de valer para novas compras e os números dele saem desta lista. Para parar só por um tempo, pause.",
      confirmar: "Excluir cupom",
      tom: "perigo",
      aoConfirmar: async () => {
        setConfirmacao(null);
        const { error } = await getSupabaseClient().from("catalog_coupons").delete().eq("id", linha.id);
        if (error) {
          setAviso({ tom: "ruim", texto: "Não deu para excluir o cupom." });
          return;
        }
        setLinhas((antes) => antes.filter((l) => l.id !== linha.id));
        setAviso({ tom: "bom", texto: `Cupom ${linha.code} excluído.` });
      },
    });
  };

  const copiarLink = async (codigo: string) => {
    try {
      await navigator.clipboard.writeText(linkDoCupom(codigo));
      setAviso({ tom: "bom", texto: `Link do cupom ${codigo} copiado.` });
    } catch {
      setQrDe(codigo);
    }
  };

  /* ------------------------------------------------------------ tela */

  if (carregando) {
    return (
      <div className="ks-surface flex items-center justify-center rounded-xl border border-[var(--ks-color-border-subtle)] py-20">
        <Loader2 className="h-7 w-7 animate-spin text-[var(--ks-color-primary)]" />
      </div>
    );
  }

  const editorDaTela = (
    <EditorDoCupom
      aberto={Boolean(editor)}
      id={editor?.id ?? null}
      inicial={editor?.inicial ?? null}
      codigoOriginal={editor?.codigoOriginal ?? null}
      categorias={categorias}
      produtos={produtos}
      buscarClientes={buscarClientes}
      nomesDosClientes={nomesDosClientes}
      linkDoCupom={linkDoCupom}
      aoAbrirQr={setQrDe}
      aoFechar={() => setEditor(null)}
      aoSalvar={salvar}
    />
  );

  const extras = (
    <>
      {editorDaTela}
      <QrDoCupom codigo={qrDe} link={qrDe ? linkDoCupom(qrDe) : ""} aoFechar={() => setQrDe(null)} />
      <CaixaDeConfirmacao pedido={confirmacao} aoFechar={() => setConfirmacao(null)} />
    </>
  );

  if (!linhas.length) {
    return (
      <div className="space-y-4">
        {aviso ? (
          <Aviso tom={aviso.tom} aoFechar={() => setAviso(null)}>
            {aviso.texto}
          </Aviso>
        ) : null}
        <div className="overflow-hidden rounded-2xl border border-[var(--ks-color-border-subtle)] bg-white shadow-[var(--ks-shadow-subtle)]">
          <div className="flex flex-col gap-5 border-b border-[var(--ks-n-100)] px-5 py-7 sm:flex-row sm:items-center sm:justify-between sm:px-8">
            <div className="flex items-start gap-4">
              <span className="flex h-14 w-14 shrink-0 items-center justify-center rounded-2xl text-white" style={{ background: GRADIENTE_DO_TIPO.percent, boxShadow: "var(--ks-shadow-brand)" }}>
                <Ticket size={26} />
              </span>
              <div>
                <h3 className="text-xl font-extrabold tracking-tight text-[var(--ks-color-text-primary)]">Crie o primeiro cupom da loja</h3>
                <p className="mt-1 max-w-xl text-sm leading-relaxed text-[var(--ks-color-text-muted)]">
                  Desconto em porcentagem ou em reais, frete grátis, só numa categoria, só na primeira compra, com limite de usos, por link ou QR code, ou automático no carrinho.
                </p>
              </div>
            </div>
            {podeEditar ? (
              <button type="button" onClick={() => abrirNovo()} className="ks-button ks-button-primary shrink-0">
                <Plus size={16} /> Começar do zero
              </button>
            ) : null}
          </div>
          <p className="px-5 pt-5 text-[11px] font-bold uppercase tracking-[0.14em] text-[var(--ks-color-text-soft)] sm:px-8">Ou comece por um modelo</p>
          <ul className="px-2 pb-3 pt-1 sm:px-5">
            {MODELOS_DE_CUPOM.map((m) => (
              <LinhaDoModelo key={m.id} modelo={m} aoUsar={podeEditar ? () => abrirNovo(m) : undefined} />
            ))}
          </ul>
        </div>
        {extras}
      </div>
    );
  }

  return (
    <div className="space-y-4">
      {aviso ? (
        <Aviso tom={aviso.tom} aoFechar={() => setAviso(null)}>
          {aviso.texto}
        </Aviso>
      ) : null}

      <div className="overflow-hidden rounded-2xl border border-[var(--ks-color-border-subtle)] bg-white shadow-[var(--ks-shadow-subtle)]">
        {/* Os números de todos os cupons */}
        <div className="grid grid-cols-3 divide-x divide-[var(--ks-n-100)] border-b border-[var(--ks-n-100)]">
          <Numero rotulo="Usos" valor={String(totais.usos)} detalhe={`${contagem.ativo} ${contagem.ativo === 1 ? "cupom ativo" : "cupons ativos"}`} />
          <Numero rotulo="Receita" valor={reaisCurtos(totais.receita)} detalhe="pedidos confirmados" />
          <Numero rotulo="Descontos" valor={reaisCurtos(totais.desconto)} detalhe="produtos e frete" />
        </div>

        {/* A barra: busca e filtros | contadores e ações */}
        <div className="flex flex-col gap-3 border-b border-[var(--ks-n-100)] px-4 py-3.5 sm:px-5 xl:flex-row xl:items-center xl:justify-between">
          <div className="flex flex-col gap-2.5 xl:flex-row xl:items-center">
            <div className="relative w-full xl:w-64">
              <Search className="pointer-events-none absolute left-3 top-1/2 z-[1] h-4 w-4 -translate-y-1/2 text-[var(--ks-color-text-soft)]" />
              <Input placeholder="Buscar por código ou nome" value={busca} onChange={(e) => setBusca(e.target.value)} className="pl-9" aria-label="Buscar cupom" />
            </div>
            <div className="grid grid-cols-2 gap-2 xl:flex">
              <div className="min-w-0 xl:w-40">
                <CustomSelect
                  size="sm"
                  value={tipo}
                  onChange={(v) => setTipo(v as FiltroDeTipo)}
                  options={[
                    { value: "todos", label: "Todos os tipos" },
                    { value: "percent", label: "Percentual" },
                    { value: "value", label: "Valor fixo" },
                    { value: "free_shipping", label: "Frete grátis" },
                    { value: "automatic", label: "Automáticos" },
                  ]}
                />
              </div>
              <div className="min-w-0 xl:w-44">
                <CustomSelect
                  size="sm"
                  value={ordem}
                  onChange={(v) => setOrdem(v as Ordem)}
                  options={[
                    { value: "recentes", label: "Mais recentes" },
                    { value: "usos", label: "Mais usados" },
                    { value: "receita", label: "Maior receita" },
                    { value: "vencimento", label: "Vencem antes" },
                    { value: "codigo", label: "Código (A-Z)" },
                  ]}
                />
              </div>
            </div>
          </div>
          {podeEditar ? (
            <div className="relative grid grid-cols-2 gap-2 xl:flex">
              <button type="button" onClick={(e) => { e.stopPropagation(); setModelosAbertos((v) => !v); }} className="ks-button ks-button-secondary">
                <LayoutTemplate size={16} /> Modelos
              </button>
              <button type="button" onClick={() => abrirNovo()} className="ks-button ks-button-primary">
                <Plus size={16} /> Novo cupom
              </button>
              {modelosAbertos ? (
                <div onClick={(e) => e.stopPropagation()} className="absolute right-0 top-full z-30 mt-2 w-[min(400px,calc(100vw-2rem))] rounded-2xl border border-[var(--ks-color-border-subtle)] bg-white p-2 shadow-[var(--ks-shadow-overlay)]">
                  <ul>
                    {MODELOS_DE_CUPOM.map((m) => (
                      <LinhaDoModelo key={m.id} modelo={m} aoUsar={() => abrirNovo(m)} compacto />
                    ))}
                  </ul>
                </div>
              ) : null}
            </div>
          ) : null}
        </div>

        {/* Situações, como abas de filtro com a contagem */}
        <div className="flex gap-5 overflow-x-auto border-b border-[var(--ks-n-100)] px-4 sm:px-5">
          {([
            ["todos", "Todos", linhas.length],
            ["ativo", "Ativos", contagem.ativo],
            ["agendado", "Agendados", contagem.agendado],
            ["pausado", "Pausados", contagem.pausado],
            ["expirado", "Expirados", contagem.expirado],
            ["esgotado", "Esgotados", contagem.esgotado],
          ] as Array<[FiltroDeSituacao, string, number]>).map(([valor, rotulo, n]) => {
            const ativo = situacao === valor;
            return (
              <button
                key={valor}
                type="button"
                onClick={() => setSituacao(valor)}
                className={`-mb-px flex shrink-0 items-center gap-1.5 border-b-2 py-2.5 text-[13px] font-semibold transition-colors ${
                  ativo ? "border-[var(--ks-color-primary)] text-[var(--ks-color-primary)]" : "border-transparent text-[var(--ks-color-text-soft)] hover:text-[var(--ks-color-text-primary)]"
                }`}
              >
                {valor !== "todos" ? <span className={`h-1.5 w-1.5 rounded-full ${COR_DA_SITUACAO[valor].ponto}`} /> : null}
                {rotulo}
                <span className="ks-num text-xs text-[var(--ks-color-text-soft)]">{n}</span>
              </button>
            );
          })}
        </div>

        {visiveis.length === 0 ? (
          <div className="px-5 py-14 text-center">
            <p className="text-sm font-semibold text-[var(--ks-color-text-primary)]">Nenhum cupom com esse filtro.</p>
            <button
              type="button"
              onClick={() => {
                setBusca("");
                setSituacao("todos");
                setTipo("todos");
              }}
              className="mt-2 text-sm font-semibold text-[var(--ks-brand-600)] hover:underline"
            >
              Ver todos
            </button>
          </div>
        ) : (
          <div>
            <div className="hidden grid-cols-[minmax(0,1fr)_118px_130px_120px_112px_104px] gap-4 px-5 pb-2 pt-3 text-[10px] font-semibold uppercase tracking-[0.14em] text-[var(--ks-color-text-soft)] lg:grid">
              <span>Cupom</span>
              <span>Usos</span>
              <span>Receita</span>
              <span>Validade</span>
              <span>Situação</span>
              <span />
            </div>
            <ul>
              {visiveis.map(({ linha, cupom }) => {
                const m = metricas[cupom.id];
                const s = situacaoDe(cupom);
                const usos = m?.usos ?? 0;
                const pct = cupom.usage_limit ? Math.min(100, Math.round((usos / cupom.usage_limit) * 100)) : 0;
                return (
                  <li
                    key={cupom.id}
                    onClick={() => abrirEdicao(linha)}
                    className={`group grid grid-cols-[minmax(0,1fr)_auto] items-center gap-x-3 gap-y-2.5 border-t border-[var(--ks-n-100)] px-4 py-3.5 transition-colors first:border-t-0 sm:px-5 lg:grid-cols-[minmax(0,1fr)_118px_130px_120px_112px_104px] lg:gap-4 ${
                      podeEditar ? "cursor-pointer hover:bg-[var(--ks-color-bg-hover)]" : ""
                    }`}
                  >
                    <div className="flex min-w-0 items-center gap-3">
                      <IconeDoTipo cupom={cupom} />
                      <div className="min-w-0">
                        <div className="flex flex-wrap items-center gap-x-2 gap-y-1">
                          <span className="font-mono text-[14px] font-black tracking-[0.06em] text-[var(--ks-color-text-primary)]">{cupom.code}</span>
                          <span className="rounded-md bg-[var(--ks-color-bg-inset)] px-1.5 py-0.5 text-[11px] font-bold text-[var(--ks-color-text-secondary)]">{rotuloDoBeneficio(cupom)}</span>
                          {cupom.application === "automatic" ? (
                            <span className="inline-flex items-center gap-1 rounded-md bg-[var(--ks-brand-50)] px-1.5 py-0.5 text-[11px] font-bold text-[var(--ks-brand-600)]">
                              <Sparkles size={11} /> Automático
                            </span>
                          ) : null}
                          {!cupom.combinable ? (
                            <span className="inline-flex items-center rounded-md bg-[var(--ks-amber-soft)] px-1.5 py-0.5 text-[11px] font-bold text-[var(--ks-color-status-warning)]" title="Não vai junto com outro cupom">
                              Sozinho
                            </span>
                          ) : null}
                          {cupom.show_in_store ? (
                            <span className="inline-flex items-center gap-1 rounded-md bg-[var(--ks-sky-soft)] px-1.5 py-0.5 text-[11px] font-bold text-[var(--ks-color-status-info)]" title="Aparece no carrinho">
                              <Eye size={11} /> No carrinho
                            </span>
                          ) : null}
                        </div>
                        <p className="mt-0.5 line-clamp-2 text-xs leading-snug text-[var(--ks-color-text-muted)]" title={fraseDoCupom(cupom, agora, nomes)}>
                          {cupom.name ? <span className="font-semibold text-[var(--ks-color-text-secondary)]">{cupom.name} · </span> : null}
                          {fraseDoCupom(cupom, agora, nomes)}
                        </p>
                      </div>
                    </div>

                    {/* No celular, a situação fica ao lado do nome */}
                    <div className="justify-self-end lg:hidden">
                      <SeloDaSituacao situacao={s} />
                    </div>

                    <div className="col-span-2 flex flex-wrap items-center gap-x-5 gap-y-1 pl-[52px] text-xs text-[var(--ks-color-text-muted)] lg:contents lg:pl-0">
                      <div className="min-w-0">
                        <p className="text-[13px] text-[var(--ks-color-text-primary)]">
                          <span className="ks-num font-bold">{usos}</span>
                          {cupom.usage_limit ? <span className="text-[var(--ks-color-text-soft)]"> / {cupom.usage_limit}</span> : null}
                          <span className="lg:hidden"> {usos === 1 ? "uso" : "usos"}</span>
                        </p>
                        {cupom.usage_limit ? (
                          <div className="mt-1 hidden h-1 w-20 overflow-hidden rounded-full bg-[var(--ks-n-100)] lg:block">
                            <div className="h-full rounded-full" style={{ width: `${pct}%`, background: pct >= 100 ? "var(--ks-amber)" : "var(--ks-brand-500)" }} />
                          </div>
                        ) : (
                          <p className="hidden text-[11px] text-[var(--ks-color-text-soft)] lg:block">sem limite</p>
                        )}
                      </div>
                      <div className="min-w-0">
                        <p className="ks-num text-[13px] font-bold text-[var(--ks-color-text-primary)]">
                          {reaisCurtos(m?.receita ?? 0)}
                          <span className="font-normal text-[var(--ks-color-text-soft)] lg:hidden"> de receita</span>
                        </p>
                        <p className="hidden text-[11px] text-[var(--ks-color-text-soft)] lg:block">
                          {m?.desconto ? `${reaisCurtos(m.desconto)} de desconto` : `${m?.pedidos ?? 0} pedidos`}
                        </p>
                      </div>
                      <div className="flex items-center gap-1.5 text-[13px] text-[var(--ks-color-text-secondary)]">
                        <CalendarClock size={13} className="text-[var(--ks-color-text-soft)] lg:hidden" />
                        {validadeCurta(cupom, agora)}
                      </div>
                      <div className="hidden lg:block">
                        <SeloDaSituacao situacao={s} />
                      </div>
                    </div>

                    {podeEditar ? (
                      <div className="col-span-2 flex items-center justify-end gap-1 border-t border-dashed border-[var(--ks-n-100)] pt-2 lg:col-span-1 lg:border-0 lg:pt-0" onClick={(e) => e.stopPropagation()}>
                        <span className="mr-auto text-xs font-semibold text-[var(--ks-color-text-soft)] lg:hidden">{cupom.active ? "Ligado" : "Pausado"}</span>
                        <Switch checked={cupom.active} onCheckedChange={(v) => void alternar(linha, v)} aria-label={cupom.active ? `Pausar ${cupom.code}` : `Ligar ${cupom.code}`} title={cupom.active ? "Pausar" : "Ligar"} />
                        <button type="button" onClick={() => abrirEdicao(linha)} className="ks-icon-button-sm lg:hidden" aria-label={`Editar ${cupom.code}`}>
                          <Pencil size={15} />
                        </button>
                        <div className="relative">
                          <button
                            type="button"
                            onClick={(e) => {
                              e.stopPropagation();
                              setMenuDe(menuDe === cupom.id ? null : cupom.id);
                            }}
                            className="ks-icon-button-sm"
                            aria-label={`Mais ações de ${cupom.code}`}
                            aria-expanded={menuDe === cupom.id}
                          >
                            <MoreHorizontal size={16} />
                          </button>
                          {menuDe === cupom.id ? (
                            <div className="absolute right-0 top-full z-30 mt-1 w-52 rounded-xl border border-[var(--ks-color-border-subtle)] bg-white p-1 shadow-[var(--ks-shadow-overlay)]">
                              <ItemDoMenu Icone={Pencil} onClick={() => abrirEdicao(linha)}>Editar</ItemDoMenu>
                              <ItemDoMenu Icone={CopyPlus} onClick={() => duplicar(linha)}>Duplicar</ItemDoMenu>
                              {cupom.application === "code" ? (
                                <>
                                  <ItemDoMenu Icone={Link2} onClick={() => void copiarLink(cupom.code)}>Copiar link do cupom</ItemDoMenu>
                                  <ItemDoMenu Icone={QrCode} onClick={() => setQrDe(cupom.code)}>QR code</ItemDoMenu>
                                  <ItemDoMenu Icone={Copy} onClick={() => void navigator.clipboard?.writeText(cupom.code).then(() => setAviso({ tom: "bom", texto: `Código ${cupom.code} copiado.` }))}>
                                    Copiar código
                                  </ItemDoMenu>
                                </>
                              ) : null}
                              <div className="my-1 h-px bg-[var(--ks-n-100)]" />
                              <ItemDoMenu Icone={Trash2} perigo onClick={() => pedirExclusao(linha)}>Excluir</ItemDoMenu>
                            </div>
                          ) : null}
                        </div>
                      </div>
                    ) : null}
                  </li>
                );
              })}
            </ul>
          </div>
        )}
      </div>
      {extras}
    </div>
  );
}

function Numero({ rotulo, valor, detalhe }: { rotulo: string; valor: string; detalhe: string }) {
  return (
    <div className="min-w-0 px-4 py-4 sm:px-6">
      <p className="truncate text-[10px] font-bold uppercase tracking-[0.14em] text-[var(--ks-color-text-soft)]">{rotulo}</p>
      <p className="ks-num mt-1 truncate text-xl font-black tracking-tight text-[var(--ks-color-text-primary)] sm:text-2xl">{valor}</p>
      <p className="truncate text-[11px] text-[var(--ks-color-text-muted)]">{detalhe}</p>
    </div>
  );
}

function ItemDoMenu({ Icone, onClick, perigo = false, children }: { Icone: typeof Pencil; onClick: () => void; perigo?: boolean; children: React.ReactNode }) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={`flex w-full items-center gap-2.5 rounded-lg px-2.5 py-2 text-left text-[13px] font-semibold transition-colors ${
        perigo ? "text-[var(--ks-color-status-danger)] hover:bg-[var(--ks-rose-soft)]" : "text-[var(--ks-color-text-primary)] hover:bg-[var(--ks-color-bg-hover)]"
      }`}
    >
      <Icone size={15} />
      {children}
    </button>
  );
}

function LinhaDoModelo({ modelo, aoUsar, compacto = false }: { modelo: ModeloDeCupom; aoUsar?: () => void; compacto?: boolean }) {
  const exemplo = lerCupom({ id: modelo.id, ...linhaDoFormulario(modelo.montar()) });
  return (
    <li className={`flex items-center gap-3 rounded-xl ${compacto ? "px-2 py-2" : "border-t border-[var(--ks-n-100)] px-3 py-3.5 first:border-t-0"} ${aoUsar ? "cursor-pointer hover:bg-[var(--ks-color-bg-hover)]" : ""}`} onClick={aoUsar}>
      <IconeDoTipo cupom={exemplo} tamanho={compacto ? 34 : 40} />
      <div className="min-w-0 flex-1">
        <p className="text-sm font-bold text-[var(--ks-color-text-primary)]">{modelo.titulo}</p>
        <p className="text-xs leading-snug text-[var(--ks-color-text-muted)]">{modelo.texto}</p>
      </div>
      {aoUsar && !compacto ? (
        <span className="ks-button ks-button-secondary ks-button-sm shrink-0">Usar</span>
      ) : null}
    </li>
  );
}
