// === Main App ===
const { useState: useAppState, useEffect: useAppEffect, useMemo: useAppMemo, useRef: useAppRef } = React;

// Kinds donde Enter ↵ realmente avanza la pregunta.
// En textarea intencionalmente NO avanza (Enter crea nueva línea).
const ENTER_KINDS = new Set(['text', 'cards', 'chips', 'ab', 'toggles']);
function kindAcceptsEnter(kind) { return ENTER_KINDS.has(kind); }

class SummaryBoundary extends React.Component {
  constructor(props) { super(props); this.state = { err: null }; }
  static getDerivedStateFromError(err) { return { err }; }
  componentDidCatch(err, info) { console.error('Summary crashed:', err, info); }
  render() {
    if (this.state.err) {
      return (
        <div className="summary" style={{ paddingTop: 80 }}>
          <h2>Algo falló al cargar el resumen</h2>
          <p className="summary-lead">Detalle técnico: {String(this.state.err?.message || this.state.err)}</p>
          <div style={{ display: 'flex', gap: 12, marginTop: 24 }}>
            <button className="btn btn-ghost" onClick={() => { this.setState({ err: null }); this.props.onReset?.(); }}>Volver a la última pregunta</button>
            <button className="btn btn-primary" onClick={() => { this.setState({ err: null }); }}>Reintentar</button>
          </div>
        </div>
      );
    }
    return this.props.children;
  }
}

