/* ====================================================================
   Appril · Diagnóstico — wizard.jsx
   Typeform conversacional · una pregunta por pantalla · 4 gifts progresivos
   ==================================================================== */

const { useState, useMemo, useEffect, useCallback, useRef } = React;

/* ---- helper: label de bloque ---- */
function blockLabel(blockKey) {
  const b = (AP.BLOCKS || []).find((x) => x.key === blockKey);
  return b ? b.label : "";
}

/* ---- helper: step_key can\u00f3nico para tracking de funnel ---- */
function stepKeyOf(s) {
  if (!s) return null;
  if (s.kind === "question") return s.q.step_key || s.q.id;
  if (s.kind === "validator") return "validator:" + s.validatorId;
  if (s.kind === "gift") return "gift:" + s.giftId;
  return s.kind; // intro | preliminary | contact
}

/* ---- helper: label visible de una respuesta (para answer_label) ---- */
function answerLabel(q, v) {
  if (!q || !q.options || v == null) return null;
  const find = (val) => {
    const o = q.options.find((o) => o.value === val);
    return o ? o.label : String(val);
  };
  if (Array.isArray(v)) return v.map(find).join(", ");
  return find(v);
}

/* ===================== Flujo (preguntas + gifts + validadores) ===================== */
function useWizardFlow(answers, showValidators) {
  return useMemo(() => {
    const steps = [];
    AP.QUESTIONS.forEach((q) => {
      if (q.kind === "intro") { steps.push({ kind: "intro", q, block: q.block }); return; }
      if (q.showIf && !q.showIf(answers)) return;
      if (q.validatorBefore && showValidators) {
        steps.push({ kind: "validator", validatorId: q.validatorBefore, block: q.block });
      }
      steps.push({ kind: "question", q, block: q.block });
      // Regla: hallazgo (gift) SIEMPRE antes del insight científico (validator)
      if (q.giftAfter) {
        steps.push({ kind: "gift", giftId: q.giftAfter, block: q.block });
      }
      if (q.validatorAfter && showValidators) {
        steps.push({ kind: "validator", validatorId: q.validatorAfter, block: q.block });
      }
    });
    steps.push({ kind: "preliminary", block: "resultado" });
    steps.push({ kind: "contact", block: "resultado" });
    return steps;
  }, [answers, showValidators]);
}

/* ===================== Top bar ===================== */
function WizardTopBar({ onClose, sectionLabel, sectionIdx, sectionsTotal, pct }) {
  return (
    <div className="wizard__top">
      <div className="wizard__brand">
        <span className="wizard__brandTitle">{AP.t("wizard.brandTitle")}</span>
        <span className="wizard__brandBy">{sectionLabel ? AP.t("wizard.stepOf", { section: sectionLabel, idx: sectionIdx, total: sectionsTotal }) : AP.t("wizard.brandBy")}</span>
      </div>
      <div className="wizard__progress">
        <div className="wizard__bar"><span style={{ width: pct + "%" }} /></div>
      </div>
      <button className="wizard__close" onClick={onClose} aria-label={AP.t("wizard.close")}>
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M6 6l12 12M18 6L6 18"/></svg>
      </button>
    </div>
  );
}

/* ===================== Step shell ===================== */
function StepShell({ chip, children }) {
  return (
    <div className="wizard__step">
      {chip && (
        <div className="wizard__chip">
          <span>{chip}</span>
        </div>
      )}
      {children}
    </div>
  );
}

