"use client";

import { AlignVerticalJustifyCenter, AlignVerticalJustifyEnd, AlignVerticalJustifyStart, Ban, Blend, Expand, Frame, Highlighter, List, ListChecks, ListOrdered, Palette, PenLine, Shapes, Shrink, Sparkles, Sticker, Undo2 } from "lucide-react";
import { ICONES, cantosDoContorno, conteudoDaPeca, solida, sombraDura, sombraSuave, type Forma, type FormaDoFundoDoTexto, type Peca, type PecaDeForma, type PecaDeIcone, type PecaDeImagem, type PecaDeTexto, type Sombra } from "@/lib/banner-editor/documento";
import { contornosQueSeparam, type ContornoQueSepara, type ModoDeSeparar } from "@/lib/banner-editor/separar-contorno";
import { BotaoDoPainel, CampoDeBorda, CampoDePintura, CampoDeSombra, Chave, Cor, Dica, Opcoes, Regua, Secao } from "./campos";
import { IconeDaCurva, IconeDaSombra, IconeDeSepararBorda, IconeDeSepararCheio, IconeDoContorno, IconeDoEspacamento, IconeDoFundoDoTexto } from "./icones-do-editor";
import { MolduraDaFoto } from "./paineis-novos";
import { EfeitosDaCamada } from "./paineis-pro";

/*
  Os ajustes da peça, cada um no seu lugar (nov/2026, pedido do Natan: "tudo
  tem que estar no seu devido lugar e padrão", "não pode tudo ser efeito").
  Antes, o "Efeitos" do texto juntava estilo, sombra, contorno, fundo,
  marca-texto, curva e espaçamento; o da foto, recorte, moldura, adesivo,
  duotone, sumiço e sombra; e os efeitos da camada ficavam num botão à
  parte, repetindo a sombra. Agora, para qualquer peça:
   - Contorno: a linha de cada uma (contorno da letra, borda da forma,
     moldura e adesivo da foto, traço do ícone), com os cantos e o "Separar
     contorno", e o contorno por fora (efeito da camada);
   - Sombra: a sombra de cada uma e as sombras e brilhos a mais (efeitos da
     camada);
   - e os próprios de cada tipo: espaçamento, curva, fundo e marca-texto do
     texto; a forma; o recorte da foto.
  Nenhuma função saiu: só mudou de lugar (o sumiço da foto é o mesmo da
  Transparência; o duotone foi para os Ajustes da foto).
*/

/* ---------------------------------------------------------------- formas */

const NOMES_DAS_FORMAS: Record<string, string> = {
  retangulo: "Retângulo",
  pilula: "Pílula",
  circulo: "Círculo",
  triangulo: "Triângulo",
  losango: "Losango",
  estrela: "Estrela",
  explosao: "Explosão",
  etiqueta: "Etiqueta",
  faixa: "Faixa",
  seta: "Seta",
  balao: "Balão",
  coracao: "Coração",
  onda: "Onda",
  hexagono: "Hexágono",
  pentagono: "Pentágono",
  octogono: "Octógono",
  paralelogramo: "Paralelo",
  cruz: "Cruz",
  raio: "Raio",
  nuvem: "Nuvem",
  gota: "Gota",
  semicirculo: "Meia-lua",
  anel: "Anel",
  rasgado: "Rasgado",
  fita: "Fita",
};

/** A grade das formas: cada uma desenhada (a escolhida em violeta). */
export function GradeDeFormas<T extends string>({ formas, valor, aoEscolher }: { formas: readonly T[]; valor: T | null; aoEscolher: (f: T) => void }) {
  return (
    <div className="grid grid-cols-4 gap-1">
      {formas.map((f) => {
        const amostra = {
          id: `amostra-${f}`,
          tipo: "forma",
          x: 0,
          y: 0,
          w: 44,
          h: 32,
          rot: 0,
          opacidade: 1,
          forma: (f === "pilula" ? "retangulo" : f) as Forma,
          pintura: solida(valor === f ? "#7C3AED" : "#BDB6D1"),
          raio: f === "pilula" ? 16 : 6,
          borda: null,
          sombra: null,
          pontas: f === "estrela" ? 5 : 14,
          profundidade: f === "estrela" ? 0.55 : 0.22,
        } as PecaDeForma;
        return (
          <button
            key={f}
            type="button"
            title={NOMES_DAS_FORMAS[f] || f}
            onClick={() => aoEscolher(f)}
            className={`flex flex-col items-center gap-1 rounded-[9px] border px-1 py-2 text-[10px] font-medium transition ${valor === f ? "border-[#7C3AED] text-[#5B21B6]" : "border-transparent text-[#6B6584] hover:border-[#E7E4EF] hover:bg-[#FAF9FD]"}`}
          >
            <span className="relative block h-[32px] w-[44px]" dangerouslySetInnerHTML={{ __html: conteudoDaPeca(amostra) }} />
            <span className="max-w-full truncate">{NOMES_DAS_FORMAS[f] || f}</span>
          </button>
        );
      })}
    </div>
  );
}

