// Editor — 3 passos lineares: upload → preset → download
// Chama a Gemini 2.5 Flash Image (Nano Banana) para processar a foto real.

function Editor({ navigate }) {
  const [step, setStep] = useState(0);
  const [file, setFile] = useState(null);
  const [presetId, setPresetId] = useState(null);
  const [processing, setProcessing] = useState(false);
  const [resultUrl, setResultUrl] = useState(null);
  const [error, setError] = useState(null);
  const [pos, setPos] = useState(50);
  const [cleanupAsk, setCleanupAsk] = useState(null);
  const [lightsAsk, setLightsAsk] = useState(null);
  const [currentPrompt, setCurrentPrompt] = useState(null);
  const [gallery, setGallery] = useState([]);
  const [adjustCount, setAdjustCount] = useState(0);
  const [, forceRerender] = useState(0);
  // Rastreamento de re-edições
  const [lastGalId, setLastGalId] = useState(null);       // id da última geração em gallery
  const [activePurchaseId, setActivePurchaseId] = useState(null); // compra ativa do usuário

  // Termos de uso
  const [termsAccepted, setTermsAccepted] = useState(true); // assume true até checar
  const [showTermsModal, setShowTermsModal] = useState(false);
  const [pendingPresetAction, setPendingPresetAction] = useState(null); // guarda ação pendente
  const [termsChecked, setTermsChecked] = useState(false);
  const [termsLoading, setTermsLoading] = useState(false);

  const preset = PRESETS.find(p => p.id === presetId);

  // Carrega galeria e purchase ativa ao montar
  useEffect(() => {
    DB.fetchGallery().then(setGallery).catch(() => {});
    // Carrega a compra paga mais recente para passar purchaseId nas gerações
    DB.listPurchases().then(purchases => {
      const paid = purchases.find(p => p.status === 'paid');
      if (paid) setActivePurchaseId(paid.orderId || null);
    }).catch(() => {});
    const unsub = DB.onUserChange(() => forceRerender(v => v + 1));
    // Verifica aceite de termos
    fetch('/api/auth/terms-status', { credentials: 'include' })
      .then(r => r.json())
      .then(d => setTermsAccepted(!!d.accepted))
      .catch(() => {});
    return unsub;
  }, []);

  const handleFile = async (f) => {
    if (!f) return;
    const looksImage = f.type.startsWith('image/') || /\.(jpe?g|png|hei[cf])$/i.test(f.name || '');
    if (!looksImage) {
      setError('Envie um arquivo de imagem (JPG, PNG ou HEIC).');
      return;
    }
    setError(null);
    try {
      const normalized = await toJpegBlob(f);
      const beforeUrl = URL.createObjectURL(normalized);
      setFile({ name: f.name, beforeUrl, blob: normalized });
      setStep(1);
    } catch (e) {
      setError(e.message || 'Não foi possível abrir essa imagem.');
    }
  };

  const runPreset = async (p, { cleanup = false, indoorLights = false } = {}) => {
    if (!p || !file) return;
    if (DB.creditsAvailable() <= 0) {
      setError('Você está sem créditos. Compre um pacote para continuar.');
      return;
    }
    setPresetId(p.id);
    setProcessing(true);
    setError(null);
    try {
      let prompt = p.prompt;
      prompt = `${SCREENSHOT_PROMPT}\n\n${prompt}`;
      if (indoorLights && p.indoorLightsPrompt) prompt = `${prompt}\n\n${p.indoorLightsPrompt}`;
      if (cleanup) prompt = `${prompt}\n\n${CLEANUP_PROMPT}`;
      prompt = `${prompt}\n\n${SCREENSHOT_PROMPT}`;
      setCurrentPrompt(prompt);
      const { dataUrl, galId } = await editImageWithGemini({
        file: file.blob,
        prompt,
        presetName: p.name,
        purchaseId: activePurchaseId || null,
      });
      setLastGalId(galId || null);
      await DB.consumeCredit();
      setResultUrl(dataUrl);
      setAdjustCount(0); // nova edição → primeiro ajuste volta a ser grátis
      DB.fetchGallery().then(setGallery).catch(() => {});
      setStep(2);
    } catch (e) {
      console.error(e);
      setError(e.message || 'Falha ao processar a imagem.');
    } finally {
      setProcessing(false);
    }
  };

  // Intercepta seleção de preset para verificar termos
  const choosePreset = (id) => {
    const p = PRESETS.find(x => x.id === id);
    if (!p) return;

    // Se não aceitou termos ainda, abre o modal primeiro
    if (!termsAccepted) {
      setPendingPresetAction({ id, preset: p });
      setShowTermsModal(true);
      return;
    }

    if (p.askCleanup) { setCleanupAsk(p); return; }
    if (p.askIndoorLights) { setLightsAsk({ preset: p, cleanup: false }); return; }
    runPreset(p);
  };

  // Callback quando termos são aceitos
  const onTermsAccepted = () => {
    setTermsAccepted(true);
    setShowTermsModal(false);
    // Retoma a ação pendente
    if (pendingPresetAction) {
      const p = pendingPresetAction.preset;
      setPendingPresetAction(null);
      if (p.askCleanup) { setCleanupAsk(p); return; }
      if (p.askIndoorLights) { setLightsAsk({ preset: p, cleanup: false }); return; }
      runPreset(p);
    }
  };

  const answerCleanup = (cleanup) => {
    const p = cleanupAsk;
    setCleanupAsk(null);
    if (!p) return;
    if (p.askIndoorLights) { setLightsAsk({ preset: p, cleanup }); return; }
    runPreset(p, { cleanup });
  };

  const answerLights = (indoorLights) => {
    const ctx = lightsAsk;
    setLightsAsk(null);
    if (ctx) runPreset(ctx.preset, { cleanup: ctx.cleanup, indoorLights });
  };

  const handleAdjust = async (text) => {
    if (!currentPrompt || !file) return;
    const isFirstFree = adjustCount === 0;
    if (!isFirstFree && DB.creditsAvailable() <= 0) {
      setError('Você está sem créditos. Compre um pacote para continuar.');
      setStep(2);
      return;
    }
    setProcessing(true);
    setStep(1);
    setError(null);
    try {
      const prompt = `${currentPrompt}\n\n[USER ADDITIONAL REQUEST]:\n${text}`;
      setCurrentPrompt(prompt);
      const { dataUrl, galId } = await editImageWithGemini({
        file: file.blob,
        prompt,
        presetName: preset?.name,
        // Re-edição: aponta para a geração original (ou a última re-edição)
        parentGenerationId: lastGalId || null,
        purchaseId: activePurchaseId || null,
      });
      setLastGalId(galId || null);
      if (!isFirstFree) await DB.consumeCredit();
      setResultUrl(dataUrl);
      setAdjustCount(c => c + 1);
      DB.fetchGallery().then(setGallery).catch(() => {});
      setStep(2);
    } catch (e) {
      console.error(e);
      setError(e.message || 'Falha ao processar o ajuste.');
      setStep(2);
    } finally {
      setProcessing(false);
    }
  };

  const reset = () => {
    if (file?.beforeUrl) URL.revokeObjectURL(file.beforeUrl);
    setStep(0); setFile(null); setPresetId(null); setPos(50);
    setResultUrl(null); setError(null); setCleanupAsk(null); setLightsAsk(null);
    setCurrentPrompt(null);
    setAdjustCount(0);
    setLastGalId(null); // limpa tracking ao iniciar nova sessão
  };

  return (
    <React.Fragment>
      <div style={{ minHeight:'100dvh', background:'var(--bg)', display:'flex', flexDirection:'column' }}>
        <EditorNav navigate={navigate} onReset={reset} step={step}/>
        <main className="m-bottom-safe" style={{ flex: 1, display:'flex', alignItems:'flex-start', justifyContent:'center', padding:'28px 16px 40px' }}>
          <div style={{ width:'100%', maxWidth: step === 2 ? 980 : 720 }}>
            <Stepper step={step}/>
            {error && <ErrorBanner message={error} onDismiss={() => setError(null)} action={
              error.includes('créditos') && (
                <button onClick={() => navigate('#/checkout')} style={{
                  background: '#7A2E18', color: '#FFF', border: 'none', padding: '4px 12px',
                  borderRadius: 6, fontSize: 12, fontWeight: 600, cursor: 'pointer'
                }}>
                  Comprar agora
                </button>
              )
            }/>}
            {step === 0 && <UploadStep onPick={handleFile}/>}
            {step === 1 && (processing
              ? <Processing preset={preset}/>
              : <PresetStep onPick={choosePreset}/>)}
            {step === 2 && resultUrl && (
              <DoneStep file={file} preset={preset} resultUrl={resultUrl}
                        pos={pos} setPos={setPos} onReset={reset} onAdjust={handleAdjust}
                        adjustCount={adjustCount}/>
            )}
          </div>
        </main>
        {cleanupAsk && (
          <CleanupModal preset={cleanupAsk}
                        onYes={() => answerCleanup(true)}
                        onNo={() => answerCleanup(false)}
                        onCancel={() => setCleanupAsk(null)}/>
        )}
        {lightsAsk && (
          <IndoorLightsModal preset={lightsAsk.preset}
                             onYes={() => answerLights(true)}
                             onNo={() => answerLights(false)}
                             onCancel={() => setLightsAsk(null)}/>
        )}
        {showTermsModal && (
          <TermsModal
            onAccept={onTermsAccepted}
            onCancel={() => { setShowTermsModal(false); setPendingPresetAction(null); }}
          />
        )}
      </div>
      {/* Galeria dos últimos 30 dias */}
      {gallery.length > 0 && (
        <Gallery items={gallery} navigate={navigate}/>
      )}
    </React.Fragment>
  );
}