/* ===================== Choice ===================== */
function ChoiceStep({ q, value, onChange, onNext, idx, total, showChip }) {
  const isMulti = !!q.multi;
  // Selección simple por ÍNDICE: evita que dos opciones con el mismo `value`
  // (p.ej. "10 minutos" y "No lo sé", o las dos "media" de urgencia) se marquen juntas.
  const [pickedIdx, setPickedIdx] = useState(() => isMulti ? -1 : q.options.findIndex((o) => o.value === value));
  const [pickedMulti, setPickedMulti] = useState(() => Array.isArray(value) ? value : []);
  useEffect(() => {
    if (isMulti) setPickedMulti(Array.isArray(value) ? value : []);
    else setPickedIdx(q.options.findIndex((o) => o.value === value));
  }, [q.id, value]);

  const isSelected = (opt, i) => isMulti ? pickedMulti.includes(opt.value) : pickedIdx === i;
  const pickedOpt = (!isMulti && pickedIdx >= 0) ? q.options[pickedIdx] : null;
  const pickedOpts = isMulti ? q.options.filter((o) => pickedMulti.includes(o.value)) : [];

  const handlePick = (opt, i) => {
    if (isMulti) {
      const arr = [...pickedMulti];
      const j = arr.indexOf(opt.value);
      if (j >= 0) arr.splice(j, 1); else arr.push(opt.value);
      setPickedMulti(arr);
      onChange(arr);
    } else {
      setPickedIdx(i);
      onChange(opt.value);
      // Nunca auto-avanzar: comportamiento consistente, el usuario controla.
    }
  };

  const micros = isMulti
    ? pickedOpts.map((o) => o.microcopy).filter(Boolean)
    : (pickedOpt && pickedOpt.microcopy ? [pickedOpt.microcopy] : (pickedIdx >= 0 && q.microcopy ? [q.microcopy] : []));

  return (
    <StepShell chip={showChip ? blockLabel(q.block) : null}>
      <h2 className="wizard__q">
        {q.text}
        {isMulti && <span className="wizard__qhint">{AP.t("wizard.multiHint")}</span>}
      </h2>
      <div className="opts">
        {q.options.map((opt, i) => {
          const letter = String.fromCharCode(65 + i);
          const sel = isSelected(opt, i);
          return (
            <button key={String(opt.value) + i}
              className={"opt" + (sel ? " is-selected" : "")}
              onClick={() => handlePick(opt, i)}>
              <span className="opt__key">{letter}</span>
              <span className="opt__label">{opt.label}</span>
              <span className={"opt__check" + (isMulti ? " opt__check--multi" : "")}>
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
              </span>
            </button>
          );
        })}
      </div>
      {micros.length > 0 && (
        <div className="micro">
          <span className="micro__ico">✦</span>
          <div>{micros[0]}</div>
        </div>
      )}
    </StepShell>
  );
}

/* ===================== Number ===================== */
function NumberStep({ q, value, onChange, idx, total, showChip }) {
  const [val, setVal] = useState(value || "");
  useEffect(() => { setVal(value || ""); }, [q.id]);
  const handle = (e) => {
    const v = e.target.value.replace(/[^\d.]/g, "");
    setVal(v); onChange(v);
  };
  return (
    <StepShell chip={showChip ? blockLabel(q.block) : null}>
      <h2 className="wizard__q">{q.text}</h2>
      <div className="numfield">
        {q.prefix && <span className="numfield__prefix">{q.prefix}</span>}
        <input type="text" inputMode="decimal" value={val} onChange={handle} placeholder={q.placeholder || "0"} autoFocus />
      </div>
    </StepShell>
  );
}

/* ===================== Intro ===================== */
function IntroStep({ q, onNext, idx, total }) {
  return (
    <StepShell idx={idx} total={total}>
      <div className="intro">
        <span className="eyebrow">{AP.t("wizard.introEyebrow")}</span>
        <h1>{q.title}</h1>
        <p className="wizard__sub">{q.body}</p>
        <div className="intro__meta">
          <span><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>{q.duration}</span>
          <span><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><polyline points="20 6 9 17 4 12"/></svg> {AP.t("wizard.introMeta")}</span>
        </div>
        <div>
          <button className="btn btn--primary btn--lg" onClick={onNext}>
            {q.cta}
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
          </button>
        </div>
      </div>
    </StepShell>
  );
}

/* ===================== Validator ===================== */
function ValidatorStep({ validatorId, idx, total, onNext }) {
  const v = AP.VALIDATORS[validatorId];
  if (!v) return null;
  return (
    <StepShell idx={idx} total={total}>
      <div className="validator">
        <span className="validator__eye">{AP.t("wizard.validatorEye")}</span>
        <h3>{v.title}</h3>
        <p>{v.body}</p>
        <p className="validator__src">{AP.t("wizard.validatorSrc", { source: v.source })}</p>
      </div>
      <div>
        <button className="btn btn--ink" onClick={onNext}>
          {AP.t("common.continue")}
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
        </button>
      </div>
    </StepShell>
  );
}