const FORMAS_DA_FORMA: Forma[] = ["retangulo", "circulo", "triangulo", "losango", "estrela", "explosao", "coracao", "balao", "seta", "etiqueta", "faixa", "onda", "hexagono", "pentagono", "octogono", "paralelogramo", "cruz", "raio", "nuvem", "gota", "semicirculo", "anel", "rasgado", "fita"];

/** A forma (o desenho e as medidas dele: cantos, pontas, rasgo, fita). */
export function PainelDaForma({ p, mudar }: { p: PecaDeForma; mudar: (c: Partial<PecaDeForma>) => void }) {
  return (
    <div>
      <Secao titulo="Desenho da forma" icone={Shapes}>
        <GradeDeFormas<Forma>
          formas={FORMAS_DA_FORMA}
          valor={p.forma}
          aoEscolher={(forma) => mudar({ forma, pontas: forma === "estrela" ? 5 : forma === "explosao" ? 16 : p.pontas, profundidade: forma === "estrela" ? 0.55 : forma === "explosao" ? 0.2 : p.profundidade })}
        />
      </Secao>
      {p.forma === "retangulo" || p.forma === "estrela" || p.forma === "explosao" || p.forma === "rasgado" || p.forma === "fita" ? (
        <Secao titulo="Medidas" icone={Shapes}>
          <div className="space-y-3.5">
            {p.forma === "retangulo" ? <Regua rotulo="Cantos" valor={p.raio} min={0} max={Math.round(Math.min(p.w, p.h) / 2)} aoMudar={(raio) => mudar({ raio })} padrao={0} /> : null}
            {p.forma === "estrela" || p.forma === "explosao" ? (
              <>
                <Regua rotulo="Pontas" valor={p.pontas} min={3} max={40} aoMudar={(pontas) => mudar({ pontas })} />
                <Regua rotulo="Profundidade" valor={Math.round(p.profundidade * 100)} min={3} max={80} aoMudar={(v) => mudar({ profundidade: v / 100 })} formato={(v) => `${Math.round(v)}%`} />
              </>
            ) : null}
            {p.forma === "rasgado" ? (
              <>
                <Regua rotulo="Desenho do rasgo" valor={p.pontas} min={3} max={48} aoMudar={(pontas) => mudar({ pontas })} />
                <Regua rotulo="Tamanho do rasgo" valor={Math.round(p.profundidade * 100)} min={3} max={80} aoMudar={(v) => mudar({ profundidade: v / 100 })} formato={(v) => `${Math.round(v)}%`} />
              </>
            ) : null}
            {p.forma === "fita" ? <Regua rotulo="Grossura da fita" valor={Math.round(p.profundidade * 100)} min={3} max={80} aoMudar={(v) => mudar({ profundidade: v / 100 })} formato={(v) => `${Math.round(v)}%`} /> : null}
          </div>
        </Secao>
      ) : null}
    </div>
  );
}

/* --------------------------------------------------------------- contorno */

/** As formas de caixa desenham a borda pelo CSS (sem canto de linha para escolher). */
const formaDeCaixa = (forma: string) => forma === "retangulo" || forma === "circulo" || forma === "pilula";

/** O "Separar contorno" de um dos contornos da peça (só aparece quando a peça tem esse contorno para separar). */
function separador(peca: Peca, qual: ContornoQueSepara, aoSeparar?: (qual: ContornoQueSepara, modo: ModoDeSeparar) => void) {
  return aoSeparar && contornosQueSeparam(peca).includes(qual) ? (modo: ModoDeSeparar) => aoSeparar(qual, modo) : undefined;
}

/**
 * Contorno: a linha da peça (cada tipo tem a sua) e o contorno por fora
 * (efeito da camada, até em degradê), que vale para qualquer peça.
 */