function App() {
  const [answers, setAnswers] = useAppState({});
  const [idx, setIdx] = useAppState(-1); // -1 = intro, N = question index, special: 'summary' | 'sent'
  const [displayIdx, setDisplayIdx] = useAppState(-1);
  const [transitioning, setTransitioning] = useAppState(false);
  const [tweaksOpen, setTweaksOpen] = useAppState(false);
  const [sent, setSent] = useAppState(false);
  const [interstitialFor, setInterstitialFor] = useAppState(null);

  // Register edit-mode listener BEFORE announcing availability
  useAppEffect(() => {
    function handler(e) {
      if (!e.data) return;
      if (e.data.type === '__activate_edit_mode') setTweaksOpen(true);
      if (e.data.type === '__deactivate_edit_mode') setTweaksOpen(false);
    }
    window.addEventListener('message', handler);
    window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    return () => window.removeEventListener('message', handler);
  }, []);

  // Compute visible questions (after filtering out those whose `condition` fails)
  const visibleQuestions = useAppMemo(() => {
    return window.QUESTIONNAIRE.filter(q => !q.condition || q.condition(answers));
  }, [answers]);

  // Animate index transitions: fade+lift out, then swap, then fade+lift in
  useAppEffect(() => {
    if (idx === displayIdx) return;
    setTransitioning(true);
    const t = setTimeout(() => {
      setDisplayIdx(idx);
      setTransitioning(false);
    }, 260);
    return () => clearTimeout(t);
  }, [idx]);

  const current = displayIdx >= 0 && displayIdx < visibleQuestions.length ? visibleQuestions[displayIdx] : null;
  const atSummary = displayIdx === 'summary';
  const atIntro = displayIdx === -1;

  function updateAnswer(id, val) {
    setAnswers(prev => ({ ...prev, [id]: val }));
  }

  const canProceed = !current || !current.required || answerFilled(answers[current?.id]);

  function answerFilled(v) {
    if (v === undefined || v === null) return false;
    if (typeof v === 'string') return v.trim().length > 0;
    if (Array.isArray(v)) return v.length > 0;
    if (typeof v === 'object') return Object.keys(v).length > 0;
    return true;
  }

  function next() {
    if (idx === -1) {
      const firstSection = visibleQuestions[0]?.section;
      if (firstSection) {
        setInterstitialFor(firstSection);
        return;
      }
      setIdx(0);
      return;
    }
    if (idx === 'summary') return;
    if (idx < visibleQuestions.length - 1) {
      const curSection = visibleQuestions[idx].section;
      const nextSection = visibleQuestions[idx + 1].section;
      if (nextSection !== curSection && SECTION_INTROS[nextSection]?.title) {
        setInterstitialFor(nextSection);
        return;
      }
      setIdx(idx + 1);
    } else {
      setIdx('summary');
    }
  }

  function dismissInterstitial() {
    if (idx === -1) {
      setIdx(0);
    } else if (typeof idx === 'number' && idx < visibleQuestions.length - 1) {
      setIdx(idx + 1);
    }
    setInterstitialFor(null);
  }

  function prev() {
    if (interstitialFor != null) { setInterstitialFor(null); return; }
    if (idx === 'summary') setIdx(visibleQuestions.length - 1);
    else if (idx > 0) setIdx(idx - 1);
    else if (idx === 0) setIdx(-1);
  }

  function editFrom(questionId) {
    const i = visibleQuestions.findIndex(q => q.id === questionId);
    if (i >= 0) setIdx(i);
  }

  // Keyboard
  useAppEffect(() => {
    function onKey(e) {
      if (interstitialFor != null) return; // Interstitial owns its own keyboard handling
      if (e.target.matches('input, textarea, select')) {
        if (e.key === 'Enter' && !e.shiftKey && current?.kind !== 'textarea') {
          e.preventDefault();
          if (canProceed) next();
        }
        return;
      }
      if (e.key === 'ArrowRight' || e.key === 'Enter') { if (canProceed) next(); }
      if (e.key === 'ArrowLeft') prev();
    }
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [idx, canProceed, current, interstitialFor]);

  // Tweaks
  const [tweaks, setTweaks] = useAppState(() => {
    const d = /*EDITMODE-BEGIN*/{
      "tone": "juguetón",
      "cardStyle": "glass",
      "transition": "fade"
    }/*EDITMODE-END*/;
    return d;
  });

  useAppEffect(() => {
    document.body.setAttribute('data-cards', tweaks.cardStyle);
    document.body.setAttribute('data-transition', tweaks.transition);
    document.body.setAttribute('data-tone', tweaks.tone);
  }, [tweaks]);

  useAppEffect(() => {
    const section = current?.section ?? (atIntro ? 1 : (atSummary || sent ? 10 : 1));
    document.body.setAttribute('data-section', String(section));
  }, [current, atIntro, atSummary, sent]);

  useAppEffect(() => {
    const name = current?.sectionName?.toLowerCase();
    if (name === 'agendador') {
      document.body.setAttribute('data-agent-type', 'agendador');
    } else if (name === 'cotizador') {
      document.body.setAttribute('data-agent-type', 'cotizador');
    } else if (name === 'recepcionista') {
      document.body.setAttribute('data-agent-type', 'recepcionista');
    } else {
      document.body.removeAttribute('data-agent-type');
    }
  }, [current]);

  // Pre-generación de sugerencias IA. El cache usa contextHash por pregunta,
  // así que no hace falta invalidar manualmente: los cambios en respuestas
  // upstream producen un nuevo hash y una nueva entrada de cache automáticamente.
  useAppEffect(() => {
    if (!window.aiCache) return;
    const timer = setTimeout(() => {
      window.aiCache.preload(answers);
    }, 1200);
    return () => clearTimeout(timer);
  }, [answers]);

  // Prellenado desde la web del cliente: cuando responde business_website,
  // leemos la página en el server y completamos SOLO los campos que sigan
  // vacíos (nunca pisamos lo que el usuario ya escribió).
  const [webExtractStatus, setWebExtractStatus] = useAppState(null); // null | 'loading' | 'done' | 'error'
  const webExtractedUrl = useAppRef(null);
  useAppEffect(() => {
    const raw = (answers.business_website || '').trim();
    if (!raw || raw.length < 4) return;
    // Espera a que el usuario avance de la pregunta de la web (evita disparar
    // por cada tecla mientras escribe la URL).
    if (current?.id === 'business_website') return;
    if (webExtractedUrl.current === raw) return;
    webExtractedUrl.current = raw;
    setWebExtractStatus('loading');
    fetch('/api/web-extract', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ url: raw }),
    })
      .then((r) => r.json())
      .then((j) => {
        if (!j.ok || !j.data) { setWebExtractStatus('error'); return; }
        const d = j.data;
        setAnswers((prev) => {
          const next = { ...prev };
          const emptyStr = (v) => typeof v !== 'string' || !v.trim();
          if (d.business_description && emptyStr(next.business_description)) next.business_description = d.business_description;
          if (d.business_differentiator && emptyStr(next.business_differentiator)) next.business_differentiator = d.business_differentiator;
          if (Array.isArray(d.faqs) && d.faqs.length && (!Array.isArray(next.faqs) || next.faqs.length === 0)) next.faqs = d.faqs;
          // Conocimiento extra de la web → viaja al markdown y al prompt del agente
          if (d.extra_notes) next.website_extract = d.extra_notes;
          return next;
        });
        setWebExtractStatus('done');
        setTimeout(() => setWebExtractStatus(null), 6000);
      })
      .catch(() => setWebExtractStatus('error'))
      .finally(() => setTimeout(() => setWebExtractStatus((s) => (s === 'loading' ? s : null)), 7000));
  }, [answers.business_website, current]);

  function setTweak(k, v) {
    const next = { ...tweaks, [k]: v };
    setTweaks(next);
    window.parent.postMessage({ type: '__edit_mode_set_keys', edits: next }, '*');
  }

  // Progress
  const totalSteps = visibleQuestions.length;
  const currentStep = idx === -1 ? 0 : (idx === 'summary' ? totalSteps : idx + 1);
  const progress = (currentStep / totalSteps) * 100;

  return (
    <>
      <div className="topbar">
        <div className="brand">
          <img src="assets/mamut-logo.png" alt="Mamut" className="brand-logo" />
          <span className="brand-sub">· Constructor agente</span>
        </div>
        <div className="topbar-right">
          {webExtractStatus && (
            <div className="progress-chip" title="Prellenado desde tu página web">
              {webExtractStatus === 'loading' && '🔍 Leyendo tu web…'}
              {webExtractStatus === 'done' && '✓ Prellenamos respuestas desde tu web'}
              {webExtractStatus === 'error' && 'No pudimos leer tu web — sigue normal'}
            </div>
          )}
          {idx !== -1 && !atSummary && !sent && (
            <div className="progress-chip">
              <span className="dot"></span>
              Sección {current?.section} · Pregunta {currentStep} de {totalSteps}
            </div>
          )}
        </div>
      </div>

      {idx !== -1 && !sent && (
        <div className="progress-bar">
          <div className="progress-bar-fill" style={{ width: `${progress}%` }}></div>
        </div>
      )}

      <div className="stage">
        <div className={`stage-inner ${transitioning ? 'is-leaving' : 'is-entering'}`}>
          {interstitialFor != null && (
            <Interstitial section={interstitialFor} onContinue={dismissInterstitial} />
          )}
          {interstitialFor == null && <>
            {atIntro && <IntroScreen onStart={next} />}
            {/* Al enviar redirigimos a gracias.html (ver onSend abajo), así que aquí no renderizamos CelebrationScreen */}
            {current && !sent && (
              <QuestionSlide
                key={current.id}
                question={current}
                value={answers[current.id]}
                onChange={(v) => updateAnswer(current.id, v)}
                context={answers}
              />
            )}
            {atSummary && !sent && (
              <div className="slide" style={{ alignItems: 'flex-start' }}>
                <SummaryBoundary onReset={() => setIdx(visibleQuestions.length - 1)}>
                  <SummaryView
                    answers={answers}
                    questions={window.QUESTIONNAIRE}
                    onEdit={editFrom}
                    onSend={() => {
                      // Validación dura ANTES de enviar — el server rechaza con
                      // 400 email/teléfono inválidos y el envío es fire-and-forget,
                      // así que un rechazo silencioso perdería TODAS las respuestas.
                      const emailQ = window.QUESTIONNAIRE.find(q => q.id === 'business_email');
                      const phoneQ = window.QUESTIONNAIRE.find(q => q.id === 'business_phone');
                      if (emailQ?.validator && !emailQ.validator(answers.business_email || '')) {
                        alert('Tu email no parece válido — corrígelo para poder crear tu agente.');
                        editFrom('business_email');
                        return;
                      }
                      if (phoneQ?.validator && !phoneQ.validator(answers.business_phone || '')) {
                        alert('Tu teléfono no parece válido — corrígelo para poder crear tu agente.');
                        editFrom('business_phone');
                        return;
                      }
                      // El id se genera acá para que gracias.html tenga el link
                      // al simulador de inmediato (el POST es fire-and-forget).
                      const submissionId = (crypto.randomUUID && crypto.randomUUID()) || null;
                      // 1. Cache para gracias.html
                      try {
                        sessionStorage.setItem('cuestionario_answers', JSON.stringify(answers));
                        if (submissionId) {
                          sessionStorage.setItem('cuestionario_submission_id', submissionId);
                          // Copia durable: sobrevive si sessionStorage se pierde
                          // (pestaña nueva, restore del navegador, etc.)
                          localStorage.setItem('cuestionario_last_submission', JSON.stringify({ id: submissionId, ts: Date.now() }));
                        }
                      } catch (err) {
                        console.warn('No pude guardar respuestas en sessionStorage:', err);
                      }
                      // 2. POST al backend (fire-and-forget). No bloquea el redirect.
                      //    keepalive=true garantiza que la request sobrevive la navegación.
                      try {
                        fetch('/api/submit', {
                          method: 'POST',
                          headers: { 'Content-Type': 'application/json' },
                          body: JSON.stringify({ answers, submissionId }),
                          keepalive: true,
                        }).catch((err) => console.warn('submit falló (fire-and-forget)', err));
                      } catch (err) {
                        console.warn('submit no se pudo disparar:', err);
                      }
                      // 3. Redirect al cierre
                      window.location.href = 'gracias.html';
                    }}
                    onUpdateOverride={(key, value) => {
                      setAnswers(prev => {
                        const next = { ...prev };
                        if (value === undefined) delete next[key];
                        else next[key] = value;
                        return next;
                      });
                    }}
                  />
                </SummaryBoundary>
              </div>
            )}
          </>}
        </div>
      </div>

      {idx !== -1 && !atSummary && !sent && interstitialFor == null && (
        <div className="footer">
          <button className="btn btn-ghost" onClick={prev}>
            <svg width="12" height="12" viewBox="0 0 12 12" fill="none">
              <path d="M7.5 2L3 6l4.5 4" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
            Atrás
          </button>
          {current && kindAcceptsEnter(current.kind) ? (
            <div className="kbd-hint">
              <span>Presiona</span>
              <span className="kbd">Enter ↵</span>
              <span>para continuar</span>
            </div>
          ) : (
            <div className="kbd-hint" aria-hidden></div>
          )}
          <button className="btn btn-primary" disabled={!canProceed || transitioning} onClick={next}>
            {idx === visibleQuestions.length - 1 ? 'Ver resumen' : 'Siguiente'}
            <svg width="12" height="12" viewBox="0 0 12 12" fill="none">
              <path d="M4.5 2L9 6l-4.5 4" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
          </button>
        </div>
      )}

      {atSummary && !sent && interstitialFor == null && (
        <div className="footer">
          <button className="btn btn-ghost" onClick={prev}>
            <svg width="12" height="12" viewBox="0 0 12 12" fill="none">
              <path d="M7.5 2L3 6l4.5 4" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
            Volver a editar
          </button>
          <div></div>
          <div></div>
        </div>
      )}

      <div className="corner-mark">hecho con cariño</div>

      {tweaksOpen && (
        <TweaksPanel tweaks={tweaks} onChange={setTweak} onClose={() => setTweaksOpen(false)} />
      )}
    </>
  );
}