/* ===================== GIFTS (4 mini-recompensas progresivas) ===================== */
function GiftStep({ giftId, answers, idx, total, onNext }) {
  const g = AP.GIFTS[giftId];
  if (!g) return null;

  const calc = AP.calculateDiscoveryPreview(answers);
  const maturity = AP.getAgendaMaturityPreview(answers);

  // --- GIFT 1: Nivel preliminar
  if (g.kind === "level") {
    const ctx = answers.appointment_scheduler_type;
    const ctxCopy = AP.t("wizard.schedulerCtx." + ctx);
    const ctxCopyFinal = (ctxCopy === "wizard.schedulerCtx." + ctx) ? AP.t("wizard.schedulerCtx.default") : ctxCopy;

    return (
      <StepShell idx={idx} total={total}>
        <div className="gift gift--level">
          <span className="gift__eye">{g.eyebrow}</span>
          <h2 className="gift__title">{g.title}</h2>
          <div className="gift__levelChip">
            {AP.t("wizard.giftLevelChip")}
            <strong>{maturity.current.name}</strong>
          </div>
          <LevelBar currentId={maturity.current.id} />
          <p className="gift__ctxCopy">{ctxCopyFinal}</p>
        </div>
        <div>
          <button className="btn btn--primary btn--lg" onClick={onNext}>
            {g.cta}
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
          </button>
        </div>
      </StepShell>
    );
  }

  // --- GIFT 2: Pérdida anual
  if (g.kind === "money") {
    return (
      <StepShell idx={idx} total={total}>
        <div className="gift gift--money">
          <span className="gift__eye">{g.eyebrow}</span>
          <h2 className="gift__title">{g.title}</h2>
          <div className="gift__metric">{AP.fmtUSD(calc.annual_lost_revenue)}</div>
          <p className="gift__metricLab">{AP.t("wizard.moneyLab")}</p>
          <div className="gift__breakdown">
            <div className="gift__breakRow"><span>{AP.t("wizard.breakLost")}</span><strong>{calc.lost_appointments_midpoint}</strong></div>
            <div className="gift__breakRow"><span>{AP.t("wizard.breakTicket")}</span><strong>USD {calc.average_ticket_midpoint}</strong></div>
            <div className="gift__breakRow"><span>{AP.t("wizard.breakMonths")}</span><strong>12</strong></div>
          </div>
          <p className="gift__note">{g.note}</p>
        </div>
        <div>
          <button className="btn btn--primary btn--lg" onClick={onNext}>
            {g.cta}
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
          </button>
        </div>
      </StepShell>
    );
  }

  // --- GIFT 3: Tiempo administrativo (solo horas, sin dinero)
  if (g.kind === "time") {
    return (
      <StepShell>
        <div className="gift gift--time">
          <span className="gift__eye">{g.eyebrow}</span>
          <h2 className="gift__title">{g.title}</h2>
          <div className="gift__pairgrid">
            <div className="gift__pair">
              <div className="gift__pairVal">{AP.fmtHours(calc.monthly_admin_hours)}</div>
              <div className="gift__pairLab">{AP.t("wizard.perMonth")}</div>
            </div>
            <div className="gift__pair">
              <div className="gift__pairVal">{AP.fmtHours(calc.annual_admin_hours)}</div>
              <div className="gift__pairLab">{AP.t("wizard.perYear")}</div>
            </div>
          </div>
          <p className="gift__note">{AP.t("wizard.timeNote")}</p>
        </div>
        <div>
          <button className="btn btn--primary btn--lg" onClick={onNext}>
            {g.cta}
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
          </button>
        </div>
      </StepShell>
    );
  }

  // --- GIFT 4: Costo administrativo (diseño claro como gift_nivel)
  if (g.kind === "cost") {
    const cost = calc.admin_cost_annual;
    return (
      <StepShell>
        <div className="gift gift--cost">
          <span className="gift__eye">{g.eyebrow}</span>
          <h2 className="gift__title">{g.title}</h2>
          <div className="gift__costChip">
            <span>{g.bodyTop}</span>
            <strong>{AP.fmtUSD(cost)}<span className="gift__costPer">{AP.t("wizard.costPer")}</span></strong>
          </div>
          <p className="gift__ctxCopy">{g.bodyBottom}</p>
        </div>
        <div>
          <button className="btn btn--primary btn--lg" onClick={onNext}>
            {g.cta}
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
          </button>
        </div>
      </StepShell>
    );
  }

  // --- GIFT WIN: after interrupciones validator
  if (g.kind === "win") {
    return (
      <StepShell idx={idx} total={total}>
        <div className="gift gift--win">
          <span className="gift__eye">{g.eyebrow}</span>
          <div className="gift__winIco">
            <svg width="56" height="56" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
              <path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/>
              <circle cx="12" cy="12" r="4"/>
            </svg>
          </div>
          <h2 className="gift__title">{g.title}</h2>
          <p className="gift__winBody">{g.body}</p>
          <div className="gift__winTags">
            <span>{AP.t("wizard.winCalm")}</span>
            <span>{AP.t("wizard.winFree")}</span>
            <span>{AP.t("wizard.winIncome")}</span>
          </div>
        </div>
        <div>
          <button className="btn btn--primary btn--lg" onClick={onNext}>
            {g.cta}
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
          </button>
        </div>
      </StepShell>
    );
  }

  // --- GIFT 4: Costo invisible / carga mental
  if (g.kind === "invisible") {
    const ctx = Array.isArray(answers.agenda_mental_load_context)
      ? answers.agenda_mental_load_context[0]
      : answers.agenda_mental_load_context;
    const mlc = AP.MENTAL_LOAD_COPY[ctx] || AP.MENTAL_LOAD_COPY.no_siente;
    return (
      <StepShell idx={idx} total={total}>
        <div className="gift gift--invisible">
          <span className="gift__eye">{g.eyebrow}</span>
          <h2 className="gift__title">{g.title}</h2>
          <div className="gift__emotional">
            <h3>{mlc.title}</h3>
            <p>{mlc.body}</p>
          </div>
          <p className="gift__note">{AP.t("wizard.invisibleNote")}</p>
        </div>
        <div>
          <button className="btn btn--primary btn--lg" onClick={onNext}>
            {g.cta}
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
          </button>
        </div>
      </StepShell>
    );
  }
  return null;
}

