// backoffice.jsx — admin editor panel

// Comprime imagem para base64 WebP adequado para mobile (max 720px)
async function compressImage(file, maxWidth = 720, quality = 0.82) {
  return new Promise(resolve => {
    const img = new Image();
    const url = URL.createObjectURL(file);
    img.onload = () => {
      URL.revokeObjectURL(url);
      const scale = Math.min(1, maxWidth / img.width);
      const canvas = document.createElement('canvas');
      canvas.width = Math.round(img.width * scale);
      canvas.height = Math.round(img.height * scale);
      canvas.getContext('2d').drawImage(img, 0, 0, canvas.width, canvas.height);
      resolve(canvas.toDataURL('image/webp', quality));
    };
    img.src = url;
  });
}

// ────────────────────────────────────────────────────────────
// Reusable primitives
// ────────────────────────────────────────────────────────────
const inputBase = {
  width: '100%', padding: '11px 13px', borderRadius: 10,
  border: '1px solid var(--line)', background: 'var(--field)',
  fontSize: 14, color: 'var(--ink)', outline: 'none',
  transition: 'border-color 120ms, background 120ms',
};

function Field({ label, hint, children, full = true }) {
  return (
    <label style={{ display: 'flex', flexDirection: 'column', gap: 6, flex: full ? 1 : undefined }}>
      <span style={{ fontSize: 12, fontWeight: 600, color: 'var(--ink-2)', letterSpacing: '-0.005em' }}>{label}</span>
      {children}
      {hint && <span style={{ fontSize: 11, color: 'var(--ink-3)' }}>{hint}</span>}
    </label>
  );
}

function TextInput({ value, onChange, placeholder, multiline = false }) {
  const [focused, setFocused] = React.useState(false);
  const Comp = multiline ? 'textarea' : 'input';
  return (
    <Comp
      value={value || ''}
      onChange={e => onChange(e.target.value)}
      placeholder={placeholder}
      onFocus={() => setFocused(true)}
      onBlur={() => setFocused(false)}
      rows={multiline ? 3 : undefined}
      style={{
        ...inputBase,
        borderColor: focused ? 'var(--ink)' : 'var(--line)',
        background: focused ? '#fff' : 'var(--field)',
        resize: multiline ? 'vertical' : 'none',
        fontFamily: 'inherit',
        minHeight: multiline ? 72 : undefined,
      }}
    />
  );
}

function NumberInput({ value, onChange, placeholder }) {
  const [focused, setFocused] = React.useState(false);
  return (
    <input
      type="number"
      value={value ?? ''}
      onChange={e => onChange(e.target.value === '' ? null : Number(e.target.value))}
      placeholder={placeholder}
      onFocus={() => setFocused(true)}
      onBlur={() => setFocused(false)}
      style={{ ...inputBase, borderColor: focused ? 'var(--ink)' : 'var(--line)', background: focused ? '#fff' : 'var(--field)' }}
    />
  );
}

function Section({ title, subtitle, children, right }) {
  return (
    <section style={{
      background: 'var(--panel)', borderRadius: 'var(--radius-lg)',
      border: '1px solid var(--line)',
      padding: '22px 24px',
      display: 'flex', flexDirection: 'column', gap: 16,
    }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', gap: 12 }}>
        <div style={{ flex: 1 }}>
          <h2 style={{
            margin: 0, fontSize: 15, fontWeight: 700, letterSpacing: '-0.01em', color: 'var(--ink)',
          }}>{title}</h2>
          {subtitle && (
            <p style={{ margin: '3px 0 0', fontSize: 13, color: 'var(--ink-3)', fontWeight: 500 }}>{subtitle}</p>
          )}
        </div>
        {right}
      </div>
      {children}
    </section>
  );
}

// ────────────────────────────────────────────────────────────
// Style picker (4 cards)
// ────────────────────────────────────────────────────────────
function StylePicker({ value, onChange }) {
  const options = [
    {
      id: 'classic', name: 'Clássico',
      desc: 'Lista vertical de botões. Limpo, direto, ideal para quem tem poucos links importantes.',
      preview: <ClassicPreview />,
    },
    {
      id: 'bento', name: 'Bento',
      desc: 'Grade modular com tamanhos variados. Visual moderno e versátil para mostrar tudo de uma vez.',
      preview: <BentoPreview />,
    },
    {
      id: 'catalog', name: 'Catálogo',
      desc: 'Cards de produto com foto, preço e botão de compra. Para vender direto da bio.',
      preview: <CatalogPreview />,
    },
    {
      id: 'mural', name: 'Mural',
      desc: 'Grid editorial com cards coloridos individualmente. Cada card tem cor e tamanho próprios.',
      preview: <MuralPreview />,
    },
  ];
  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 12 }}>
      {options.map(opt => {
        const active = value === opt.id;
        return (
          <button key={opt.id} onClick={() => onChange(opt.id)} style={{
            background: active ? 'var(--accent-soft)' : 'var(--field)',
            border: active ? '1.5px solid var(--ink)' : '1.5px solid var(--line)',
            borderRadius: 14, padding: 14, textAlign: 'left',
            display: 'flex', flexDirection: 'column', gap: 10,
            transition: 'all 140ms',
          }}>
            <div style={{
              height: 96, borderRadius: 8, background: '#fff',
              border: '1px solid var(--line)', overflow: 'hidden',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              padding: 8,
            }}>{opt.preview}</div>
            <div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                <span style={{ fontSize: 14, fontWeight: 700, letterSpacing: '-0.01em' }}>{opt.name}</span>
                {active && (
                  <span style={{
                    background: 'var(--ink)', color: '#fff', borderRadius: 999,
                    padding: '2px 6px', fontSize: 9, fontWeight: 700, letterSpacing: '0.05em',
                  }}>ATIVO</span>
                )}
              </div>
              <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginTop: 4, lineHeight: 1.4 }}>{opt.desc}</div>
            </div>
          </button>
        );
      })}
    </div>
  );
}