function IndoorLightsModal({ preset, onYes, onNo, onCancel }) {
  return (
    <div
      onClick={onCancel}
      className="m-sheet-bg"
      style={{
        position:'fixed', inset: 0, background:'rgba(31,26,21,.45)',
        display:'flex', alignItems:'flex-end', justifyContent:'center', zIndex: 1000,
        padding: 20, backdropFilter:'blur(4px)',
      }}>
      <div
        onClick={e => e.stopPropagation()}
        className="sheet-in m-sheet"
        style={{
          background:'var(--paper)', borderRadius: 18, maxWidth: 440, width:'100%',
          padding: 28, boxShadow:'var(--shadow-lg)', border:'1px solid var(--line)',
          paddingBottom: 'calc(28px + var(--safe-bottom))',
        }}>
        <div style={{
          width: 44, height: 44, borderRadius: 12, background:'var(--accent-soft)',
          color:'var(--accent)', display:'flex', alignItems:'center', justifyContent:'center',
          marginBottom: 16,
        }}><Icons.Sparkles size={22}/></div>
        <h3 className="serif" style={{ fontSize: 28, lineHeight: 1.1, margin:'0 0 8px', letterSpacing:'-0.01em' }}>
          Deixar as luzes internas acesas?
        </h3>
        <p style={{ color:'var(--ink-3)', fontSize: 14, margin:'0 0 20px', lineHeight: 1.5 }}>
          Se houver luminárias, abajures ou arandelas na cena, podemos deixá-las
          acesas com um brilho quente — visual "twilight de revista" que contrasta
          com o céu dourado.
        </p>
        <div style={{ display:'flex', gap: 10, flexDirection:'column' }}>
          <Button variant="primary" size="lg" onClick={onYes}>
            Sim, acender as luzes
          </Button>
          <Button variant="secondary" size="lg" onClick={onNo}>
            Não, manter como está
          </Button>
        </div>
      </div>
    </div>
  );
}