/* ===================== Level Bar (5 levels visual) ===================== */
function LevelBar({ currentId, recommendedId, compact }) {
  return (
    <div className={"levelbar" + (compact ? " levelbar--compact" : "")}>
      <div className="levelbar__steps">
        {AP.LEVELS.map((lv) => {
          const isCurrent = lv.id === currentId;
          const isRecommended = recommendedId != null && lv.id === recommendedId && lv.id !== currentId;
          return (
            <div key={lv.id}
              className={"levelbar__step" + (isCurrent ? " is-current" : "") + (isRecommended ? " is-target" : "")}>
              <span className="levelbar__dot" />
              <span className="levelbar__label">{lv.short}</span>
            </div>
          );
        })}
      </div>
    </div>
  );
}

/* ===================== Preliminary (antes del contacto) ===================== */
function PreliminaryStep({ answers, idx, total, onNext }) {
  const calc = AP.calculateDiscoveryPreview(answers);
  const maturity = AP.getAgendaMaturityPreview(answers);
  const risk = AP.getRiskLevel(calc);

  // Gain framing (B.J. Fogg — aumentar motivation con futuro positivo)
  const moneyRecover = AP.round2((calc.annual_lost_revenue || 0) * 0.5);
  const timeRecover  = AP.round2((calc.annual_admin_hours || 0) * 0.5);
  const costRecover  = AP.round2((calc.admin_cost_annual  || 0) * 0.5);
  const totalGain = AP.round2(moneyRecover + costRecover);

  return (
    <StepShell idx={idx} total={total}>
      <span className="wizard__chip wizard__chip--green">
        <span>✓</span> {AP.t("wizard.prelimChip")}
      </span>
      <h2 className="wizard__q">{AP.t("wizard.prelimH")}</h2>

      {/* GAIN FRAME — la gran promesa, no la pérdida */}
      {totalGain > 0 && (
        <div className="prelim__gain">
          <span className="prelim__gainEye">{AP.t("wizard.prelimGainEye")}</span>
          <p className="prelim__gainQ">
            {AP.t("wizard.prelimGainQ")}
          </p>
          <div className="prelim__gainVal">+{AP.fmtUSD(totalGain)}</div>
          <p className="prelim__gainSub">
            {AP.t("wizard.prelimGainSub1")}<strong>{AP.t("wizard.prelimGainBold1")}</strong>{AP.t("wizard.prelimGainSub2")}
            {timeRecover > 0 && <>{AP.t("wizard.prelimGainFree1")}<strong>{AP.fmtHours(timeRecover)}</strong>{AP.t("wizard.prelimGainFree2")}</>}
            {AP.t("wizard.prelimGainEnd")}
          </p>
          <p className="prelim__gainNote">
            {AP.t("wizard.prelimGainNote")}
          </p>
        </div>
      )}

      <div className="prelim__cards">
        <div className="prelim__card">
          <span className="prelim__cardLab">{AP.t("wizard.cardCurrent")}</span>
          <span className="prelim__cardVal">{maturity.current.name}</span>
        </div>
        <div className="prelim__card">
          <span className="prelim__cardLab">{AP.t("wizard.cardRisk")}</span>
          <span className="prelim__cardVal" style={{ color: risk.color }}>{risk.label}</span>
        </div>
        <div className="prelim__card">
          <span className="prelim__cardLab">{AP.t("wizard.cardStake")}</span>
          <span className="prelim__cardVal">{AP.fmtUSD(calc.annual_lost_revenue)}<small>{AP.t("wizard.stakePerYear")}</small></span>
        </div>
        <div className="prelim__card">
          <span className="prelim__cardLab">{AP.t("wizard.cardTime")}</span>
          <span className="prelim__cardVal">{AP.fmtHours(calc.annual_admin_hours)}<small>{AP.t("wizard.stakePerYear")}</small></span>
        </div>
      </div>

      <p className="wizard__sub">
        {AP.t("wizard.prelimSub1")}<strong>{maturity.current.name}</strong>{AP.t("wizard.prelimSubTo")}<strong>{AP.t("wizard.prelimSubBlindada")}</strong>.
      </p>
      <div>
        <button className="btn btn--primary btn--lg" onClick={onNext}>
          {AP.t("wizard.prelimCta")}
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
        </button>
      </div>
    </StepShell>
  );
}