// Tiny preview thumbnails (visual hint of each style)
function ClassicPreview() {
  return (
    <svg viewBox="0 0 80 80" style={{ width: '100%', height: '100%' }}>
      <circle cx="40" cy="14" r="6" fill="#d8d2c5"/>
      <rect x="28" y="24" width="24" height="2.5" rx="1.25" fill="#1f1d18"/>
      <rect x="32" y="30" width="16" height="1.5" rx="0.75" fill="#8a8479"/>
      {[40, 50, 60, 70].map(y => (
        <rect key={y} x="14" y={y - 4} width="52" height="7" rx="2.5" fill="#f0ebe1" stroke="#d8d2c5" strokeWidth="0.5"/>
      ))}
    </svg>
  );
}
function BentoPreview() {
  return (
    <svg viewBox="0 0 80 80" style={{ width: '100%', height: '100%' }}>
      <circle cx="40" cy="10" r="5" fill="#d8d2c5"/>
      <rect x="30" y="18" width="20" height="2" rx="1" fill="#1f1d18"/>
      <rect x="14" y="26" width="22" height="22" rx="3" fill="#f0ebe1" stroke="#d8d2c5" strokeWidth="0.5"/>
      <rect x="44" y="26" width="22" height="22" rx="3" fill="#f0ebe1" stroke="#d8d2c5" strokeWidth="0.5"/>
      <rect x="14" y="52" width="52" height="18" rx="3" fill="#1f1d18"/>
    </svg>
  );
}
function MuralPreview() {
  return (
    <svg viewBox="0 0 80 80" style={{ width: '100%', height: '100%' }}>
      <circle cx="16" cy="11" r="5" fill="#d8d2c5"/>
      <rect x="24" y="8" width="22" height="3" rx="1.5" fill="#1f1d18"/>
      <rect x="24" y="14" width="14" height="2" rx="1" fill="#8a8479"/>
      <rect x="8" y="24" width="30" height="48" rx="3" fill="#c9a227"/>
      <rect x="42" y="24" width="30" height="22" rx="3" fill="#2b6b41"/>
      <rect x="42" y="50" width="30" height="22" rx="3" fill="#7a1f2a"/>
    </svg>
  );
}
function CatalogPreview() {
  return (
    <svg viewBox="0 0 80 80" style={{ width: '100%', height: '100%' }}>
      <circle cx="40" cy="10" r="5" fill="#d8d2c5"/>
      <rect x="30" y="18" width="20" height="2" rx="1" fill="#1f1d18"/>
      <rect x="14" y="26" width="52" height="44" rx="3" fill="#fff" stroke="#d8d2c5" strokeWidth="0.5"/>
      <rect x="18" y="30" width="44" height="22" rx="2" fill="#e6dfd0"/>
      <rect x="20" y="56" width="22" height="2" rx="1" fill="#1f1d18"/>
      <rect x="20" y="60" width="14" height="1.5" rx="0.75" fill="#8a8479"/>
      <rect x="48" y="58" width="14" height="6" rx="3" fill="#1f1d18"/>
    </svg>
  );
}