function CleanupModal({ preset, onYes, onNo, onCancel }) {
  return (
    <div
      onClick={onCancel}
      className="m-sheet-bg"
      style={{
        position:'fixed', inset: 0, background:'rgba(31,26,21,.45)',
        display:'flex', alignItems:'flex-end', justifyContent:'center', zIndex: 1000,
        padding: 20, backdropFilter:'blur(4px)',
      }}>
      <div
        onClick={e => e.stopPropagation()}
        className="sheet-in m-sheet"
        style={{
          background:'var(--paper)', borderRadius: 18, maxWidth: 440, width:'100%',
          padding: 28, boxShadow:'var(--shadow-lg)', border:'1px solid var(--line)',
          paddingBottom: 'calc(28px + var(--safe-bottom))',
        }}>
        <div style={{
          width: 44, height: 44, borderRadius: 12, background:'var(--accent-soft)',
          color:'var(--accent)', display:'flex', alignItems:'center', justifyContent:'center',
          marginBottom: 16,
        }}><Icons.Sparkles size={22}/></div>
        <h3 className="serif" style={{ fontSize: 28, lineHeight: 1.1, margin:'0 0 8px', letterSpacing:'-0.01em' }}>
          Há bagunça ou pessoas na foto?
        </h3>
        <p style={{ color:'var(--ink-3)', fontSize: 14, margin:'0 0 20px', lineHeight: 1.5 }}>
          Se sim, vamos remover junto com a edição de luz: pessoas, roupas soltas,
          lixo, objetos pessoais e reflexos. Pode demorar alguns segundos a mais.
        </p>
        <div style={{ display:'flex', gap: 10, flexDirection:'column' }}>
          <Button variant="primary" size="lg" onClick={onYes}>
            Sim, limpar a cena também
          </Button>
          <Button variant="secondary" size="lg" onClick={onNo}>
            Não, só ajustar luz e atmosfera
          </Button>
        </div>
      </div>
    </div>
  );
}