export function PainelDeContorno({ peca, mudar, aoSeparar }: { peca: Peca; mudar: (c: Partial<Peca>) => void; aoSeparar?: (qual: ContornoQueSepara, modo: ModoDeSeparar) => void }) {
  return (
    <div data-painel-contorno>
      {peca.tipo === "texto" ? (
        <Secao titulo="Contorno nas letras" icone={IconeDoContorno} ligado={Boolean(peca.contorno)} aoLigar={(v) => mudar({ contorno: v ? { cor: "#141414", largura: Math.max(2, Math.round(peca.tamanho * 0.04)) } : null } as Partial<Peca>)}>
          <CampoDeBorda valor={peca.contorno} aoMudar={(contorno) => mudar({ contorno } as Partial<Peca>)} rotulo="Contorno" semChave cantos={cantosDoContorno(peca)} buracos={!textoEmCurva(peca)} aoSeparar={separador(peca, "contorno", aoSeparar)} />
        </Secao>
      ) : null}
      {peca.tipo === "forma" ? (
        <Secao titulo={peca.nome === "Fundo" ? "Borda do fundo" : "Borda"} icone={IconeDoContorno} ligado={Boolean(peca.borda)} aoLigar={(v) => mudar({ borda: v ? { cor: "#141414", largura: 6 } : null } as Partial<Peca>)}>
          <CampoDeBorda valor={peca.borda} aoMudar={(borda) => mudar({ borda } as Partial<Peca>)} semChave cantos={formaDeCaixa(peca.forma) ? undefined : cantosDoContorno(peca)} aoSeparar={separador(peca, "borda", aoSeparar)} />
        </Secao>
      ) : null}
      {peca.tipo === "imagem" ? <ContornosDaFoto p={peca} mudar={mudar as (c: Partial<PecaDeImagem>) => void} aoSeparar={aoSeparar} /> : null}
      {peca.tipo === "icone" ? <TracoDoIcone p={peca} mudar={mudar as (c: Partial<PecaDeIcone>) => void} /> : null}
      <Secao titulo="Contorno por fora" icone={IconeDeSepararBorda} dica="Um contorno a mais em volta do desenho (até em degradê). Dá para juntar vários.">
        <EfeitosDaCamada peca={peca} mudar={mudar} tipos={["contorno"]} />
      </Secao>
    </div>
  );
}

function ContornosDaFoto({ p, mudar, aoSeparar }: { p: PecaDeImagem; mudar: (c: Partial<PecaDeImagem>) => void; aoSeparar?: (qual: ContornoQueSepara, modo: ModoDeSeparar) => void }) {
  /* A peça que já é só o contorno separado: a cor, a grossura e se mostra o anel ou a silhueta cheia. */
  if (p.silhueta && p.adesivo) {
    return (
      <Secao titulo="Contorno separado" icone={Sticker}>
        <div className="space-y-3.5">
          <Opcoes
            valor={p.silhueta}
            opcoes={[
              { valor: "borda", rotulo: "Só a borda", icone: IconeDeSepararBorda },
              { valor: "cheia", rotulo: "Preenchido", icone: IconeDeSepararCheio },
            ]}
            aoMudar={(silhueta) => mudar({ silhueta })}
          />
          <Cor rotulo="Cor do contorno" valor={p.adesivo.cor} aoMudar={(cor) => mudar({ adesivo: { ...p.adesivo!, cor } })} />
          <Regua rotulo="Grossura" valor={p.adesivo.largura} min={1} max={60} aoMudar={(largura) => mudar({ adesivo: { ...p.adesivo!, largura } })} />
        </div>
      </Secao>
    );
  }
  const comMascara = Boolean(p.mascara && p.mascara !== "retangulo" && !p.circulo);
  return (
    <>
      {/* A foto dentro de uma forma não mostra a moldura (o recorte corta). */}
      {comMascara ? null : (
        <Secao titulo="Moldura" icone={Frame} ligado={Boolean(p.borda)} aoLigar={(v) => mudar({ borda: v ? { cor: "#FFFFFF", largura: Math.max(4, Math.round(Math.min(p.w, p.h) * 0.03)) } : null })} dica="Uma borda em volta da foto, por dentro da caixa.">
          <CampoDeBorda valor={p.borda} aoMudar={(borda) => mudar({ borda })} rotulo="Moldura" semChave aoSeparar={separador(p, "moldura", aoSeparar)} />
        </Secao>
      )}
      <Secao titulo="Contorno de adesivo" icone={Sticker} ligado={Boolean(p.adesivo)} aoLigar={(v) => mudar({ adesivo: v ? { cor: "#FFFFFF", largura: Math.max(4, Math.round(Math.min(p.w, p.h) * 0.025)) } : null })} dica="Contorna o recorte (foto sem fundo, PNG) como um adesivo de papel.">
        {p.adesivo ? (
          <div className="space-y-3.5">
            <div className="flex items-end gap-2.5">
              <div className="w-[52px] shrink-0">
                <Cor compacta rotulo="Cor do contorno" valor={p.adesivo.cor} aoMudar={(cor) => mudar({ adesivo: { ...p.adesivo!, cor } })} />
              </div>
              <div className="min-w-0 flex-1">
                <Regua rotulo="Grossura" valor={p.adesivo.largura} min={1} max={60} aoMudar={(largura) => mudar({ adesivo: { ...p.adesivo!, largura } })} />
              </div>
            </div>
            {separador(p, "adesivo", aoSeparar) ? (
              <div data-separar-contorno>
                <span className="mb-1.5 block text-[12px] font-medium text-[#3F3A55]">Separar contorno</span>
                <div className="grid grid-cols-2 gap-2">
                  <BotaoDoPainel icone={IconeDeSepararBorda} aoClicar={() => aoSeparar!("adesivo", "borda")} titulo="O contorno vira uma peça própria: só o anel em volta (como aparece)" data-separar="borda">
                    Só a borda
                  </BotaoDoPainel>
                  <BotaoDoPainel icone={IconeDeSepararCheio} aoClicar={() => aoSeparar!("adesivo", "cheio")} titulo="O contorno vira uma peça própria: a silhueta inteira na cor dele" data-separar="cheio">
                    Preenchido
                  </BotaoDoPainel>
                </div>
              </div>
            ) : null}
          </div>
        ) : null}
      </Secao>
    </>
  );
}