// ────────────────────────────────────────────────────────────
// Palette picker (+ custom pickers when 'custom' selected)
// ────────────────────────────────────────────────────────────
function PalettePicker({ value, onChange, customColors, onCustomChange }) {
  const ids = Object.keys(window.PALETTES);
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(6, 1fr)', gap: 10 }}>
        {ids.map(id => {
          const p = window.PALETTES[id];
          const active = value === id;
          return (
            <button key={id} onClick={() => onChange(id)} style={{
              display: 'flex', flexDirection: 'column', gap: 6,
              padding: 8, borderRadius: 12,
              border: active ? '1.5px solid var(--ink)' : '1.5px solid var(--line)',
              background: active ? 'var(--accent-soft)' : 'var(--field)',
              transition: 'all 120ms',
            }}>
              <div style={{
                height: 48, borderRadius: 8, background: p.bg, position: 'relative',
                border: `1px solid ${p.ink}15`, overflow: 'hidden',
              }}>
                <div style={{ position: 'absolute', inset: 8, borderRadius: 4, background: p.surface, border: `1px solid ${p.ink}10` }} />
                <div style={{ position: 'absolute', bottom: 6, right: 6, width: 12, height: 12, borderRadius: '50%', background: p.cta }} />
              </div>
              <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--ink-2)', textAlign: 'center' }}>{p.name}</div>
            </button>
          );
        })}
        {/* Custom palette swatch */}
        <CustomPaletteSwatch active={value === 'custom'} colors={customColors} onClick={() => onChange('custom')} />
      </div>
      {value === 'custom' && (
        <CustomPaletteEditor colors={customColors} onChange={onCustomChange} />
      )}
    </div>
  );
}

function CustomPaletteSwatch({ active, colors, onClick }) {
  return (
    <button onClick={onClick} style={{
      display: 'flex', flexDirection: 'column', gap: 6,
      padding: 8, borderRadius: 12,
      border: active ? '1.5px solid var(--ink)' : '1.5px solid var(--line)',
      background: active ? 'var(--accent-soft)' : 'var(--field)',
      transition: 'all 120ms',
    }}>
      <div style={{
        height: 48, borderRadius: 8, position: 'relative', overflow: 'hidden',
        background: `conic-gradient(from 210deg, ${colors?.bg || '#f3eee4'}, ${colors?.surface || '#fff'}, ${colors?.accent || '#1f1b14'}, ${colors?.bg || '#f3eee4'})`,
        border: '1px solid var(--line-2)',
      }}>
        <div style={{
          position: 'absolute', inset: 14, borderRadius: '50%', background: '#fff',
          display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--ink-2)',
          fontSize: 14, fontWeight: 700, letterSpacing: '-0.02em',
        }}>+</div>
      </div>
      <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--ink-2)', textAlign: 'center' }}>Personalizado</div>
    </button>
  );
}