/* ===================== Contact ===================== */
function ContactStep({ contact, setContact, idx, total, onSubmit, submitting, submitError }) {
  const set = (k) => (e) => setContact({ ...contact, [k]: e.target.value });
  const setRaw = (k, v) => setContact({ ...contact, [k]: v });

  const country = AP.COUNTRIES.find((c) => c.iso === (contact.phone_country_iso2 || "CO")) || AP.COUNTRIES[0];
  const phone = AP.buildPhoneE164(country.dial, contact.phone_raw);
  const emailOk = AP.isValidEmail(contact.email);

  const valid =
    (contact.name || "").trim().length >= 2 &&
    phone.is_valid &&
    !!contact.consent &&
    emailOk;

  return (
    <StepShell idx={idx} total={total}>
      <span className="wizard__chip">
        <span>📨</span> {AP.t("wizard.contactChip")}
      </span>
      <h2 className="wizard__q">{AP.t("wizard.contactH")}</h2>
      <p className="wizard__sub">
        {AP.t("wizard.contactSub")}
      </p>

      <div className="contact">
        <div className="contact__row">
          <label className="contact__label" htmlFor="c-name">{AP.t("wizard.fName")}</label>
          <input id="c-name" className="contact__input" value={contact.name || ""} onChange={set("name")} placeholder={AP.t("wizard.fNamePh")} autoComplete="name" />
        </div>

        <div className="contact__row">
          <label className="contact__label">{AP.t("wizard.fWhatsapp")}</label>
          <div className="contact__phone">
            <div className="contact__country">
              <span className="contact__country__flag">{country.flag}</span>
              <select value={country.iso} onChange={(e) => setRaw("phone_country_iso2", e.target.value)}>
                {AP.COUNTRIES.map((c) => (
                  <option key={c.iso} value={c.iso}>+{c.dial} {c.name}</option>
                ))}
              </select>
            </div>
            <input className="contact__input" inputMode="tel" value={contact.phone_raw || ""} onChange={set("phone_raw")} placeholder="3001234567" />
          </div>
          {contact.phone_raw && (
            <div className={"contact__hint" + (phone.is_valid ? "" : " is-error")}>
              {phone.is_valid ? `✓ ${phone.e164}` : AP.t("wizard.phoneError")}
            </div>
          )}
        </div>

        <div className="contact__row">
          <label className="contact__label" htmlFor="c-email">{AP.t("wizard.fEmail")} <span className="opt-tag">{AP.t("wizard.fEmailOpt")}</span></label>
          <input id="c-email" type="email" className="contact__input" value={contact.email || ""} onChange={set("email")} placeholder={AP.t("wizard.fEmailPh")} autoComplete="email" />
          {!emailOk && contact.email && <div className="contact__hint is-error">{AP.t("wizard.emailError")}</div>}
        </div>

        <label className="contact__consent">
          <input type="checkbox" checked={!!contact.consent} onChange={(e) => setRaw("consent", e.target.checked)} />
          <span>{AP.t("wizard.consent")}</span>
        </label>
      </div>

      {submitError && (
        <div className="contact__error">
          {submitError}
        </div>
      )}

      <div>
        <button
          className="btn btn--primary btn--lg btn--block"
          disabled={!valid || submitting}
          style={(!valid || submitting) ? { opacity: .55, cursor: "not-allowed" } : null}
          onClick={() => onSubmit({
            ...contact,
            phone_country_iso2: country.iso,
            phone_country_code: country.dial,
            whatsapp_e164: phone.e164,
            whatsapp_national: phone.national,
            whatsapp_is_valid: phone.is_valid
          })}
        >
          {submitting ? AP.t("wizard.calculating") : AP.t("wizard.prelimCta")}
        </button>
      </div>
    </StepShell>
  );
}