function TracoDoIcone({ p, mudar }: { p: PecaDeIcone; mudar: (c: Partial<PecaDeIcone>) => void }) {
  /* Logo de rede (desenho oficial, já preenchido) e laço de presente não têm traço para engrossar. */
  if (!(p.desenho || !ICONES[p.icone]?.cheio)) return null;
  return (
    <Secao titulo="Traço do ícone" icone={PenLine}>
      <div className="space-y-3.5">
        <Regua rotulo="Grossura" valor={p.espessura} min={0.5} max={4} passo={0.1} aoMudar={(espessura) => mudar({ espessura })} formato={(v) => v.toFixed(1)} />
        <Chave rotulo="Preencher por dentro" ligado={p.preenchido} aoMudar={(preenchido) => mudar({ preenchido })} />
      </div>
    </Secao>
  );
}

/** O ícone tem traço para engrossar (o logo de rede e o laço de presente não). */
export const iconeTemTraco = (p: PecaDeIcone) => Boolean(p.desenho || !ICONES[p.icone]?.cheio);

/* ----------------------------------------------------------------- sombra */

const SOMBRAS: Array<{ chave: string; nome: string; valor: Sombra }> = [
  { chave: "nenhuma", nome: "Nenhuma", valor: null },
  { chave: "suave", nome: "Suave", valor: sombraSuave() },
  { chave: "marcada", nome: "Marcada", valor: sombraDura() },
  { chave: "longa", nome: "Longa", valor: { cor: "#000000", x: 10, y: 12, desfoque: 0, opacidade: 0.45 } },
  { chave: "brilho", nome: "Brilho", valor: { cor: "#FFFFFF", x: 0, y: 0, desfoque: 30, opacidade: 0.85 } },
];

function amostraDeLetra(s: Sombra) {
  const filtro = s ? `drop-shadow(${s.x / 3}px ${s.y / 3}px ${s.desfoque / 6}px rgba(${s.cor === "#FFFFFF" ? "255,255,255" : s.cor === "#FF2D87" ? "255,45,135" : "0,0,0"},${s.opacidade}))` : "none";
  const cor = s?.cor === "#FFFFFF" || s?.cor === "#FF2D87" ? "#7C3AED" : "#1F1B2E";
  return `<span style="font:900 24px Montserrat,sans-serif;color:${cor};filter:${filtro}">Ag</span>`;
}