function CustomPaletteEditor({ colors, onChange }) {
  const c = colors || {};
  const set = (key, value) => onChange({ ...c, [key]: value });
  const slots = [
    { key: 'bg', label: 'Fundo', hint: 'Cor de trás da página' },
    { key: 'surface', label: 'Cards', hint: 'Fundo dos botões/cards' },
    { key: 'ink', label: 'Texto', hint: 'Cor principal do texto' },
    { key: 'accent', label: 'Botão', hint: 'CTAs e destaques' },
  ];
  return (
    <div style={{
      display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 10,
      padding: 14, background: 'var(--field)', borderRadius: 12, border: '1px solid var(--line)',
    }}>
      {slots.map(s => (
        <label key={s.key} style={{ display: 'flex', flexDirection: 'column', gap: 6, cursor: 'pointer' }}>
          <span style={{ fontSize: 11, fontWeight: 600, color: 'var(--ink-2)' }}>{s.label}</span>
          <div style={{
            display: 'flex', alignItems: 'center', gap: 8,
            background: '#fff', border: '1px solid var(--line)', borderRadius: 10, padding: '6px 8px 6px 6px',
          }}>
            <div style={{
              width: 32, height: 32, borderRadius: 7, position: 'relative', overflow: 'hidden',
              background: c[s.key] || '#000', border: '1px solid rgba(0,0,0,0.1)',
            }}>
              <input type="color" value={c[s.key] || '#000000'} onChange={e => set(s.key, e.target.value)}
                style={{ position: 'absolute', inset: 0, opacity: 0, cursor: 'pointer', border: 'none' }} />
            </div>
            <span className="mono" style={{ fontSize: 11, color: 'var(--ink-2)', textTransform: 'uppercase' }}>{c[s.key]}</span>
          </div>
          <span style={{ fontSize: 10.5, color: 'var(--ink-3)', lineHeight: 1.3 }}>{s.hint}</span>
        </label>
      ))}
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// Background image editor
// ────────────────────────────────────────────────────────────
function BackgroundEditor({ background, onChange, palette }) {
  const I = window.Icon;
  const fileRef = React.useRef(null);
  const [dragOver, setDragOver] = React.useState(false);

  const handleFile = async (file) => {
    if (!file || !file.type.startsWith('image/')) return;
    const compressed = await compressImage(file, 1280, 0.82);
    onChange({ ...background, image: compressed });
  };
  const onDrop = (e) => {
    e.preventDefault(); setDragOver(false);
    handleFile(e.dataTransfer.files?.[0]);
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      <input ref={fileRef} type="file" accept="image/*" style={{ display: 'none' }}
        onChange={e => handleFile(e.target.files?.[0])} />

      {!background.image ? (
        <button
          onClick={() => fileRef.current?.click()}
          onDragOver={e => { e.preventDefault(); setDragOver(true); }}
          onDragLeave={() => setDragOver(false)}
          onDrop={onDrop}
          style={{
            border: `1.5px dashed ${dragOver ? 'var(--ink)' : 'var(--line-2)'}`,
            background: dragOver ? 'var(--accent-soft)' : 'var(--field)',
            borderRadius: 14, padding: '32px 20px',
            display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8,
            transition: 'all 140ms',
          }}
        >
          <div style={{
            width: 44, height: 44, borderRadius: 12, background: 'var(--panel)',
            border: '1px solid var(--line)',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}>
            <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
              <rect x="3" y="5" width="18" height="14" rx="2"/>
              <circle cx="9" cy="11" r="1.5"/>
              <path d="M21 16l-5-5L7 19"/>
            </svg>
          </div>
          <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--ink)' }}>Adicionar imagem de fundo</div>
          <div style={{ fontSize: 11.5, color: 'var(--ink-3)' }}>Arraste aqui ou clique para escolher · JPG/PNG/WebP</div>
        </button>
      ) : (
        <div style={{
          position: 'relative', borderRadius: 14, overflow: 'hidden',
          border: '1px solid var(--line)', height: 200,
          background: palette.bg,
        }}>
          {/* Preview that mirrors the rendering */}
          <div style={{
            position: 'absolute', inset: 0,
            backgroundImage: `url(${background.image})`,
            backgroundSize: 'cover', backgroundPosition: 'center',
            opacity: background.opacity,
            filter: `blur(${background.blur}px) saturate(1.15)`,
          }} />
          <div style={{
            position: 'absolute', inset: 0,
            display: 'flex', alignItems: 'flex-end',
            padding: 12,
            background: `linear-gradient(to top, ${palette.bg}88, transparent 40%)`,
          }}>
            <div style={{ fontSize: 11, color: palette.ink, fontWeight: 600, opacity: 0.7 }}>
              Como aparece com a paleta atual
            </div>
          </div>
          <button onClick={() => onChange({ ...background, image: null })} style={{
            position: 'absolute', top: 10, right: 10,
            background: 'rgba(0,0,0,0.55)', color: '#fff',
            padding: '6px 10px', borderRadius: 999,
            fontSize: 11, fontWeight: 600, backdropFilter: 'blur(6px)',
            display: 'flex', alignItems: 'center', gap: 5,
          }}>
            <I.trash size={12} stroke="#fff" /> Remover
          </button>
          <button onClick={() => fileRef.current?.click()} style={{
            position: 'absolute', top: 10, left: 10,
            background: 'rgba(255,255,255,0.85)', color: 'var(--ink)',
            padding: '6px 10px', borderRadius: 999,
            fontSize: 11, fontWeight: 600, backdropFilter: 'blur(6px)',
          }}>Trocar imagem</button>
        </div>
      )}

      {background.image && (
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
          <Slider
            label="Intensidade" hint="0% = invisível, 100% = imagem cheia"
            value={Math.round((background.opacity ?? 0.5) * 100)} min={0} max={100}
            onChange={v => onChange({ ...background, opacity: v / 100 })}
            suffix="%"
          />
          <Slider
            label="Desfoque" hint="Mais desfoque = atmosfera; menos = foto nítida"
            value={background.blur ?? 0} min={0} max={40}
            onChange={v => onChange({ ...background, blur: v })}
            suffix="px"
          />
        </div>
      )}
    </div>
  );
}

function Slider({ label, hint, value, min, max, onChange, suffix = '' }) {
  return (
    <label style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
        <span style={{ fontSize: 12, fontWeight: 600, color: 'var(--ink-2)' }}>{label}</span>
        <span className="mono" style={{ fontSize: 11, fontWeight: 600, color: 'var(--ink-2)' }}>{value}{suffix}</span>
      </div>
      <input type="range" min={min} max={max} value={value} onChange={e => onChange(Number(e.target.value))} />
      {hint && <span style={{ fontSize: 10.5, color: 'var(--ink-3)', lineHeight: 1.4 }}>{hint}</span>}
    </label>
  );
}

// ────────────────────────────────────────────────────────────
// Upload de imagem para link (catálogo)
// ────────────────────────────────────────────────────────────
function LinkImageUpload({ value, onChange }) {
  const fileRef = React.useRef(null);
  const [loading, setLoading] = React.useState(false);

  async function handleFile(file) {
    if (!file || !file.type.startsWith('image/')) return;
    setLoading(true);
    try {
      const compressed = await compressImage(file);
      onChange(compressed);
    } finally {
      setLoading(false);
    }
  }

  return (
    <div>
      <input ref={fileRef} type="file" accept="image/*" style={{ display: 'none' }}
        onChange={e => handleFile(e.target.files?.[0])} />
      {value ? (
        <div style={{ position: 'relative', borderRadius: 10, overflow: 'hidden', border: '1px solid var(--line)' }}>
          <img src={value} style={{ width: '100%', height: 120, objectFit: 'cover', display: 'block' }} />
          <div style={{ position: 'absolute', top: 8, right: 8, display: 'flex', gap: 6 }}>
            <button onClick={() => fileRef.current?.click()} style={{
              background: 'rgba(255,255,255,0.92)', padding: '5px 10px', borderRadius: 999,
              fontSize: 11, fontWeight: 600, color: 'var(--ink)',
            }}>Trocar</button>
            <button onClick={() => onChange(null)} style={{
              background: 'rgba(0,0,0,0.5)', color: '#fff', padding: '5px 10px', borderRadius: 999,
              fontSize: 11, fontWeight: 600,
            }}>Remover</button>
          </div>
        </div>
      ) : (
        <button onClick={() => fileRef.current?.click()} disabled={loading} style={{
          width: '100%', padding: '18px', borderRadius: 10,
          border: '1.5px dashed var(--line-2)', background: 'var(--field)',
          display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 5,
          color: 'var(--ink-3)', fontSize: 13, fontWeight: 500,
        }}>
          <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
            <rect x="3" y="5" width="18" height="14" rx="2"/>
            <circle cx="9" cy="11" r="1.5"/><path d="M21 16l-5-5L7 19"/>
          </svg>
          {loading ? 'Comprimindo…' : 'Adicionar imagem do produto'}
          <span style={{ fontSize: 10.5 }}>JPG/PNG/WebP · comprimida automaticamente</span>
        </button>
      )}
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// Link editor row (collapsible)
// ────────────────────────────────────────────────────────────
function LinkRow({ link, index, total, onChange, onDelete, onMove, expandedId, setExpandedId, currentStyle }) {
  const I = window.Icon;
  const expanded = expandedId === link.id;
  const Ico = I[link.icon] || I.link;

  return (
    <div style={{
      background: '#fff', border: '1px solid var(--line)', borderRadius: 12,
      overflow: 'hidden', transition: 'box-shadow 120ms',
      boxShadow: expanded ? '0 4px 16px rgba(0,0,0,0.06)' : 'none',
    }}>
      {/* Header */}
      <div style={{
        display: 'flex', alignItems: 'center', gap: 10, padding: '12px 14px',
        cursor: 'pointer', userSelect: 'none',
      }} onClick={() => setExpandedId(expanded ? null : link.id)}>
        {/* Reorder */}
        <div style={{ display: 'flex', flexDirection: 'column', gap: 2 }} onClick={e => e.stopPropagation()}>
          <button onClick={() => onMove(index, -1)} disabled={index === 0} style={{
            width: 20, height: 18, display: 'flex', alignItems: 'center', justifyContent: 'center',
            opacity: index === 0 ? 0.25 : 1, color: 'var(--ink-3)',
          }}><I.chevronUp size={12} /></button>
          <button onClick={() => onMove(index, 1)} disabled={index === total - 1} style={{
            width: 20, height: 18, display: 'flex', alignItems: 'center', justifyContent: 'center',
            opacity: index === total - 1 ? 0.25 : 1, color: 'var(--ink-3)',
          }}><I.chevronDown size={12} /></button>
        </div>
        {/* Icon */}
        <div style={{
          width: 36, height: 36, borderRadius: 10, background: 'var(--accent-soft)',
          display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--ink)',
          flexShrink: 0,
        }}><Ico size={18} stroke="var(--ink)" /></div>
        {/* Title + url */}
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{
            fontWeight: 600, fontSize: 14, color: 'var(--ink)',
            whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
          }}>{link.title || <span style={{ color: 'var(--ink-3)', fontWeight: 500 }}>Sem título</span>}</div>
          <div className="mono" style={{
            fontSize: 11, color: 'var(--ink-3)', marginTop: 2,
            whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
          }}>{link.url || 'sem url'}</div>
        </div>
        {/* Active toggle */}
        <button onClick={e => { e.stopPropagation(); onChange({ ...link, active: !link.active }); }} style={{
          width: 32, height: 18, borderRadius: 999,
          background: link.active !== false ? 'var(--ink)' : 'var(--line-2)',
          position: 'relative', transition: 'background 140ms',
          flexShrink: 0,
        }}>
          <div style={{
            position: 'absolute', top: 2, left: link.active !== false ? 16 : 2,
            width: 14, height: 14, borderRadius: '50%', background: '#fff',
            transition: 'left 140ms',
          }} />
        </button>
        <button onClick={e => { e.stopPropagation(); setExpandedId(expanded ? null : link.id); }} style={{
          width: 24, height: 24, display: 'flex', alignItems: 'center', justifyContent: 'center',
          color: 'var(--ink-3)',
        }}>
          {expanded ? <I.chevronUp size={14} /> : <I.chevronDown size={14} />}
        </button>
      </div>

      {/* Expanded body */}
      {expanded && (
        <div style={{
          padding: '4px 14px 16px', display: 'flex', flexDirection: 'column', gap: 14,
          borderTop: '1px solid var(--line)',
        }}>
          <div style={{ display: 'flex', gap: 10, paddingTop: 14 }}>
            <Field label="Título">
              <TextInput value={link.title} onChange={v => onChange({ ...link, title: v })} placeholder="Ex: Curso de produtividade" />
            </Field>
          </div>
          <Field label="URL" hint="Para WhatsApp use wa.me/55... — pre-preencha a mensagem com ?text=">
            <TextInput value={link.url} onChange={v => onChange({ ...link, url: v })} placeholder="https://" />
          </Field>
          <Field label="Subtítulo (opcional)">
            <TextInput value={link.subtitle} onChange={v => onChange({ ...link, subtitle: v })} placeholder="Descrição curta que aparece embaixo" />
          </Field>

          <Field label="Ícone">
            <IconPicker value={link.icon} onChange={v => onChange({ ...link, icon: v })} />
          </Field>

          {/* Imagem do produto (catálogo) */}
          {currentStyle === 'catalog' && (
            <Field label="Imagem do produto (opcional)">
              <LinkImageUpload value={link.image} onChange={v => onChange({ ...link, image: v })} />
            </Field>
          )}

          {/* Style-specific fields */}
          {(currentStyle === 'bento' || currentStyle === 'catalog') && (
            <div style={{ display: 'flex', gap: 10 }}>
              <Field label={currentStyle === 'catalog' ? 'Preço (R$)' : 'Preço (R$, opcional)'} hint="Deixe vazio para mostrar 'Gratuito'">
                <NumberInput value={link.price} onChange={v => onChange({ ...link, price: v })} placeholder="0,00" />
              </Field>
              {currentStyle === 'catalog' && (
                <Field label="Etiqueta (opcional)" hint="Ex: NOVO, ÚLTIMAS VAGAS">
                  <TextInput value={link.tag} onChange={v => onChange({ ...link, tag: v })} placeholder="" />
                </Field>
              )}
              {currentStyle === 'catalog' && (
                <Field label="Texto do botão">
                  <TextInput value={link.cta} onChange={v => onChange({ ...link, cta: v })} placeholder="Comprar" />
                </Field>
              )}
            </div>
          )}

          {currentStyle === 'bento' && (
            <label style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 12px', background: 'var(--field)', borderRadius: 10, cursor: 'pointer' }}>
              <input type="checkbox" checked={!!link.featured} onChange={e => onChange({ ...link, featured: e.target.checked })} style={{ width: 16, height: 16, accentColor: 'var(--ink)' }} />
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 13, fontWeight: 600 }}>Destaque (card largo)</div>
                <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginTop: 1 }}>Ocupa a linha inteira no estilo Bento</div>
              </div>
            </label>
          )}

          {currentStyle === 'mural' && (
            <>
              <Field label="Tamanho do card">
                <div style={{ display: 'flex', gap: 8 }}>
                  {[
                    { id: 'square', label: 'Quadrado' },
                    { id: 'vertical', label: 'Vertical' },
                    { id: 'wide', label: 'Largo' },
                  ].map(opt => (
                    <button
                      key={opt.id}
                      onClick={() => onChange({ ...link, size: opt.id })}
                      style={{
                        flex: 1, padding: '8px 4px', borderRadius: 8,
                        border: (link.size || 'square') === opt.id
                          ? '1.5px solid var(--ink)'
                          : '1px solid var(--line)',
                        background: (link.size || 'square') === opt.id
                          ? 'var(--accent-soft)'
                          : 'var(--field)',
                        fontSize: 12, fontWeight: 600, color: 'var(--ink)',
                        transition: 'all 120ms',
                      }}
                    >{opt.label}</button>
                  ))}
                </div>
              </Field>
              <Field label="Cor do card">
                <div style={{
                  display: 'flex', alignItems: 'center', gap: 10,
                  background: '#fff', border: '1px solid var(--line)',
                  borderRadius: 10, padding: '8px 12px',
                }}>
                  <div style={{
                    width: 36, height: 36, borderRadius: 8, position: 'relative', overflow: 'hidden',
                    background: link.cardColor || '#ffffff', border: '1px solid var(--line-2)',
                  }}>
                    <input
                      type="color"
                      value={link.cardColor || '#ffffff'}
                      onChange={e => onChange({ ...link, cardColor: e.target.value })}
                      style={{ position: 'absolute', inset: 0, opacity: 0, cursor: 'pointer', border: 'none', width: '100%', height: '100%' }}
                    />
                  </div>
                  <span className="mono" style={{ fontSize: 12, color: 'var(--ink-2)', textTransform: 'uppercase' }}>
                    {link.cardColor || 'Padrão da paleta'}
                  </span>
                  {link.cardColor && (
                    <button
                      onClick={() => onChange({ ...link, cardColor: '' })}
                      style={{ marginLeft: 'auto', fontSize: 11, color: 'var(--ink-3)', fontWeight: 600 }}
                    >Limpar</button>
                  )}
                </div>
              </Field>
            </>
          )}

          <div style={{ display: 'flex', justifyContent: 'flex-end', paddingTop: 4 }}>
            <button onClick={() => onDelete(link.id)} style={{
              display: 'flex', alignItems: 'center', gap: 6,
              color: 'var(--danger)', fontSize: 12, fontWeight: 600,
              padding: '6px 10px', borderRadius: 8,
            }}>
              <I.trash size={14} stroke="var(--danger)" />
              Remover link
            </button>
          </div>
        </div>
      )}
    </div>
  );
}