// ---- Question Slide ----
function QuestionSlide({ question, value, onChange, context }) {
  const Renderer = {
    text: window.TextInput,
    textarea: window.TextareaInput,
    cards: window.CardsInput,
    chips: window.ChipsInput,
    ab: window.ABInput,
    ranking: window.RankingInput,
    schedule: window.ScheduleInput,
    'faq-builder': window.FAQBuilder,
    'identity-fields': window.IdentityFields,
    toggles: window.TogglesInput,
    'link-list': window.LinkListInput,
    'flow-tree': window.FlowTreeInput,
    thresholds: window.ThresholdsInput,
    'agent-types-multi': window.AgentTypesMulti,
    'stepped-slider': window.SteppedSlider,
    'linear-slider': window.LinearSlider,
    'info-card': window.InfoCard,
    'callers-list': window.CallersList,
    'drag-order-questions': window.DragOrderQuestions,
    'team-member-field': window.TeamMemberField,
    'routing-list': window.RoutingList,
    'agent-intro': window.AgentIntro,
  }[question.kind];

  return (
    <div className="slide slide-active">
      <div className="slide-inner">
        <div className="section-label">
          <span className="idx">{question.section}</span>
          {question.sectionName}
        </div>
        <h2 className="q-title" dangerouslySetInnerHTML={{ __html: question.prompt }} />
        {question.subtitle && <p className="q-subtitle">{question.subtitle}</p>}
        {Renderer ? (
          <Renderer question={question} value={value} onChange={onChange} context={context} />
        ) : (
          <div className="summary-empty">Tipo de pregunta desconocido: {question.kind}</div>
        )}
      </div>
    </div>
  );
}