function EditorNav({ navigate, onReset, step }) {
  return (
    <nav style={{
      display:'flex', alignItems:'center', justifyContent:'space-between',
      padding:'22px 48px', borderBottom:'1px solid var(--line)',
      paddingTop: 'calc(14px + var(--safe-top))',
      paddingLeft: 'calc(16px + var(--safe-left))',
      paddingRight: 'calc(16px + var(--safe-right))',
      position:'sticky', top: 0, zIndex: 40,
      background: 'rgba(245,241,235,.92)', backdropFilter:'blur(12px)', WebkitBackdropFilter:'blur(12px)',
    }} className="m-nav">
      <button onClick={() => navigate('#/landing')} style={{ display:'flex', alignItems:'center', gap: 10 }}>
        <AftershotMark/>
        <span className="serif hide-mobile" style={{ fontSize: 24 }}>Aftershot</span>
      </button>

      {/* Desktop */}
      <div className="hide-mobile" style={{ display:'flex', alignItems:'center', gap: 16 }}>
        {window.USER && (
          <button onClick={() => navigate('#/account')}
            style={{ fontSize: 14, color: DB.creditsAvailable() === 0 ? 'var(--accent)' : 'var(--ink-2)', fontWeight: 500 }}>
            {window.USER.name.split(' ')[0]} · {DB.creditsAvailable()} créditos
          </button>
        )}
        {window.USER && DB.creditsAvailable() === 0 && (
          <Button variant="accent" size="sm" onClick={() => navigate('#/checkout')}>
            <Icons.Zap size={14}/> Comprar créditos
          </Button>
        )}
        {step > 0 && (
          <Button variant="ghost" size="sm" onClick={onReset}>Começar de novo</Button>
        )}
        {window.USER && (
          <Button variant="ghost" size="sm" onClick={() => navigate('#/account')}>Minha conta</Button>
        )}
      </div>

      {/* Mobile */}
      <div className="show-mobile" style={{ display:'none', alignItems:'center', gap: 8 }}>
        {window.USER && (
          <button onClick={() => navigate('#/account')}
            className="tap-fade"
            style={{ display:'flex', alignItems:'center', gap: 6, padding:'7px 12px', borderRadius: 999,
              background: DB.creditsAvailable() === 0 ? 'var(--accent-soft)' : 'var(--paper)',
              border: '1px solid ' + (DB.creditsAvailable() === 0 ? 'var(--accent)' : 'var(--line)'),
              fontSize: 12, fontWeight: 600,
              color: DB.creditsAvailable() === 0 ? 'var(--accent-deep)' : 'var(--ink-2)' }}>
            <Icons.Zap size={12}/> {DB.creditsAvailable()}
          </button>
        )}
        {step > 0 && (
          <button onClick={onReset} className="tap-fade" title="Começar de novo"
            style={{ width: 38, height: 38, borderRadius: 10, background:'var(--paper)', border:'1px solid var(--line)', display:'flex', alignItems:'center', justifyContent:'center' }}>
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"><path d="M3 12a9 9 0 1 0 3-6.7L3 8"/><path d="M3 3v5h5"/></svg>
          </button>
        )}
      </div>
    </nav>
  );
}

function Stepper({ step }) {
  const labels = ['Envie a foto', 'Escolha o estilo', 'Baixe pronta'];
  return (
    <div style={{ display:'flex', alignItems:'center', justifyContent:'center', gap: 8, marginBottom: 28, flexWrap:'nowrap' }}>
      {labels.map((l, i) => (
        <React.Fragment key={i}>
          <div style={{ display:'flex', alignItems:'center', gap: 8, minWidth: 0 }}>
            <div style={{
              width: 26, height: 26, borderRadius:'50%', fontSize: 12, fontWeight: 600,
              display:'flex', alignItems:'center', justifyContent:'center', flexShrink: 0,
              background: i <= step ? 'var(--accent)' : 'var(--line)',
              color: i <= step ? '#fff' : 'var(--ink-3)',
            }}>{i < step ? '✓' : i+1}</div>
            <span className={i === step ? '' : 'hide-mobile'} style={{ fontSize: 13, fontWeight: 500, whiteSpace:'nowrap',
              color: i === step ? 'var(--ink)' : 'var(--ink-3)' }}>{l}</span>
          </div>
          {i < labels.length - 1 && <div style={{ width: 24, height: 1, background:'var(--line)', flexShrink: 0 }}/>}
        </React.Fragment>
      ))}
    </div>
  );
}

function ErrorBanner({ message, onDismiss, action }) {
  return (
    <div style={{
      marginBottom: 20, padding: '12px 16px', borderRadius: 10,
      background:'#FDECE7', border:'1px solid #E8B7A5', color:'#7A2E18',
      display:'flex', alignItems:'center', justifyContent:'space-between', gap: 12,
    }}>
      <div style={{ display:'flex', alignItems:'center', gap: 12 }}>
        <span style={{ fontSize: 13 }}>{message}</span>
        {action}
      </div>
      <button onClick={onDismiss} style={{ fontSize: 12, color:'#7A2E18', padding: '4px 8px' }}>Fechar</button>
    </div>
  );
}