function IconPicker({ value, onChange }) {
  const I = window.Icon;
  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
      {window.ICON_TYPES.map(t => {
        const Ico = I[t.id];
        const active = value === t.id;
        return (
          <button key={t.id} onClick={() => onChange(t.id)} title={t.label} style={{
            width: 36, height: 36, borderRadius: 10,
            border: active ? '1.5px solid var(--ink)' : '1px solid var(--line)',
            background: active ? 'var(--ink)' : 'var(--field)',
            color: active ? '#fff' : 'var(--ink)',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            transition: 'all 120ms',
          }}><Ico size={16} stroke={active ? '#fff' : 'var(--ink)'} /></button>
        );
      })}
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// Profile editor
// ────────────────────────────────────────────────────────────
function ProfileEditor({ profile, onChange }) {
  const avatarRef = React.useRef(null);
  const [compressing, setCompressing] = React.useState(false);

  async function handleAvatarFile(file) {
    if (!file || !file.type.startsWith('image/')) return;
    setCompressing(true);
    try {
      const compressed = await compressImage(file, 400, 0.88);
      onChange({ ...profile, avatar: compressed });
    } finally {
      setCompressing(false);
    }
  }

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
      <div style={{ display: 'flex', gap: 14, alignItems: 'flex-start' }}>
        <input ref={avatarRef} type="file" accept="image/*" style={{ display: 'none' }}
          onChange={e => handleAvatarFile(e.target.files?.[0])} />
        <div style={{ position: 'relative', flexShrink: 0 }}>
          <window.Avatar name={profile.name} src={profile.avatar} size={64} palette={window.PALETTES.cream} ring={false} />
          <button onClick={() => avatarRef.current?.click()} title="Trocar foto" style={{
            position: 'absolute', bottom: -4, right: -4,
            width: 22, height: 22, borderRadius: '50%',
            background: 'var(--ink)', color: '#fff',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            border: '2px solid var(--bg)', fontSize: 13, lineHeight: 1,
          }}>
            {compressing ? '…' : '+'}
          </button>
        </div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 10, flex: 1 }}>
          <Field label="Nome">
            <TextInput value={profile.name} onChange={v => onChange({ ...profile, name: v })} placeholder="Seu nome" />
          </Field>
          <Field label="@ usuário" hint="Aparece como linko.bio/seu-usuario">
            <TextInput value={profile.handle} onChange={v => onChange({ ...profile, handle: v.replace(/[^a-z0-9._-]/gi, '').toLowerCase() })} placeholder="seu.usuario" />
          </Field>
        </div>
      </div>
      <Field label="Bio">
        <TextInput value={profile.bio} onChange={v => onChange({ ...profile, bio: v })} placeholder="Conte em uma frase o que você faz" multiline />
      </Field>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// Backoffice root