/* ===================== Wizard main ===================== */
function Wizard({ open, onClose, onFinish, tweaks }) {
  const [answers, setAnswers] = useState(() => {
    try { return JSON.parse(localStorage.getItem("appril_disc_answers") || "{}"); } catch { return {}; }
  });
  const [contact, setContact] = useState(() => {
    try { return JSON.parse(localStorage.getItem("appril_disc_contact") || "{}"); } catch { return { phone_country_iso2: "CO", consent: false }; }
  });
  const [stepIdx, setStepIdx] = useState(0);
  const [submitting, setSubmitting] = useState(false);
  const [submitError, setSubmitError] = useState(null);
  const startedAtRef = useRef(null);

  useEffect(() => { localStorage.setItem("appril_disc_answers", JSON.stringify(answers)); }, [answers]);
  useEffect(() => { localStorage.setItem("appril_disc_contact", JSON.stringify(contact)); }, [contact]);

  // Track discovery_started cuando se abre
  useEffect(() => {
    if (open && !startedAtRef.current) {
      startedAtRef.current = new Date().toISOString();
      AP.trackDiscoveryEvent({ event_name: "discovery_started" });
    }
  }, [open]);

  const steps = useWizardFlow(answers, tweaks.showValidators !== false);
  const total = steps.length;
  const current = steps[stepIdx];

  const scrollTop = () => {
    requestAnimationFrame(() => {
      const w = document.querySelector(".wizard");
      if (w) w.scrollTop = 0;
    });
  };

  const advance = useCallback(() => {
    setStepIdx((i) => Math.min(steps.length - 1, i + 1));
    scrollTop();
  }, [steps.length]);

  const back = useCallback(() => {
    setStepIdx((i) => Math.max(0, i - 1));
    scrollTop();
  }, []);

  const setAnswer = (id, v) => {
    setAnswers((a) => {
      const next = { ...a, [id]: v };
      // tracking question_answered (fire-and-forget)
      const q = current && current.kind === "question" ? current.q : null;
      const progress = total > 0 ? Math.min(100, Math.round(((stepIdx + 1) / total) * 100)) : 0;
      const section = current?.block;
      const sec = AP.getSection(section);
      window._answeredCount = (window._answeredCount || 0) + 1;
      AP.trackDiscoveryEvent({
        event_name: "question_answered",
        section: sec.section,
        section_index: sec.section_index,
        step_key: (q && q.step_key) || id,
        step_index: stepIdx + 1,
        question_key: id,
        answer_value: Array.isArray(v) ? v.join(",") : v,
        answer_label: answerLabel(q, v),
        time_on_step_ms: AP.getTimeOnStep(),
        progress_percent: progress
      });
      return next;
    });
  };

  // teclado
  useEffect(() => {
    if (!open) return;
    const onKey = (e) => {
      if (e.key === "Escape") onClose();
      if (e.key === "Enter" && current && current.kind === "intro") advance();
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [open, current, advance, onClose]);

  // botón Continuar habilitación
  const isAnswered = useMemo(() => {
    if (!current) return false;
    if (current.kind !== "question") return true;
    const v = answers[current.q.id];
    if (current.q.kind === "number") return v != null && String(v).trim() !== "";
    if (current.q.multi) return Array.isArray(v) && v.length > 0;
    return v != null;
  }, [current, answers]);

  // tracking por paso: question_viewed / contact_form_viewed / section_completed
  // + actualización de variables de estado para discovery_abandoned
  const prevStepRef = useRef(-1);
  const prevBlockRef = useRef(null);
  useEffect(() => {
    const s = steps[stepIdx];
    if (!s) return;
    const progress = total > 0 ? Math.min(100, Math.round(((stepIdx + 1) / total) * 100)) : 0;
    const section = s.block;
    const section_index = AP.getSection(section).section_index;
    const step_key = stepKeyOf(s);
    const step_index = stepIdx + 1;
    const movingForward = stepIdx > prevStepRef.current;

    AP.onStepEnter();

    // mantener estado de abandono al día para TODO tipo de paso
    window._lastStepKey  = step_key;
    window._lastSection  = section;
    window._maxStepIndex = Math.max(window._maxStepIndex || 0, step_index);
    window._maxProgress  = Math.max(window._maxProgress || 0, progress);

    // section_completed al avanzar fuera de una sección real
    if (movingForward && prevBlockRef.current && prevBlockRef.current !== section && prevBlockRef.current !== "resultado") {
      const pb = prevBlockRef.current;
      AP.trackDiscoveryEvent({
        event_name: "section_completed",
        section: pb,
        section_index: AP.getSection(pb).section_index,
        progress_percent: progress
      });
    }

    if (s.kind === "question") {
      AP.trackDiscoveryEvent({
        event_name: "question_viewed",
        section, section_index, step_key, step_index,
        question_key: s.q.id,
        progress_percent: progress
      });
    } else if (s.kind === "contact") {
      const calc = AP.calculateDiscoveryPreview ? AP.calculateDiscoveryPreview(answers) : {};
      const score = AP.calcLeadScorePreview ? AP.calcLeadScorePreview(answers) : null;
      const maturity = AP.getAgendaMaturityPreview ? AP.getAgendaMaturityPreview(answers) : {};
      AP.trackDiscoveryEvent({
        event_name: "contact_form_viewed",
        section, section_index, step_key, step_index,
        progress_percent: progress,
        lead_score_preview: score,
        agenda_maturity_preview: maturity.agenda_maturity_level || null,
        annual_lost_revenue_preview: calc.annual_lost_revenue != null ? Math.round(calc.annual_lost_revenue) : null
      });
    }

    prevStepRef.current = stepIdx;
    prevBlockRef.current = section;
  }, [stepIdx, steps, total]);

  // hallazgos intermedios (gift_viewed)
  useEffect(() => {
    if (current?.kind === "gift") {
      const map = {
        gift_perdida:  { gift_key: "perdida",  gift_title: "Pérdida anual estimada" },
        gift_tiempo:   { gift_key: "tiempo",   gift_title: "Tiempo administrativo" },
        gift_invisible:{ gift_key: "invisible",gift_title: "Carga invisible" }
      };
      const meta = map[current.giftId] || { gift_key: current.giftId };
      AP.trackDiscoveryEvent({ event_name: "gift_viewed", metadata: meta });
    }
  }, [current && current.giftId]);

  const handleContactSubmit = async (payload) => {
    setSubmitError(null);
    setSubmitting(true);
    setContact(payload);
    const calc = AP.calculateDiscoveryPreview(answers);
    const built = AP.buildDiscoveryPayload({
      answers, contact: payload, calc,
      started_at: startedAtRef.current || new Date().toISOString(),
      completion_rate: 1
    });
    const finishProgress = 90;
    try {
      const data = await AP.submitDiscoveryLead(built);
      setSubmitting(false);

      // Estado de sesi\u00f3n: completada -> no contar como abandono, limpiar id persistido
      window._discoveryLeadId = data?.discovery_lead_id || null;
      window._leadId          = data?.lead_id || null;
      window._formSubmitted   = true;
      AP._abandonSent = true;
      AP.clearSession();

      if (!data || data.ok === false) {
        // TODO: en producci\u00f3n mostrar error. Por ahora pasamos igual al dashboard usando preview frontend.
        console.warn("submit_discovery_lead devolvi\u00f3 ok=false. Mostrando dashboard con c\u00e1lculos preview.");
        // contact_submitted con datos preview (sin lead_id real)
        AP.trackDiscoveryEvent({
          event_name: "contact_submitted",
          progress_percent: finishProgress,
          lead_score: built.frontend_calculations?.lead_score,
          marketing_segment: built.frontend_calculations?.lead_classification,
          lead_classification: built.frontend_calculations?.lead_classification
        });
        onFinish({ payload: built, backend: built.frontend_calculations });
        return;
      }

      // contact_submitted DESPU\u00c9S del submit (ya hay lead_id)
      AP.trackDiscoveryEvent({
        event_name: "contact_submitted",
        discovery_lead_id: data.discovery_lead_id,
        lead_id: data.lead_id,
        lead_score: data.lead_score,
        marketing_segment: data.marketing_segment,
        lead_classification: data.lead_classification,
        progress_percent: finishProgress
      });

      localStorage.setItem("appril_disc_result", JSON.stringify({ ...built, backend: data }));

      AP.trackDiscoveryEvent({
        event_name: "result_viewed",
        discovery_lead_id: data.discovery_lead_id,
        lead_id: data.lead_id,
        lead_score: data.lead_score,
        marketing_segment: data.marketing_segment,
        lead_classification: data.lead_classification,
        recommended_action: data.recommended_action,
        progress_percent: 100
      });
      onFinish({ payload: built, backend: data });
    } catch (e) {
      setSubmitting(false);
      // El usuario s\u00ed envi\u00f3 el contacto: no debe contar como abandono
      window._formSubmitted = true;
      AP._abandonSent = true;
      // TODO: en producci\u00f3n bloquear con setSubmitError. Por ahora dejamos pasar al dashboard para revisi\u00f3n visual.
      console.warn("submit_discovery_lead fall\u00f3:", e, "\u2014 mostrando dashboard con c\u00e1lculos preview.");
      onFinish({ payload: built, backend: built.frontend_calculations });
    }
  };

  const sectionsTotal = AP.BLOCKS.length;
  const blockKey = current?.block || (steps[Math.max(0, stepIdx - 1)]?.block) || "agenda";
  const sectionIdx = Math.max(1, AP.BLOCKS.findIndex((b) => b.key === blockKey) + 1);
  const sectionLabel = blockLabel(blockKey);
  const pct = total > 0 ? Math.min(100, Math.round(((stepIdx + 1) / total) * 100)) : 0;

  // chip rojo solo en la PRIMERA pregunta de cada sección
  const isFirstQuestionInBlock = (() => {
    if (!current || current.kind !== "question") return false;
    for (let i = stepIdx - 1; i >= 0; i--) {
      const s = steps[i];
      if (!s) continue;
      if (s.block !== current.block) return true;
      if (s.kind === "question") return false;
    }
    return true;
  })();

  return (
    <div className={"wizard" + (open ? " is-open" : "")}>
      <WizardTopBar
        onClose={onClose}
        sectionLabel={sectionLabel}
        sectionIdx={sectionIdx}
        sectionsTotal={sectionsTotal}
        pct={pct}
      />
      <div className="wizard__body">
        <div className="wizard__stage">
          {current && current.kind === "intro" && (
            <IntroStep q={current.q} idx={stepIdx + 1} total={total} onNext={advance} />
          )}
          {current && current.kind === "question" && current.q.kind === "choice" && (
            <ChoiceStep key={current.q.id} q={current.q} value={answers[current.q.id]}
              onChange={(v) => setAnswer(current.q.id, v)} onNext={advance}
              idx={stepIdx + 1} total={total} showChip={isFirstQuestionInBlock} />
          )}
          {current && current.kind === "question" && current.q.kind === "number" && (
            <NumberStep key={current.q.id} q={current.q} value={answers[current.q.id]}
              onChange={(v) => setAnswer(current.q.id, v)} idx={stepIdx + 1} total={total}
              showChip={isFirstQuestionInBlock} />
          )}
          {current && current.kind === "validator" && (
            <ValidatorStep key={current.validatorId} validatorId={current.validatorId}
              idx={stepIdx + 1} total={total} onNext={advance} />
          )}
          {current && current.kind === "gift" && (
            <GiftStep key={current.giftId} giftId={current.giftId} answers={answers}
              idx={stepIdx + 1} total={total} onNext={advance} />
          )}
          {current && current.kind === "preliminary" && (
            <PreliminaryStep answers={answers} idx={stepIdx + 1} total={total} onNext={advance} />
          )}
          {current && current.kind === "contact" && (
            <ContactStep contact={contact} setContact={setContact}
              idx={stepIdx + 1} total={total} onSubmit={handleContactSubmit}
              submitting={submitting} submitError={submitError} />
          )}
        </div>

        <div className="wizard__nav">
          <button className="wizard__back" onClick={back} disabled={stepIdx === 0}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M19 12H5M11 6l-6 6 6 6"/></svg>
            {AP.t("common.back")}
          </button>
          {current && current.kind === "question" && (
            <button className="btn btn--primary" onClick={advance}
              disabled={!isAnswered}
              style={!isAnswered ? { opacity: .4, cursor: "not-allowed" } : null}>
              {AP.t("common.continue")}
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
            </button>
          )}
        </div>
      </div>
    </div>
  );
}

window.Wizard = Wizard;
window.LevelBar = LevelBar;