function CartoesDeSombra({ valor, aoMudar }: { valor: Sombra; aoMudar: (s: Sombra) => void }) {
  const igual = (a: Sombra, b: Sombra) => (!a && !b) || (a && b && a.x === b.x && a.y === b.y && a.desfoque === b.desfoque && a.cor === b.cor);
  return (
    <div className="grid grid-cols-5 gap-1.5">
      {SOMBRAS.map((s) => (
        <button key={s.chave} type="button" title={s.nome} onClick={() => aoMudar(s.valor)} className="group text-center">
          <span className={`flex h-[46px] items-center justify-center rounded-[9px] border bg-[#FAF9FD] transition ${igual(valor, s.valor) ? "border-[#7C3AED]" : "border-[#EEEBF5] group-hover:border-[#C4B5FD]"}`} dangerouslySetInnerHTML={{ __html: amostraDeLetra(s.valor) }} />
          <span className="mt-1 block truncate text-[10.5px] font-medium text-[#4B4760]">{s.nome}</span>
        </button>
      ))}
    </div>
  );
}

/** Sombra: a sombra da peça (as que têm) e as sombras e brilhos a mais (efeitos da camada, para qualquer peça). */
export function PainelDeSombra({ peca, mudar }: { peca: Peca; mudar: (c: Partial<Peca>) => void }) {
  const temSombra = peca.tipo === "texto" || peca.tipo === "forma" || peca.tipo === "imagem" || peca.tipo === "icone" || peca.tipo === "traco";
  const sombra = temSombra ? (peca as { sombra: Sombra }).sombra : null;
  return (
    <div data-painel-sombra>
      {temSombra ? (
        <Secao titulo="Sombra" icone={IconeDaSombra}>
          {peca.tipo === "texto" ? (
            <div className="space-y-3.5">
              <CartoesDeSombra valor={sombra} aoMudar={(s) => mudar({ sombra: s } as Partial<Peca>)} />
              {sombra ? <CampoDeSombra valor={sombra} aoMudar={(s) => mudar({ sombra: s } as Partial<Peca>)} /> : null}
            </div>
          ) : (
            <CampoDeSombra valor={sombra} aoMudar={(s) => mudar({ sombra: s } as Partial<Peca>)} />
          )}
        </Secao>
      ) : null}
      <Secao titulo="Mais sombras e brilhos" icone={Sparkles} dica="Junte quantos quiser na mesma peça: sombra e brilho por fora, sombra por dentro.">
        <EfeitosDaCamada peca={peca} mudar={mudar} tipos={["sombra", "brilho", "sombra-interna"]} />
      </Secao>
    </div>
  );
}

/* ------------------------------------------------------------------ texto */

/** O texto em curva: o espaço entre linhas, a posição na caixa e a lista não valem (é uma linha só no arco). */
export const textoEmCurva = (p: PecaDeTexto) => Boolean(p.curva && Math.abs(p.curva) >= 1);

/** Espaçamento e parágrafo: entre letras, entre linhas, onde o texto fica na caixa e a lista. */
export function PainelDoEspacamento({ p, mudar }: { p: PecaDeTexto; mudar: (c: Partial<PecaDeTexto>) => void }) {
  const curva = textoEmCurva(p);
  return (
    <div>
      <Secao titulo="Espaçamento" icone={IconeDoEspacamento}>
        <div className="space-y-3.5">
          <Regua rotulo="Entre letras" valor={p.espaco} min={-0.1} max={0.6} passo={0.01} aoMudar={(espaco) => mudar({ espaco })} formato={(v) => v.toFixed(2)} padrao={0} />
          {curva ? null : <Regua rotulo="Entre linhas" valor={p.linha} min={0.7} max={2} passo={0.05} aoMudar={(linha) => mudar({ linha })} formato={(v) => v.toFixed(2)} />}
        </div>
      </Secao>
      {curva ? (
        <Secao titulo="Parágrafo" icone={List}>
          <Dica>Texto em curva fica numa linha só: a posição na caixa e a lista voltam quando ele fica reto.</Dica>
        </Secao>
      ) : (
        <>
          <Secao titulo="Posição na caixa" icone={AlignVerticalJustifyCenter}>
            <Opcoes
              valor={p.vertical}
              opcoes={[
                { valor: "topo", rotulo: "No alto", icone: AlignVerticalJustifyStart },
                { valor: "meio", rotulo: "No meio", icone: AlignVerticalJustifyCenter },
                { valor: "base", rotulo: "Embaixo", icone: AlignVerticalJustifyEnd },
              ]}
              aoMudar={(vertical) => mudar({ vertical })}
            />
          </Secao>
          <Secao titulo="Lista" icone={List} dica="Cada linha do texto (Enter) vira um item.">
            <Opcoes
              valor={p.lista || "nenhuma"}
              opcoes={[
                { valor: "nenhuma", rotulo: "Sem", icone: Ban },
                { valor: "pontos", rotulo: "Pontos", icone: List },
                { valor: "numeros", rotulo: "Números", icone: ListOrdered },
                { valor: "checks", rotulo: "Checks", icone: ListChecks },
              ]}
              aoMudar={(v) => mudar({ lista: v === "nenhuma" ? null : v })}
            />
          </Secao>
        </>
      )}
    </div>
  );
}