// ---- Intro ----
function IntroScreen({ onStart }) {
  return (
    <div className="intro">
      <div className="intro-inner">
        <div className="intro-eyebrow">Constructor agente · ~8 minutos</div>
        <h1>Creemos tu <em>agente de IA</em> juntos.</h1>
        <p>Vamos a hacerte preguntas sobre tu negocio. A medida que respondes, generamos ejemplos y opciones adaptadas a lo tuyo — no tienes que escribir todo desde cero.</p>
        <p style={{ marginTop: 12, color: 'var(--accent)', fontWeight: 500 }}>
          Apenas termines, comenzamos a generar la primera versión de tu agente.
        </p>
        <div className="intro-meta">
          <div>
            <span>Secciones</span>
            <span className="meta-val">10</span>
          </div>
          <div>
            <span>Preguntas</span>
            <span className="meta-val">~20</span>
          </div>
          <div>
            <span>Tiempo</span>
            <span className="meta-val">8 min</span>
          </div>
        </div>
        <button className="btn btn-primary" onClick={onStart} style={{ padding: '14px 24px', fontSize: 15 }}>
          Empezar
          <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
            <path d="M3 7h8M7 3l4 4-4 4" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" />
          </svg>
        </button>
        <div style={{ marginTop: 32, display: 'flex', gap: 24, fontSize: 13, color: 'var(--muted)', alignItems: 'center' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <span style={{ width: 8, height: 8, borderRadius: '50%', background: 'var(--violet)' }}></span>
            Preguntas adaptativas
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <span style={{ width: 8, height: 8, borderRadius: '50%', background: 'var(--lavender)' }}></span>
            Ejemplos generados para ti
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <span style={{ width: 8, height: 8, borderRadius: '50%', background: 'var(--indigo)' }}></span>
            Edita lo que quieras al final
          </div>
        </div>
      </div>
    </div>
  );
}

// ---- Tweaks Panel ----
function TweaksPanel({ tweaks, onChange, onClose }) {
  return (
    <div className="tweaks-panel">
      <h5>Tweaks <span>·</span></h5>
      <div className="tweak-group">
        <label>Tono del constructor</label>
        <div className="tweak-opts">
          {['serio', 'warm', 'juguetón'].map(t => (
            <button key={t} className={`tweak-opt ${tweaks.tone === t ? 'active' : ''}`} onClick={() => onChange('tone', t)}>{t}</button>
          ))}
        </div>
      </div>
      <div className="tweak-group">
        <label>Estilo de cards</label>
        <div className="tweak-opts">
          {['default', 'flat', 'bordered', 'glass'].map(s => (
            <button key={s} className={`tweak-opt ${tweaks.cardStyle === s ? 'active' : ''}`} onClick={() => onChange('cardStyle', s)}>{s}</button>
          ))}
        </div>
      </div>
      <div className="tweak-group">
        <label>Transición entre preguntas</label>
        <div className="tweak-opts">
          {['default', 'fade', 'slide', 'scale'].map(s => (
            <button key={s} className={`tweak-opt ${tweaks.transition === s ? 'active' : ''}`} onClick={() => onChange('transition', s)}>{s}</button>
          ))}
        </div>
      </div>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