function UploadStep({ onPick }) {
  const inputRef = useRef(null);
  const [dragOver, setDragOver] = useState(false);

  const onDrop = (e) => {
    e.preventDefault();
    setDragOver(false);
    const f = e.dataTransfer.files?.[0];
    if (f) onPick(f);
  };

  return (
    <div
      onDragOver={e => { e.preventDefault(); setDragOver(true); }}
      onDragLeave={() => setDragOver(false)}
      onDrop={onDrop}
      className="m-card-pad"
      style={{
        background:'var(--paper)',
        border: `2px dashed ${dragOver ? 'var(--accent)' : 'var(--line-2)'}`,
        borderRadius: 20, padding: 64, textAlign:'center',
        transition:'border-color .15s',
      }}>
      <div style={{
        width: 64, height: 64, margin:'0 auto 20px', borderRadius: 16,
        background:'var(--accent-soft)', color:'var(--accent)',
        display:'flex', alignItems:'center', justifyContent:'center',
      }}><Icons.Upload size={28}/></div>
      <h2 className="serif m-h2" style={{ fontSize: 40, lineHeight: 1, margin:'0 0 12px', letterSpacing:'-0.015em' }}>
        Solte sua foto aqui
      </h2>
      <p style={{ color:'var(--ink-3)', maxWidth: 380, margin:'0 auto 24px', fontSize: 15 }}>
        Arraste uma imagem ou selecione. JPG, PNG ou HEIC.
      </p>
      <Button variant="primary" size="lg" onClick={() => inputRef.current?.click()} className="m-btn-full">
        <Icons.Upload size={16}/> Selecionar foto
      </Button>
      <input
        ref={inputRef}
        type="file"
        accept="image/*"
        capture="environment"
        style={{ display:'none' }}
        onChange={e => onPick(e.target.files?.[0])}
      />
      <div className="show-mobile" style={{ display:'none', marginTop: 14, fontSize: 12, color:'var(--ink-3)' }}>
        Tirar foto ou escolher da galeria
      </div>
    </div>
  );
}

function PresetStep({ onPick }) {
  return (
    <div>
      <div style={{ textAlign:'center', marginBottom: 24 }}>
        <h2 className="serif m-h2" style={{ fontSize: 40, lineHeight: 1, margin:'0 0 8px', letterSpacing:'-0.015em' }}>
          Escolha um estilo
        </h2>
        <p style={{ color:'var(--ink-3)', fontSize: 15, margin: 0 }}>
          Um clique aplica. Pode tentar outro depois.
        </p>
      </div>
      <div className="m-grid-2" style={{ display:'grid', gridTemplateColumns:'repeat(3, 1fr)', gap: 12 }}>
        {PRESETS.map(p => (
          <button key={p.id} onClick={() => onPick(p.id)}
            style={{
              background:'var(--paper)', border:'1px solid var(--line)', borderRadius: 14,
              overflow:'hidden', textAlign:'left', padding: 0,
              display:'flex', flexDirection:'column',
              transition:'transform .12s, box-shadow .15s',
            }}
            onMouseEnter={e => { e.currentTarget.style.transform = 'translateY(-2px)'; e.currentTarget.style.boxShadow = 'var(--shadow-md)'; }}
            onMouseLeave={e => { e.currentTarget.style.transform = ''; e.currentTarget.style.boxShadow = ''; }}>
            <img src={p.demo.after} alt="" style={{ width:'100%', height:'auto', display:'block' }}/>
            <div style={{ padding: 12, flex: 1 }}>
              <div style={{ fontSize: 14, fontWeight: 600, marginBottom: 4 }}>{p.name}</div>
              <div style={{ fontSize: 12, color: 'var(--ink-3)', lineHeight: 1.4 }}>{p.desc}</div>
            </div>
          </button>
        ))}
      </div>
    </div>
  );
}

function Processing({ preset }) {
  return (
    <div className="m-card-pad" style={{
      background:'var(--paper)', border:'1px solid var(--line)', borderRadius: 20,
      padding: 80, textAlign:'center',
    }}>
      <div style={{
        width: 56, height: 56, margin:'0 auto 20px', borderRadius:'50%',
        border:'3px solid var(--line)', borderTopColor:'var(--accent)',
        animation:'spin 1s linear infinite',
      }}/>
      <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>
      <div className="serif m-h3" style={{ fontSize: 32, marginBottom: 6 }}>Aplicando {preset?.name}…</div>
      <div style={{ fontSize: 14, color:'var(--ink-3)' }}>Pode levar de 10 a 30 segundos.</div>
    </div>
  );
}