// ────────────────────────────────────────────────────────────
function Backoffice({ state, setState }) {
  const I = window.Icon;
  const [expandedLinkId, setExpandedLinkId] = React.useState(null);

  const update = (patch) => setState(s => ({ ...s, ...patch }));
  const updateLink = (updated) => {
    setState(s => ({ ...s, links: s.links.map(l => l.id === updated.id ? updated : l) }));
  };
  const deleteLink = (id) => {
    setState(s => ({ ...s, links: s.links.filter(l => l.id !== id) }));
  };
  const moveLink = (index, delta) => {
    setState(s => {
      const arr = [...s.links];
      const j = index + delta;
      if (j < 0 || j >= arr.length) return s;
      [arr[index], arr[j]] = [arr[j], arr[index]];
      return { ...s, links: arr };
    });
  };
  const addLink = () => {
    const id = 'l' + Date.now();
    const newLink = {
      id, title: 'Novo link', url: 'https://', subtitle: '',
      icon: 'link', active: true, price: null, featured: false,
      size: 'square', cardColor: '',
    };
    setState(s => ({ ...s, links: [...s.links, newLink] }));
    setExpandedLinkId(id);
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      <Section
        title="Estilo da página"
        subtitle="Como seus links são apresentados para quem visita"
      >
        <StylePicker value={state.style} onChange={style => update({ style })} />
        {state.style === 'mural' && (
          <Slider
            label="Espaçamento entre cards"
            hint="Distância entre os cards do grid"
            value={state.bentoGap ?? 12}
            min={4}
            max={24}
            onChange={v => update({ bentoGap: v })}
            suffix="px"
          />
        )}
      </Section>

      <Section
        title="Paleta de cores"
        subtitle="Cor de fundo, texto e botões do seu link público"
      >
        <PalettePicker
          value={state.paletteId}
          onChange={paletteId => update({ paletteId })}
          customColors={state.customColors}
          onCustomChange={customColors => update({ customColors })}
        />
      </Section>

      <Section
        title="Imagem de fundo"
        subtitle="Uma foto sutil atrás do conteúdo. A paleta tinta a imagem para manter a leitura confortável."
      >
        <BackgroundEditor
          background={state.background}
          onChange={background => update({ background })}
          palette={state.paletteId === 'custom' ? window.getCustomPalette(state.customColors) : window.PALETTES[state.paletteId]}
        />
      </Section>

      <Section title="Perfil" subtitle="Aparece no topo da sua página">
        <ProfileEditor profile={state.profile} onChange={profile => update({ profile })} />
      </Section>

      <Section
        title="Links"
        subtitle={`${state.links.length} ${state.links.length === 1 ? 'item' : 'itens'} · arraste para reordenar`}
        right={
          <button onClick={addLink} style={{
            display: 'flex', alignItems: 'center', gap: 6,
            background: 'var(--ink)', color: '#fff',
            padding: '8px 14px', borderRadius: 999,
            fontSize: 13, fontWeight: 600,
          }}>
            <I.plus size={14} stroke="#fff" />
            Adicionar link
          </button>
        }
      >
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
          {state.links.map((link, idx) => (
            <LinkRow
              key={link.id}
              link={link} index={idx} total={state.links.length}
              onChange={updateLink} onDelete={deleteLink} onMove={moveLink}
              expandedId={expandedLinkId} setExpandedId={setExpandedLinkId}
              currentStyle={state.style}
            />
          ))}
          {state.links.length === 0 && (
            <div style={{
              padding: '32px 16px', textAlign: 'center', color: 'var(--ink-3)',
              fontSize: 13, border: '1px dashed var(--line-2)', borderRadius: 12,
            }}>Nenhum link ainda. Clique em <strong style={{ color: 'var(--ink)' }}>Adicionar link</strong> para começar.</div>
          )}
        </div>
      </Section>
    </div>
  );
}

window.Backoffice = Backoffice;