/** Curva: para cima arqueia, para baixo sorri; no 100 fecha o círculo (selo). */
export function PainelDaCurva({ p, mudar }: { p: PecaDeTexto; mudar: (c: Partial<PecaDeTexto>) => void }) {
  return (
    <div>
      <Secao
        titulo="Curva"
        icone={IconeDaCurva}
        acao={
          p.curva ? (
            <button type="button" title="Deixar o texto reto" onClick={() => mudar({ curva: 0 })} className="flex h-7 items-center gap-1 rounded-[7px] px-2 text-[11.5px] font-semibold text-[#6D28D9] hover:bg-[#F5F3FF]">
              <Undo2 size={13} /> Reto
            </button>
          ) : null
        }
      >
        <div className="space-y-3">
          <Regua rotulo="Curvar o texto" valor={p.curva ?? 0} min={-100} max={100} aoMudar={(curva) => mudar({ curva: Math.abs(curva) < 2 ? 0 : curva })} formato={(v) => (Math.round(v) === 100 ? "Círculo" : `${Math.round(v)}`)} padrao={0} />
          <Dica>Para cima arqueia, para baixo sorri. No 100 o texto fecha o círculo (selo).</Dica>
        </div>
      </Secao>
    </div>
  );
}

const FORMAS_DO_FUNDO: FormaDoFundoDoTexto[] = ["pilula", "retangulo", "circulo", "explosao", "estrela", "etiqueta", "faixa", "balao", "seta", "rasgado"];

/** Fundo do texto: a forma atrás do texto (botão, selo, etiqueta de preço, faixa). */
export function PainelDoFundoDoTexto({ p, mudar }: { p: PecaDeTexto; mudar: (c: Partial<PecaDeTexto>) => void }) {
  const fundo = p.fundo;
  return (
    <div>
      <Secao
        titulo="Fundo do texto"
        icone={IconeDoFundoDoTexto}
        ligado={Boolean(fundo)}
        aoLigar={(v) => mudar({ fundo: v ? { forma: "pilula", pintura: solida("#FFD400"), borda: null, raio: 16, pontas: 16, profundidade: 0.2 } : null })}
        dica="O texto vira botão, selo, etiqueta de preço ou faixa."
      >
        {fundo ? (
          <div className="space-y-3.5">
            <GradeDeFormas<FormaDoFundoDoTexto>
              formas={FORMAS_DO_FUNDO}
              valor={fundo.forma}
              aoEscolher={(forma) => mudar({ fundo: { ...fundo, forma, pontas: forma === "estrela" ? 5 : forma === "explosao" ? 16 : fundo.pontas, profundidade: forma === "estrela" ? 0.55 : forma === "explosao" ? 0.2 : fundo.profundidade } })}
            />
            {fundo.forma === "retangulo" ? <Regua rotulo="Cantos" valor={fundo.raio} min={0} max={200} aoMudar={(raio) => mudar({ fundo: { ...fundo, raio } })} padrao={0} /> : null}
            {fundo.forma === "explosao" || fundo.forma === "estrela" ? (
              <>
                <Regua rotulo="Pontas" valor={fundo.pontas} min={3} max={40} aoMudar={(pontas) => mudar({ fundo: { ...fundo, pontas } })} />
                <Regua rotulo="Profundidade" valor={Math.round(fundo.profundidade * 100)} min={3} max={80} aoMudar={(v) => mudar({ fundo: { ...fundo, profundidade: v / 100 } })} formato={(v) => `${Math.round(v)}%`} />
              </>
            ) : null}
            {fundo.forma === "rasgado" ? (
              <>
                <Regua rotulo="Desenho do rasgo" valor={fundo.pontas} min={3} max={48} aoMudar={(pontas) => mudar({ fundo: { ...fundo, pontas } })} />
                <Regua rotulo="Tamanho do rasgo" valor={Math.round(fundo.profundidade * 100)} min={3} max={80} aoMudar={(v) => mudar({ fundo: { ...fundo, profundidade: v / 100 } })} formato={(v) => `${Math.round(v)}%`} />
              </>
            ) : null}
          </div>
        ) : null}
      </Secao>
      {fundo ? (
        <>
          <Secao titulo="Cor do fundo" icone={Palette}>
            <CampoDePintura valor={fundo.pintura} aoMudar={(pintura) => mudar({ fundo: { ...fundo, pintura } })} rotulo="Cor do fundo" permiteSem />
          </Secao>
          <Secao titulo="Borda do fundo" icone={IconeDoContorno} ligado={Boolean(fundo.borda)} aoLigar={(v) => mudar({ fundo: { ...fundo, borda: v ? { cor: "#141414", largura: 4 } : null } })}>
            <CampoDeBorda valor={fundo.borda} aoMudar={(borda) => mudar({ fundo: { ...fundo, borda } })} rotulo="Borda do fundo" semChave cantos={formaDeCaixa(fundo.forma) ? undefined : (fundo.borda?.cantos ?? "redondos")} />
          </Secao>
        </>
      ) : null}
    </div>
  );
}