function DoneStep({ file, preset, resultUrl, pos, setPos, onReset, onAdjust, adjustCount = 0 }) {
  const [adjustText, setAdjustText] = useState('');

  const download = () => {
    const a = document.createElement('a');
    a.href = resultUrl;
    const base = (file?.name || 'foto').replace(/\.[^.]+$/, '');
    a.download = `${base}-${preset.id}.png`;
    document.body.appendChild(a);
    a.click();
    a.remove();
  };

  return (
    <div>
      <div style={{ textAlign:'center', marginBottom: 20 }}>
        <h2 className="serif m-h2" style={{ fontSize: 40, lineHeight: 1, margin:'0 0 8px', letterSpacing:'-0.015em' }}>
          Sua foto está pronta
        </h2>
        <p style={{ color:'var(--ink-3)', fontSize: 15, margin: 0 }}>
          Arraste o divisor para comparar antes e depois.
        </p>
      </div>
      <div style={{
        borderRadius: 20, overflow:'hidden', background:'var(--paper)', border:'1px solid var(--line)',
        boxShadow:'var(--shadow-lg)', position:'relative', marginBottom: 20,
        width: 'fit-content', maxWidth:'100%', margin: '0 auto 20px', display:'flex', justifyContent:'center'
      }}>
        <img src={file.beforeUrl} alt="" style={{ display:'block', maxWidth:'100%', maxHeight:'65vh', width:'auto', height:'auto', opacity: 0, pointerEvents:'none' }} />
        <BeforeAfter before={file.beforeUrl} after={resultUrl} pos={pos} setPos={setPos}/>
        <div style={{ position:'absolute', top: 12, left: 12 }}><Pill tone="ink">Antes</Pill></div>
        <div style={{ position:'absolute', top: 12, right: 12 }}><Pill tone="accent">Depois · {preset.name}</Pill></div>
      </div>
      <div className="m-stack" style={{ display:'flex', gap: 10, justifyContent:'center' }}>
        <Button variant="secondary" size="lg" onClick={onReset} className="m-btn-full">Editar outra foto</Button>
        <Button variant="primary" size="lg" onClick={download} className="m-btn-full">
          <Icons.Download size={16}/> Baixar PNG
        </Button>
      </div>

      <div className="m-card-pad" style={{ marginTop: 24, padding: 22, background: 'var(--paper)', borderRadius: 20, border: '1px solid var(--line)', textAlign: 'left' }}>
        <h4 className="serif" style={{ margin: '0 0 6px', fontSize: 20 }}>Erramos algo?</h4>
        <p style={{ margin: '0 0 14px', fontSize: 14, color: 'var(--ink-3)' }}>
          {adjustCount === 0
            ? 'Peça um ajuste, é grátis dessa vez.'
            : 'O próximo ajuste consome 1 crédito.'}
        </p>
        <div className="m-stack" style={{ display: 'flex', gap: 10 }}>
          <input
            type="text"
            value={adjustText}
            onChange={e => setAdjustText(e.target.value)}
            placeholder="Ex: Deixe o céu mais vibrante..."
            style={{ flex: 1, padding: '12px 14px', borderRadius: 12, border: '1px solid var(--line)', background: 'var(--bg)', fontSize: 15, outline: 'none' }}
            onKeyDown={e => e.key === 'Enter' && adjustText.trim() && onAdjust(adjustText.trim())}
          />
          <Button variant="secondary" onClick={() => { if(adjustText.trim()) onAdjust(adjustText.trim()) }} className="m-btn-full">
            Ajustar
          </Button>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { Editor });

function Gallery({ items, navigate }) {
  const fmt = (ts) => {
    const d = new Date(ts);
    return d.toLocaleDateString('pt-BR', { day: '2-digit', month: 'short' });
  };
  const download = (url, presetName) => {
    const a = document.createElement('a');
    a.href = url;
    a.download = `aftershot-${(presetName || 'foto').replace(/\s+/g,'-')}-${Date.now()}.png`;
    document.body.appendChild(a); a.click(); a.remove();
  };
  return (
    <section className="m-section" style={{ borderTop:'1px solid var(--line)', padding:'48px 48px 80px', background:'var(--bg-warm)' }}>
      <div style={{ maxWidth: 980, margin:'0 auto' }}>
        <div className="m-stack" style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom: 20, gap: 14 }}>
          <div>
            <h2 className="serif m-h3" style={{ fontSize: 32, lineHeight: 1, margin:'0 0 6px', letterSpacing:'-0.01em' }}>
              Suas fotos recentes
            </h2>
            <p style={{ fontSize: 13, color:'var(--ink-3)', margin: 0 }}>
              Últimos 30 dias · {items.length} {items.length === 1 ? 'foto editada' : 'fotos editadas'}
            </p>
          </div>
          <Button variant="secondary" size="sm" onClick={() => navigate('#/checkout')} className="m-btn-full">
            <Icons.Zap size={13}/> Comprar créditos
          </Button>
        </div>
        <div className="m-grid-2" style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(200px, 1fr))', gap: 14 }}>
          {items.map(item => (
            <div key={item.id} style={{
              background:'var(--paper)', borderRadius: 14, overflow:'hidden',
              border:'1px solid var(--line)', display:'flex', flexDirection:'column',
              boxShadow:'var(--shadow-sm)',
            }}>
              <div style={{ position:'relative', aspectRatio:'4/3', overflow:'hidden', background:'var(--bg)' }}>
                <img src={item.result_url} alt={item.preset_name}
                  style={{ width:'100%', height:'100%', objectFit:'cover', display:'block' }}/>
              </div>
              <div style={{ padding:'10px 12px', display:'flex', alignItems:'center', justifyContent:'space-between', gap: 8 }}>
                <div style={{ minWidth: 0 }}>
                  <div style={{ fontSize: 12, fontWeight: 600, color:'var(--ink)', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
                    {item.preset_name || 'Edição'}
                  </div>
                  <div style={{ fontSize: 11, color:'var(--ink-4)', marginTop: 2 }}>{fmt(item.created_at)}</div>
                </div>
                <button title="Baixar foto" onClick={() => download(item.result_url, item.preset_name)}
                  onMouseEnter={e => { e.currentTarget.style.background='var(--accent-soft)'; e.currentTarget.style.color='var(--accent)'; }}
                  onMouseLeave={e => { e.currentTarget.style.background='var(--bg)'; e.currentTarget.style.color='var(--ink-2)'; }}
                  style={{ width:30, height:30, borderRadius:8, flexShrink:0, background:'var(--bg)', border:'1px solid var(--line)', display:'flex', alignItems:'center', justifyContent:'center', color:'var(--ink-2)', cursor:'pointer' }}>
                  <Icons.Download size={14}/>
                </button>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

function TermsModal({ onAccept, onCancel }) {
  const [checked, setChecked] = useState(false);
  const [loading, setLoading] = useState(false);

  const handleAccept = async () => {
    if (!checked || loading) return;
    setLoading(true);
    try {
      const res = await fetch('/api/auth/accept-terms', {
        method: 'POST',
        credentials: 'include',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({}),
      });
      const data = await res.json();
      if (data.ok) {
        onAccept();
      } else {
        alert(data.error || 'Erro ao registrar aceite.');
      }
    } catch {
      alert('Erro de conexão. Tente novamente.');
    } finally {
      setLoading(false);
    }
  };

  const modalBg = {
    position:'fixed', inset: 0, zIndex: 9999,
    background:'rgba(31,26,21,.6)', backdropFilter:'blur(4px)',
    display:'flex', alignItems:'center', justifyContent:'center',
    padding: 20,
  };
  const modalCard = {
    background:'var(--paper)', borderRadius: 20, maxWidth: 620, width:'100%',
    maxHeight:'85vh', display:'flex', flexDirection:'column',
    boxShadow:'var(--shadow-lg)', border:'1px solid var(--line)',
  };

  return (
    <div style={modalBg} onClick={onCancel}>
      <div style={modalCard} onClick={e => e.stopPropagation()} className="sheet-in">
        {/* Header */}
        <div style={{ padding:'24px 28px 0', display:'flex', justifyContent:'space-between', alignItems:'center' }}>
          <div>
            <div className="serif" style={{ fontSize: 24, lineHeight: 1.1 }}>Termos de Uso</div>
            <div style={{ fontSize: 13, color:'var(--ink-3)', marginTop: 4 }}>Leia e aceite para continuar</div>
          </div>
          <button onClick={onCancel} className="tap-fade" style={{
            width: 36, height: 36, borderRadius: 10, background:'var(--bg-deep)',
            border:'1px solid var(--line)', display:'flex', alignItems:'center', justifyContent:'center',
          }}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M6 6l12 12M18 6l-12 12"/></svg>
          </button>
        </div>

        {/* Scrollable terms */}
        <div className="momentum" style={{
          flex: 1, overflow:'auto', padding:'20px 28px',
          fontSize: 13, lineHeight: 1.7, color:'var(--ink-2)',
        }}>
          <p><strong>AFTERSHOT — TERMOS DE USO E CONDIÇÕES GERAIS</strong></p>
          <p>Última atualização: 27 de abril de 2026</p>
          <p>Ao utilizar a plataforma Aftershot ("Plataforma"), você ("Usuário") declara que leu, entendeu e concorda integralmente com os termos abaixo.</p>

          <p><strong>1. NATUREZA DO SERVIÇO</strong></p>
          <p>1.1. A Aftershot é uma plataforma digital de edição fotográfica automatizada por inteligência artificial, destinada a profissionais do mercado imobiliário e de hospedagem.</p>
          <p>1.2. O serviço consiste no processamento de imagens enviadas pelo Usuário por meio de predefinições de iluminação, atmosfera e correção óptica.</p>

          <p><strong>2. CRÉDITOS E PAGAMENTO</strong></p>
          <p>2.1. O acesso às funcionalidades de edição requer a aquisição de pacotes de créditos, mediante pagamento único.</p>
          <p>2.2. Cada crédito corresponde ao processamento de uma (1) foto com qualquer predefinição disponível.</p>
          <p>2.3. O primeiro ajuste (re-edição) de cada foto é gratuito; ajustes adicionais consomem créditos normalmente.</p>

          <p><strong>3. POLÍTICA DE NÃO REEMBOLSO — PRODUTO DIGITAL</strong></p>
          <p>3.1. Conforme o artigo 49, §2º do Código de Defesa do Consumidor (Lei nº 8.078/1990), o direito de arrependimento não se aplica a produtos digitais de acesso imediato, uma vez que o conteúdo é disponibilizado instantaneamente após a compra.</p>
          <p>3.2. Ao adquirir créditos, o Usuário reconhece que está ciente da natureza digital e instantânea do produto, e que não poderá solicitar reembolso após a confirmação do pagamento.</p>
          <p>3.3. Em caso de falha técnica comprovada que impossibilite o uso dos créditos adquiridos, a Aftershot se compromete a restaurar os créditos afetados ou oferecer solução equivalente.</p>

          <p><strong>4. PROPRIEDADE INTELECTUAL</strong></p>
          <p>4.1. As imagens enviadas pelo Usuário permanecem de sua propriedade. A Aftershot não reivindica direitos sobre as fotos originais ou editadas.</p>
          <p>4.2. A tecnologia, design, código-fonte e predefinições da plataforma são de propriedade exclusiva da Aftershot.</p>
          <p>4.3. É vedada a reprodução, engenharia reversa ou distribuição da tecnologia da plataforma.</p>

          <p><strong>5. RESPONSABILIDADES DO USUÁRIO</strong></p>
          <p>5.1. O Usuário é responsável pela veracidade e legalidade das imagens enviadas.</p>
          <p>5.2. É vedado o upload de conteúdo ilegal, difamatório, pornográfico ou que viole direitos de terceiros.</p>
          <p>5.3. O Usuário é responsável pela segurança de suas credenciais de acesso.</p>

          <p><strong>6. ARMAZENAMENTO E EXCLUSÃO</strong></p>
          <p>6.1. As fotos editadas ficam disponíveis na galeria por até 30 (trinta) dias, sendo removidas automaticamente após esse período.</p>
          <p>6.2. O Usuário é responsável por fazer o download das fotos editadas dentro desse prazo.</p>

          <p><strong>7. DISPONIBILIDADE E LIMITAÇÃO DE RESPONSABILIDADE</strong></p>
          <p>7.1. A Aftershot empenha seus melhores esforços para manter a plataforma disponível, mas não garante disponibilidade ininterrupta.</p>
          <p>7.2. A Aftershot não se responsabiliza por danos indiretos, perdas de receita ou lucros cessantes decorrentes do uso ou impossibilidade de uso da plataforma.</p>
          <p>7.3. Os resultados da edição por IA são gerados automaticamente e podem variar. A Aftershot não garante resultados específicos.</p>

          <p><strong>8. PRIVACIDADE E DADOS PESSOAIS</strong></p>
          <p>8.1. A Aftershot coleta e processa dados pessoais (nome, e-mail, dados de pagamento) exclusivamente para a prestação do serviço, em conformidade com a Lei Geral de Proteção de Dados (Lei nº 13.709/2018 — LGPD).</p>
          <p>8.2. Dados de pagamento são processados por intermediadores terceirizados certificados (PCI-DSS) e não são armazenados em nossos servidores.</p>

          <p><strong>9. MODIFICAÇÕES DOS TERMOS</strong></p>
          <p>9.1. A Aftershot reserva-se o direito de alterar estes termos a qualquer momento, mediante aviso na plataforma.</p>
          <p>9.2. O uso contínuo da plataforma após alterações constitui aceite dos novos termos.</p>

          <p><strong>10. FORO E LEGISLAÇÃO APLICÁVEL</strong></p>
          <p>10.1. Estes termos são regidos pela legislação brasileira.</p>
          <p>10.2. Fica eleito o foro da comarca de São Paulo/SP para dirimir quaisquer controvérsias.</p>

          <p><strong>11. CONTATO</strong></p>
          <p>Para dúvidas, suporte ou solicitações relacionadas a estes termos: <strong>contato@aftershot.com.br</strong></p>
        </div>

        {/* Footer */}
        <div style={{ padding:'16px 28px 24px', borderTop:'1px solid var(--line)' }}>
          <label style={{ display:'flex', alignItems:'flex-start', gap: 10, cursor:'pointer', marginBottom: 16 }}>
            <input type="checkbox" checked={checked} onChange={e => setChecked(e.target.checked)}
              style={{ width: 18, height: 18, marginTop: 2, accentColor:'var(--accent)', flexShrink: 0 }}/>
            <span style={{ fontSize: 13, lineHeight: 1.5, color:'var(--ink)' }}>
              Li e concordo com os <strong>Termos de Uso e Condições Gerais</strong> da plataforma Aftershot, incluindo a política de não reembolso para produtos digitais.
            </span>
          </label>
          <Button variant="accent" size="lg" style={{ width:'100%', justifyContent:'center', opacity: checked ? 1 : .4 }}
            onClick={handleAccept} disabled={!checked || loading}>
            {loading ? 'Registrando...' : 'Aceitar e continuar'}
          </Button>
        </div>
      </div>
    </div>
  );
}