/** Marca-texto: a faixa de cor atrás de cada linha (acompanha a quebra do texto). */
export function PainelDoMarcaTexto({ p, mudar }: { p: PecaDeTexto; mudar: (c: Partial<PecaDeTexto>) => void }) {
  return (
    <div>
      <Secao titulo="Marca-texto nas linhas" icone={Highlighter} ligado={Boolean(p.destaque)} aoLigar={(v) => mudar({ destaque: v ? { pintura: solida("#FFFFFF"), respiro: 0.25, raio: 0 } : null })} dica="Uma faixa de cor atrás de cada linha, que acompanha a quebra do texto.">
        {p.destaque ? (
          <div className="space-y-3.5">
            <CampoDePintura valor={p.destaque.pintura} aoMudar={(pintura) => mudar({ destaque: { ...p.destaque!, pintura } })} rotulo="Cor do marca-texto" />
            <Regua rotulo="Folga dos lados" valor={Math.round(p.destaque.respiro * 100)} min={0} max={120} aoMudar={(v) => mudar({ destaque: { ...p.destaque!, respiro: v / 100 } })} formato={(v) => `${(v / 100).toFixed(2)}`} />
            <Regua rotulo="Cantos" valor={p.destaque.raio} min={0} max={Math.round(p.tamanho)} aoMudar={(raio) => mudar({ destaque: { ...p.destaque!, raio } })} padrao={0} />
          </div>
        ) : null}
      </Secao>
    </div>
  );
}

/* ------------------------------------------------------------------- foto */

/** Recorte da foto: inteira ou preenchendo, cantos, a foto dentro de uma forma e o enquadre. */
export function PainelDoRecorte({ p, mudar, aoEnquadrar }: { p: PecaDeImagem; mudar: (c: Partial<PecaDeImagem>) => void; aoEnquadrar?: () => void }) {
  return (
    <div>
      <Secao titulo="Na caixa" icone={Expand}>
        <div className="space-y-3.5">
          <Opcoes
            valor={p.ajuste}
            opcoes={[
              { valor: "conter", rotulo: "Inteira", icone: Shrink, titulo: "A foto inteira dentro da caixa" },
              { valor: "cobrir", rotulo: "Preencher", icone: Expand, titulo: "A foto cobre a caixa (corta o que sobra)" },
            ]}
            aoMudar={(ajuste) => mudar({ ajuste })}
          />
          {!p.circulo && !p.mascara ? <Regua rotulo="Cantos" valor={p.raio} min={0} max={Math.round(Math.min(p.w, p.h) / 2)} aoMudar={(raio) => mudar({ raio })} padrao={0} /> : null}
        </div>
      </Secao>
      <MolduraDaFoto p={p} mudar={mudar} GradeDeFormas={GradeDeFormas} aoEnquadrar={aoEnquadrar} />
    </div>
  );
}

const DUOTONES: Array<{ escuro: string; claro: string }> = [
  { escuro: "#3B0A2A", claro: "#FF9FCB" },
  { escuro: "#14213D", claro: "#7FDBFF" },
  { escuro: "#1E1B4B", claro: "#C4B5FD" },
  { escuro: "#052E16", claro: "#A3E635" },
  { escuro: "#431407", claro: "#FDBA74" },
  { escuro: "#111111", claro: "#F5F5F5" },
];

/** Duas cores (duotone): o escuro da foto vira uma cor, o claro vira outra. Fica nos Ajustes da foto (é tratamento de cor). */
export function SecaoDoDuotone({ p, mudar }: { p: PecaDeImagem; mudar: (c: Partial<PecaDeImagem>) => void }) {
  return (
    <Secao titulo="Duas cores (duotone)" icone={Blend} ligado={Boolean(p.duotone)} aoLigar={(v) => mudar({ duotone: v ? DUOTONES[0] : null })} dica="Pinta a foto com duas cores: o escuro vira uma, o claro vira a outra.">
      {p.duotone ? (
        <div className="space-y-3.5" data-duotone>
          <div className="grid grid-cols-6 gap-2">
            {DUOTONES.map((d) => (
              <button
                key={`${d.escuro}${d.claro}`}
                type="button"
                title="Usar estas duas cores"
                onClick={() => mudar({ duotone: d })}
                className={`h-9 rounded-[9px] ring-1 ring-black/10 transition hover:scale-110 ${p.duotone?.escuro === d.escuro && p.duotone?.claro === d.claro ? "ring-2 ring-[#7C3AED] ring-offset-2" : ""}`}
                style={{ background: `linear-gradient(135deg, ${d.escuro} 50%, ${d.claro} 50%)` }}
              />
            ))}
          </div>
          <div className="grid grid-cols-2 gap-2">
            <Cor rotulo="Sombras" valor={p.duotone.escuro} aoMudar={(escuro) => mudar({ duotone: { ...p.duotone!, escuro } })} />
            <Cor rotulo="Luzes" valor={p.duotone.claro} aoMudar={(claro) => mudar({ duotone: { ...p.duotone!, claro } })} />
          </div>
        </div>
      ) : null}
    </Secao>
  );
}

/* --------------------------------------------------- o que está ligado */

/** O que está ligado na peça (para a barra mostrar o pontinho no botão de cada coisa). */
export function ligadosNaPeca(p: Peca) {
  const efeitos = p.efeitos || [];
  const contorno =
    efeitos.some((e) => e.tipo === "contorno") ||
    (p.tipo === "texto" && Boolean(p.contorno)) ||
    (p.tipo === "forma" && Boolean(p.borda)) ||
    (p.tipo === "imagem" && Boolean(p.borda || p.adesivo));
  const sombra = efeitos.some((e) => e.tipo !== "contorno") || Boolean((p as { sombra?: Sombra }).sombra);
  return {
    contorno,
    sombra,
    fundo: p.tipo === "texto" && Boolean(p.fundo),
    marcaTexto: p.tipo === "texto" && Boolean(p.destaque),
    curva: p.tipo === "texto" && textoEmCurva(p),
    estilo: p.tipo === "texto" && Boolean(p.efeito || (p.pintura.tipo === "nenhuma" && p.contorno)),
    espacamento: p.tipo === "texto" && (Math.abs(p.espaco) > 0.001 || Boolean(p.lista)),
    recorte: p.tipo === "imagem" && Boolean(p.circulo || (p.mascara && p.mascara !== "retangulo") || p.raio > 0 || (p.enquadre && p.enquadre.zoom > 1.001)),
    ajustes: p.tipo === "imagem" && Boolean(p.duotone || filtrosMexidos(p.filtros)),
    reticulaViva: Boolean(p.reticulaViva),
  };
}

/* Algum ajuste da foto fora do original (brilho, contraste, saturação, desfoque e os que só entram quando mexidos). */
function filtrosMexidos(f: PecaDeImagem["filtros"]) {
  return f.brilho !== 100 || f.contraste !== 100 || f.saturacao !== 100 || f.desfoque !== 0 || Boolean(f.exposicao || f.temperatura || f.matiz || f.pretos || f.nitidez || f.vinheta || f.sobreposicao || (f.gama && f.gama !== 1) || (f.brancos !== undefined && f.brancos !== 255));
}

