// Formulario público — Solicitud de código Guaca Repuestos
const { useState, useEffect, useMemo, useRef } = React;
const DRAFT_KEY = 'guaca_form_draft_v1';

const EMPTY = {
  r_idType: 'fisica', r_idNumber: '', r_firstName: '', r_lastName: '', r_birthDate: '', r_phoneCode: '+506', r_phone: '', r_email: '',
  n_idType: 'juridica', n_idNumber: '', n_name: '', n_phoneCode: '+506', n_phone: '', n_email: '',
  n_provincia: '', n_canton: '', n_distrito: '', n_direccion: '',
  f_cedula: null, f_evidencia: null, f_personeria: null,
  privacy: false,
};

const PERSON_ID = ['fisica', 'dimex', 'pasaporte'];
const BIZ_ID = ['juridica', 'fisica', 'dimex', 'nite'];
const ID_HINT = {
  fisica: '9 dígitos, sin guiones. Ej.: 112340567',
  dimex: '11 o 12 dígitos',
  pasaporte: 'Entre 6 y 20 caracteres alfanuméricos',
  juridica: '10 dígitos, inicia con 3. Ej.: 3101123456',
  nite: '10 dígitos',
};
const ID_PH = { fisica: '1 1234 0567', dimex: '155812345678', pasaporte: 'A1234567', juridica: '3 101 123456', nite: '1234567890' };

// ---------- Validación ----------
const emailRe = /^[^\s@]+@[^\s@]+\.[a-z]{2,}$/i;
function vId(type, v) {
  const s = String(v || '').replace(/[\s-]/g, '');
  if (!s) return 'Ingresá el número de identificación.';
  if (type === 'fisica' && !/^[1-9]\d{8}$/.test(s)) return 'La cédula física debe tener 9 dígitos y no iniciar con 0.';
  if (type === 'dimex' && !/^\d{11,12}$/.test(s)) return 'El DIMEX debe tener 11 o 12 dígitos.';
  if (type === 'pasaporte' && !/^[a-z0-9]{6,20}$/i.test(s)) return 'El pasaporte debe tener entre 6 y 20 letras o números.';
  if (type === 'juridica' && !/^3\d{9}$/.test(s)) return 'La cédula jurídica debe tener 10 dígitos e iniciar con 3.';
  if (type === 'nite' && !/^\d{10}$/.test(s)) return 'El NITE debe tener 10 dígitos.';
  return '';
}
function vPhone(code, v) {
  if (!v) return 'Ingresá un número de teléfono.';
  if (code === '+506') { if (!/^[245678]\d{7}$/.test(v)) return 'En Costa Rica el número tiene 8 dígitos (ej.: 8888 8888).'; }
  else if (!/^\d{6,14}$/.test(v)) return 'El número debe tener entre 6 y 14 dígitos.';
  return '';
}
function vEmail(v) { if (!v) return 'Ingresá un correo electrónico.'; if (!emailRe.test(v.trim())) return 'Revisá el formato del correo (ej.: nombre@dominio.com).'; return ''; }
function vName(v, what) { const s = (v || '').trim(); if (!s) return `Ingresá ${what}.`; if (s.length < 2) return 'Debe tener al menos 2 letras.'; if (/[0-9]/.test(s)) return 'No debe contener números.'; return ''; }
function vBirth(v) {
  if (!v) return 'Ingresá tu fecha de nacimiento.';
  const d = new Date(v + 'T12:00:00'); if (isNaN(d)) return 'La fecha no es válida.';
  const now = new Date(); let age = now.getFullYear() - d.getFullYear(); const m = now.getMonth() - d.getMonth(); if (m < 0 || (m === 0 && now.getDate() < d.getDate())) age--;
  if (d > now) return 'La fecha no puede ser futura.';
  if (age < 18) return 'El responsable debe ser mayor de edad (18 años o más).';
  if (age > 100) return 'Revisá el año de nacimiento.';
  return '';
}

const needsPersoneria = (d) => d.n_idType === 'juridica';

function validate(step, d) {
  const e = {};
  if (step === 0) {
    e.r_idNumber = vId(d.r_idType, d.r_idNumber);
    e.r_firstName = vName(d.r_firstName, 'tu nombre');
    e.r_lastName = vName(d.r_lastName, 'tus apellidos');
    e.r_birthDate = vBirth(d.r_birthDate);
    e.r_phone = vPhone(d.r_phoneCode, d.r_phone);
    e.r_email = vEmail(d.r_email);
  }
  if (step === 1) {
    e.n_idNumber = vId(d.n_idType, d.n_idNumber);
    e.n_name = (d.n_name || '').trim().length < 3 ? 'Ingresá el nombre comercial o la razón social.' : '';
    e.n_phone = vPhone(d.n_phoneCode, d.n_phone);
    e.n_email = vEmail(d.n_email);
    e.n_provincia = d.n_provincia ? '' : 'Seleccioná la provincia.';
    e.n_canton = d.n_canton ? '' : d.n_provincia ? 'Seleccioná el cantón.' : 'Primero seleccioná la provincia.';
    e.n_distrito = d.n_distrito ? '' : d.n_canton ? 'Seleccioná el distrito.' : 'Primero seleccioná el cantón.';
    const a = (d.n_direccion || '').trim();
    e.n_direccion = !a ? 'Indicá la dirección exacta del negocio.' : a.length < 15 ? 'Agregá más detalle: señas, referencias o número de local (mínimo 15 caracteres).' : '';
  }
  if (step === 2) {
    e.f_cedula = d.f_cedula ? '' : 'Adjuntá la cédula del representante legal.';
    e.f_evidencia = d.f_evidencia ? '' : 'Adjuntá una fotografía o referencia visual del negocio.';
    e.f_personeria = needsPersoneria(d) && !d.f_personeria ? 'Para negocios con cédula jurídica, la personería es obligatoria.' : '';
  }
  if (step === 3) {
    e.privacy = d.privacy ? '' : 'Debés aceptar la política de privacidad para enviar la solicitud.';
  }
  Object.keys(e).forEach(k => { if (!e[k]) delete e[k]; });
  return e;
}

// ---------- App ----------
function FormApp() {
  const ST = GuacaStore.storage();
  const [d, setD] = useState(() => { try { return { ...EMPTY, ...JSON.parse(ST.get(DRAFT_KEY)).data }; } catch (e) { return EMPTY; } });
  const [step, setStep] = useState(() => { try { return JSON.parse(ST.get(DRAFT_KEY)).step || 0; } catch (e) { return 0; } });
  const [touched, setTouched] = useState({});
  const [tried, setTried] = useState({});
  const [sending, setSending] = useState(false);
  const [submitErr, setSubmitErr] = useState('');
  const [done, setDone] = useState(null);
  const [legal, setLegal] = useState(false);
  const [savedAt, setSavedAt] = useState(null);
  const token = useRef(null);
  const top = useRef();

  useEffect(() => {
    if (done) return;
    const t = setTimeout(() => {
      if (ST.set(DRAFT_KEY, JSON.stringify({ data: d, step }))) setSavedAt(new Date());
      else { const lite = { ...d, f_cedula: d.f_cedula && { ...d.f_cedula, thumb: null }, f_evidencia: d.f_evidencia && { ...d.f_evidencia, thumb: null }, f_personeria: d.f_personeria && { ...d.f_personeria, thumb: null } }; if (ST.set(DRAFT_KEY, JSON.stringify({ data: lite, step }))) setSavedAt(new Date()); }
    }, 350);
    return () => clearTimeout(t);
  }, [d, step, done]);

  const set = (k, v) => { setD(p => ({ ...p, [k]: v })); setSubmitErr(''); };
  const blur = k => () => setTouched(p => ({ ...p, [k]: true }));
  const allErr = useMemo(() => validate(step, d), [step, d]);
  // Error visible: cuando el campo fue tocado o cuando se intentó avanzar
  const err = k => (touched[k] || tried[step]) ? allErr[k] : '';
  const ok = k => touched[k] && !allErr[k] && d[k];

  function scrollTop() { const y = top.current.getBoundingClientRect().top + window.scrollY - 12; window.scrollTo({ top: Math.max(0, y), behavior: 'smooth' }); }

  function next() {
    const e = validate(step, d);
    if (Object.keys(e).length) {
      setTried(p => ({ ...p, [step]: true }));
      setTimeout(() => { const el = document.querySelector('.is-invalid input, .is-invalid select, .is-invalid textarea, .is-invalid button'); if (el) { el.focus({ preventScroll: true }); const y = el.getBoundingClientRect().top + window.scrollY - 120; window.scrollTo({ top: y, behavior: 'smooth' }); } }, 30);
      return;
    }
    setStep(step + 1); scrollTop();
  }
  function back() { setStep(Math.max(0, step - 1)); scrollTop(); }
  function goto(s) { if (s < step) { setStep(s); scrollTop(); } }

  async function submit() {
    if (sending) return;
    const e = validate(3, d);
    for (let s = 0; s < 3; s++) { if (Object.keys(validate(s, d)).length) { setTried(p => ({ ...p, [s]: true })); setStep(s); scrollTop(); return; } }
    if (Object.keys(e).length) { setTried(p => ({ ...p, 3: true })); return; }
    setSending(true); setSubmitErr('');
    if (!token.current) token.current = 'tk_' + Date.now().toString(36) + Math.random().toString(36).slice(2);
    await new Promise(r => setTimeout(r, 1100));
    const clean = s => String(s || '').trim();
    const res = GuacaStore.createRequest({
      responsable: { idType: d.r_idType, idNumber: clean(d.r_idNumber).replace(/[\s-]/g, ''), firstName: clean(d.r_firstName), lastName: clean(d.r_lastName), birthDate: d.r_birthDate, phoneCode: d.r_phoneCode, phone: d.r_phone, email: clean(d.r_email).toLowerCase() },
      negocio: { idType: d.n_idType, idNumber: clean(d.n_idNumber).replace(/[\s-]/g, ''), name: clean(d.n_name), phoneCode: d.n_phoneCode, phone: d.n_phone, email: clean(d.n_email).toLowerCase(), provincia: d.n_provincia, canton: d.n_canton, distrito: d.n_distrito, direccion: clean(d.n_direccion) },
      docs: [['cedula', d.f_cedula], ['evidencia', d.f_evidencia], ['personeria', d.f_personeria]].filter(x => x[1]).map(([slot, f]) => ({ slot, ...f })),
    }, token.current);
    setSending(false);
    if (!res.ok) {
      setSubmitErr(res.code === 'duplicate' ? 'Ya existe una solicitud en trámite para esta identificación de negocio. Si necesitás actualizarla, escribinos indicando tu número de solicitud.' : 'No pudimos enviar la solicitud. Revisá tu conexión e intentá de nuevo.');
      return;
    }
    try { localStorage.removeItem(DRAFT_KEY); sessionStorage.removeItem(DRAFT_KEY); } catch (e) {}
    setDone({ id: res.id, email: d.r_email.trim() });
    window.scrollTo({ top: 0 });
  }

  function restart() { setD(EMPTY); setStep(0); setTouched({}); setTried({}); setDone(null); token.current = null; setSubmitErr(''); }

  const geo = window.CR_GEO;
  const cantones = d.n_provincia ? Object.keys(geo[d.n_provincia]) : [];
  const distritos = d.n_canton ? geo[d.n_provincia][d.n_canton] : [];

  const STEPS = [
    { t: 'Información del responsable', s: 'Datos de la persona que solicita el código.' },
    { t: 'Datos del negocio', s: 'Información con la que se creará el código de cliente.' },
    { t: 'Documentación y envío', s: 'Adjuntá los documentos y revisá antes de enviar.' },
  ];
  const visStep = Math.min(step, 2);
  const isReview = step === 3;

  return (
    <div className="gf-page">
      <header className="gf-header">
        <div className="gf-header-in">
          <img src="/assets/guaca-repuestos-logo.png" alt="Guaca Repuestos" className="gf-logo" />
          <div className="gf-secure"><Icon name="lock" size={16} /><span>Conexión segura · Tus datos están protegidos</span></div>
        </div>
      </header>

      <main className="gf-main" ref={top}>
        {done ? (
          <div className="gf-card" data-screen-label="Confirmación">
            <Success done={done} onRestart={restart} />
          </div>
        ) : (
          <>
            <div className="gf-intro">
              <h1>Solicitud de código Guaca Repuestos</h1>
              <p>Completá la siguiente información para solicitar tu código de cliente.</p>
            </div>
            <div className="gf-layout">
              <aside className="gf-rail" aria-label="Progreso">
                <ol className="gf-steps">
                  {STEPS.map((s, i) => {
                    const st = i < visStep ? 'is-done' : i === visStep ? 'is-current' : '';
                    return (
                      <li key={i}>
                        <button type="button" className={'gf-step ' + st} onClick={() => goto(i)} disabled={i >= visStep && !(i === 2 && isReview)} aria-current={i === visStep ? 'step' : undefined}>
                          <span className="gf-step-n">{i < visStep ? <Icon name="check" size={17} stroke={2.6} /> : i + 1}</span>
                          <span>
                            <span className="gf-step-k">Paso {i + 1} de 3</span>
                            <span className="gf-step-t" style={{ display: 'block' }}>{s.t}</span>
                          </span>
                        </button>
                      </li>
                    );
                  })}
                </ol>
                <div className="gf-rail-note"><Icon name="info" size={18} /><span>Tu avance se guarda automáticamente en este dispositivo. Podés volver en cualquier momento sin perder lo que escribiste.</span></div>
                <div className="gf-rail-mascota">
                  <video
                    src="/assets/mascota-guaca-formulario.mp4"
                    autoPlay
                    loop
                    muted
                    playsInline
                    aria-label="Mascota Guaca Repuestos"
                  />
                </div>
              </aside>

              <section>
                <div className="gf-mprog" aria-hidden="true">
                  <div className="gf-mprog-top"><span className="gf-mprog-k">Paso {visStep + 1} de 3</span><span className="gf-mprog-t">{isReview ? 'Revisión final' : STEPS[visStep].t}</span></div>
                  <div className="gf-mprog-bar">{[0, 1, 2].map(i => <span key={i} className={i < visStep ? 'done' : i === visStep ? 'on' : ''} />)}</div>
                </div>

                <div className="gf-card" data-screen-label={isReview ? 'Paso 3 · Revisión' : `Paso ${step + 1}`}>
                  <div className="gf-card-head">
                    <span className="gf-card-k">Paso {visStep + 1} de 3{isReview ? ' · Revisión' : ''}</span>
                    <h2>{isReview ? 'Revisá tu solicitud' : STEPS[step].t}</h2>
                    <p>{isReview ? 'Confirmá que todos los datos sean correctos antes de enviar. Podés editar cualquier sección.' : STEPS[step].s}</p>
                  </div>
                  <div className="gf-card-body">
                    {step === 0 && <Step1 d={d} set={set} blur={blur} err={err} ok={ok} />}
                    {step === 1 && <Step2 d={d} set={set} blur={blur} err={err} ok={ok} cantones={cantones} distritos={distritos} />}
                    {step === 2 && <Step3 d={d} set={set} err={err} />}
                    {step === 3 && <Review d={d} set={set} err={err} goto={s => { setStep(s); scrollTop(); }} openLegal={() => setLegal(true)} submitErr={submitErr} />}
                  </div>
                  <div className="gf-actions">
                    {savedAt && <span className="gf-saved"><Icon name="check" size={14} /> Borrador guardado</span>}
                    <div className="gf-actions-r">
                      {step > 0 && <button type="button" className="btn btn-ghost btn-lg" onClick={back} disabled={sending}><Icon name="arrowLeft" size={18} /> Volver</button>}
                      {step < 2 && <button type="button" className="btn btn-primary btn-lg" onClick={next}>Continuar <Icon name="arrowRight" size={18} /></button>}
                      {step === 2 && <button type="button" className="btn btn-primary btn-lg" onClick={next}>Revisar solicitud <Icon name="arrowRight" size={18} /></button>}
                      {step === 3 && <button type="button" className="btn btn-primary btn-lg" onClick={submit} disabled={sending} aria-busy={sending}>
                        {sending ? <><span className="gf-spin" style={{ width: 18, height: 18, borderColor: 'rgba(255,255,255,.35)', borderTopColor: '#fff' }} /> Enviando…</> : <><Icon name="send" size={18} /> Enviar solicitud</>}
                      </button>}
                    </div>
                  </div>
                </div>
              </section>
            </div>
          </>
        )}
      </main>

      <footer className="gf-foot">
        <div className="gf-foot-in">
          <span>© 2026 Guaca Repuestos · La Guaca</span>
          <span style={{ display: 'flex', gap: 18 }}><a href="#" onClick={e => { e.preventDefault(); setLegal(true); }}>Política de privacidad</a><a href="/admin">Acceso colaboradores</a></span>
        </div>
      </footer>
      {legal && <LegalModal onClose={() => setLegal(false)} onAccept={() => { set('privacy', true); setLegal(false); }} />}
    </div>
  );
}

function IdTypeSeg({ options, value, onChange, label }) {
  return (
    <div className="gf-seg" role="group" aria-label={label}>
      {options.map(o => <button key={o} type="button" aria-pressed={value === o} onClick={() => onChange(o)}>{ID_TYPES[o]}</button>)}
    </div>
  );
}

function Step1({ d, set, blur, err, ok }) {
  return (
    <div className="gf-grid">
      <Field id="r_idType" label="Tipo de identificación" required span>
        <IdTypeSeg label="Tipo de identificación" options={PERSON_ID} value={d.r_idType} onChange={v => set('r_idType', v)} />
      </Field>
      <Field id="r_idNumber" label="Número de identificación" required error={err('r_idNumber')} valid={ok('r_idNumber')} hint={ID_HINT[d.r_idType]}>
        <input id="r_idNumber" className="input" inputMode={d.r_idType === 'pasaporte' ? 'text' : 'numeric'} autoComplete="off" placeholder={ID_PH[d.r_idType]}
          value={d.r_idNumber} onChange={e => set('r_idNumber', d.r_idType === 'pasaporte' ? e.target.value.toUpperCase().replace(/[^A-Z0-9]/g, '') : e.target.value.replace(/[^0-9]/g, '').slice(0, 12))} onBlur={blur('r_idNumber')} />
      </Field>
      <Field id="r_birthDate" label="Fecha de nacimiento" required error={err('r_birthDate')} hint="Debés ser mayor de edad.">
        <input id="r_birthDate" className="input" type="date" max={new Date().toISOString().slice(0, 10)} min="1920-01-01" autoComplete="bday"
          value={d.r_birthDate} onChange={e => set('r_birthDate', e.target.value)} onBlur={blur('r_birthDate')} />
      </Field>
      <div className="gf-sub">Nombre completo</div>
      <Field id="r_firstName" label="Nombre" required error={err('r_firstName')} valid={ok('r_firstName')}>
        <input id="r_firstName" className="input" autoComplete="given-name" placeholder="Ej.: María José" value={d.r_firstName} onChange={e => set('r_firstName', e.target.value)} onBlur={blur('r_firstName')} />
      </Field>
      <Field id="r_lastName" label="Apellidos" required error={err('r_lastName')} valid={ok('r_lastName')}>
        <input id="r_lastName" className="input" autoComplete="family-name" placeholder="Ej.: Rodríguez Mora" value={d.r_lastName} onChange={e => set('r_lastName', e.target.value)} onBlur={blur('r_lastName')} />
      </Field>
      <div className="gf-sub">Contacto</div>
      <Field id="r_phone" label="Número de teléfono" required error={err('r_phone')} hint="Preferiblemente con WhatsApp.">
        <PhoneInput id="r_phone" code={d.r_phoneCode} value={d.r_phone} onCode={v => set('r_phoneCode', v)} onChange={v => set('r_phone', v)} onBlur={blur('r_phone')} invalid={!!err('r_phone')} />
      </Field>
      <Field id="r_email" label="Correo electrónico" required error={err('r_email')} valid={ok('r_email')} hint="Aquí te enviaremos la confirmación.">
        <input id="r_email" className="input" type="email" inputMode="email" autoComplete="email" placeholder="ejemplo@ejemplo.com" value={d.r_email} onChange={e => set('r_email', e.target.value.replace(/\s/g, ''))} onBlur={blur('r_email')} />
      </Field>
    </div>
  );
}

function Step2({ d, set, blur, err, ok, cantones, distritos }) {
  const sameAsPerson = d.n_idType === d.r_idType && d.n_idNumber === d.r_idNumber && d.n_idNumber;
  return (
    <div className="gf-grid">
      <Field id="n_idType" label="Tipo de identificación del negocio" required span>
        <IdTypeSeg label="Tipo de identificación del negocio" options={BIZ_ID} value={d.n_idType} onChange={v => set('n_idType', v)} />
      </Field>
      <Field id="n_idNumber" label="Número de identificación" required error={err('n_idNumber')} valid={ok('n_idNumber')} hint={ID_HINT[d.n_idType]}>
        <input id="n_idNumber" className="input" inputMode="numeric" autoComplete="off" placeholder={ID_PH[d.n_idType]}
          value={d.n_idNumber} onChange={e => set('n_idNumber', e.target.value.replace(/[^0-9]/g, '').slice(0, 12))} onBlur={blur('n_idNumber')} />
      </Field>
      <Field id="n_name" label="Nombre comercial o razón social" required error={err('n_name')} valid={ok('n_name')} hint="Nombre que estará asociado al nuevo código.">
        <input id="n_name" className="input" autoComplete="organization" placeholder="Ej.: Taller El Roble S.A." value={d.n_name} onChange={e => set('n_name', e.target.value)} onBlur={blur('n_name')} />
      </Field>
      {d.n_idType === 'fisica' && !sameAsPerson && d.r_idType === 'fisica' && d.r_idNumber && (
        <div style={{ gridColumn: '1/-1', marginTop: -6 }}>
          <button type="button" className="btn btn-text btn-sm" style={{ marginLeft: -10 }} onClick={() => { set('n_idNumber', d.r_idNumber); }}>
            <Icon name="copy" size={16} /> El negocio está a mi nombre: usar mi cédula
          </button>
        </div>
      )}
      <div className="gf-sub">Contacto del negocio</div>
      <Field id="n_phone" label="Teléfono del negocio" required error={err('n_phone')}>
        <PhoneInput id="n_phone" code={d.n_phoneCode} value={d.n_phone} onCode={v => set('n_phoneCode', v)} onChange={v => set('n_phone', v)} onBlur={blur('n_phone')} invalid={!!err('n_phone')} />
      </Field>
      <Field id="n_email" label="Correo electrónico para facturación" required error={err('n_email')} valid={ok('n_email')} hint="Aquí se enviarán las facturas electrónicas.">
        <input id="n_email" className="input" type="email" inputMode="email" autoComplete="email" placeholder="facturacion@negocio.com" value={d.n_email} onChange={e => set('n_email', e.target.value.replace(/\s/g, ''))} onBlur={blur('n_email')} />
      </Field>
      {d.r_email && !d.n_email && (
        <div style={{ gridColumn: '1/-1', marginTop: -6 }}>
          <button type="button" className="btn btn-text btn-sm" style={{ marginLeft: -10 }} onClick={() => { set('n_email', d.r_email); if (!d.n_phone) { set('n_phone', d.r_phone); set('n_phoneCode', d.r_phoneCode); } }}>
            <Icon name="copy" size={16} /> Usar el mismo teléfono y correo del responsable
          </button>
        </div>
      )}
      <div className="gf-sub">Ubicación del negocio</div>
      <div className="gf-geo">
        <Field id="n_provincia" label="Provincia" required error={err('n_provincia')}>
          <select id="n_provincia" className="select" value={d.n_provincia} onBlur={blur('n_provincia')}
            onChange={e => { set('n_provincia', e.target.value); set('n_canton', ''); set('n_distrito', ''); }}>
            <option value="">Seleccioná…</option>
            {Object.keys(window.CR_GEO).map(p => <option key={p}>{p}</option>)}
          </select>
        </Field>
        <Field id="n_canton" label="Cantón" required error={err('n_canton')}>
          <select id="n_canton" className="select" value={d.n_canton} disabled={!d.n_provincia} onBlur={blur('n_canton')}
            onChange={e => { set('n_canton', e.target.value); set('n_distrito', ''); }}>
            <option value="">{d.n_provincia ? 'Seleccioná…' : 'Elegí provincia'}</option>
            {cantones.map(c => <option key={c}>{c}</option>)}
          </select>
        </Field>
        <Field id="n_distrito" label="Distrito" required error={err('n_distrito')}>
          <select id="n_distrito" className="select" value={d.n_distrito} disabled={!d.n_canton} onBlur={blur('n_distrito')}
            onChange={e => set('n_distrito', e.target.value)}>
            <option value="">{d.n_canton ? 'Seleccioná…' : 'Elegí cantón'}</option>
            {distritos.map(c => <option key={c}>{c}</option>)}
          </select>
        </Field>
        {d.n_distrito && <div className="gf-geo-path"><Icon name="pin" size={16} /> <b>{d.n_provincia}</b> › <b>{d.n_canton}</b> › <b>{d.n_distrito}</b></div>}
      </div>
      <Field id="n_direccion" label="Dirección exacta del negocio" required error={err('n_direccion')} span hint="Incluí señas y puntos de referencia que faciliten la entrega.">
        <textarea id="n_direccion" className="textarea" rows="3" placeholder="Ej.: 200 m norte de la iglesia católica, local esquinero con portón azul." value={d.n_direccion} onChange={e => set('n_direccion', e.target.value)} onBlur={blur('n_direccion')} />
      </Field>
    </div>
  );
}

function Step3({ d, set, err }) {
  const jur = needsPersoneria(d);
  const count = [d.f_cedula, d.f_evidencia, d.f_personeria].filter(Boolean).length;
  const need = jur ? 3 : 2;
  return (
    <div className="gf-files">
      <div className="gf-alert info"><Icon name="info" size={18} /><span>Formatos aceptados: <b>PDF, JPG o PNG</b>, máximo 5 MB por archivo. Desde el teléfono podés tomar la foto directamente. <b>{Math.min(count, need)} de {need}</b> documentos requeridos adjuntos.</span></div>
      <FileDrop id="f_cedula" title="Cédula del representante legal" required desc="Ambos lados, legible y vigente." value={d.f_cedula} onChange={v => set('f_cedula', v)} error={err('f_cedula')} />
      <FileDrop id="f_evidencia" title="Referencia visual del negocio" required desc="Fotografía de la fachada o del rótulo donde se identifique el negocio." value={d.f_evidencia} onChange={v => set('f_evidencia', v)} error={err('f_evidencia')} />
      <FileDrop id="f_personeria" title="Personería jurídica" required={jur} badge={jur ? 'Obligatorio para cédula jurídica' : 'Solo si corresponde'}
        desc={jur ? 'Certificación con no más de 3 meses de emitida.' : 'Si tu negocio no está inscrito como persona jurídica, podés omitirla.'}
        value={d.f_personeria} onChange={v => set('f_personeria', v)} error={err('f_personeria')} />
    </div>
  );
}

function Review({ d, set, err, goto, openLegal, submitErr }) {
  const Row = ({ k, v, full }) => <div className={full ? 'full' : ''}><dt>{k}</dt><dd>{v || '—'}</dd></div>;
  const files = [['Cédula del representante legal', d.f_cedula], ['Referencia visual del negocio', d.f_evidencia], ['Personería jurídica', d.f_personeria]];
  return (
    <div className="gf-review">
      <div className="gf-rv">
        <div className="gf-rv-h"><h3>Responsable</h3><button className="btn btn-text btn-sm" onClick={() => goto(0)}><Icon name="edit" size={16} /> Editar</button></div>
        <dl className="gf-rv-dl">
          <Row k="Nombre completo" v={`${d.r_firstName} ${d.r_lastName}`} />
          <Row k={ID_TYPES[d.r_idType]} v={GFmt.idNum(d.r_idType, d.r_idNumber)} />
          <Row k="Fecha de nacimiento" v={d.r_birthDate && new Date(d.r_birthDate + 'T12:00').toLocaleDateString('es-CR', { day: 'numeric', month: 'long', year: 'numeric' })} />
          <Row k="Teléfono" v={GFmt.phone(d.r_phoneCode, d.r_phone)} />
          <Row k="Correo electrónico" v={d.r_email} full />
        </dl>
      </div>
      <div className="gf-rv">
        <div className="gf-rv-h"><h3>Negocio</h3><button className="btn btn-text btn-sm" onClick={() => goto(1)}><Icon name="edit" size={16} /> Editar</button></div>
        <dl className="gf-rv-dl">
          <Row k="Nombre o razón social" v={d.n_name} full />
          <Row k={ID_TYPES[d.n_idType]} v={GFmt.idNum(d.n_idType, d.n_idNumber)} />
          <Row k="Teléfono del negocio" v={GFmt.phone(d.n_phoneCode, d.n_phone)} />
          <Row k="Correo de facturación" v={d.n_email} full />
          <Row k="Ubicación" v={`${d.n_provincia}, ${d.n_canton}, ${d.n_distrito}`} full />
          <Row k="Dirección exacta" v={d.n_direccion} full />
        </dl>
      </div>
      <div className="gf-rv">
        <div className="gf-rv-h"><h3>Documentos</h3><button className="btn btn-text btn-sm" onClick={() => goto(2)}><Icon name="edit" size={16} /> Editar</button></div>
        <div className="gf-rv-files">
          {files.filter(f => f[1]).map(([l, f]) => (
            <div className="gf-rv-file" key={l}>
              <span className="ic">{f.thumb ? <img src={f.thumb} alt="" /> : <Icon name="file" size={18} />}</span>
              <span style={{ minWidth: 0, flex: 1 }}><span className="lbl">{l}</span><b>{f.name}</b></span>
              <small>{GFmt.bytes(f.size)}</small>
            </div>
          ))}
        </div>
      </div>

      <label className={'gf-check' + (d.privacy ? ' on' : '') + (err('privacy') ? ' is-invalid' : '')}>
        <input type="checkbox" checked={d.privacy} onChange={e => set('privacy', e.target.checked)} />
        <span className="gf-box">{d.privacy && <Icon name="check" size={15} stroke={3} />}</span>
        <span className="gf-check-t">
          He leído y acepto la <a href="#" onClick={e => { e.preventDefault(); openLegal(); }}>política de privacidad y tratamiento de datos personales</a> de Guaca Repuestos.
          <small>Declaro que la información suministrada es verdadera. Conforme a la Ley N.° 8968 de Protección de la Persona frente al Tratamiento de sus Datos Personales.</small>
        </span>
      </label>
      {err('privacy') && <p className="gf-error" role="alert" style={{ marginTop: -8 }}><Icon name="alert" size={15} /> {err('privacy')}</p>}
      {submitErr && <div className="gf-alert err" role="alert"><Icon name="alert" size={18} /><span>{submitErr}</span></div>}
    </div>
  );
}

function Success({ done, onRestart }) {
  const [copied, setCopied] = useState(false);
  return (
    <div className="gf-success">
      <div className="gf-success-mark"><Icon name="check" size={40} stroke={3} /></div>
      <h1>¡Solicitud recibida!</h1>
      <p>Gracias por completar tu información. Tu solicitud fue enviada correctamente y será revisada por nuestro equipo.</p>
      <div className="gf-ticket">
        <div className="gf-ticket-k">Número de solicitud</div>
        <div className="gf-ticket-n tnum">{done.id}</div>
        <button className="btn btn-text btn-sm" style={{ marginTop: 6 }} onClick={() => { navigator.clipboard && navigator.clipboard.writeText(done.id); setCopied(true); setTimeout(() => setCopied(false), 1800); }}>
          <Icon name={copied ? 'check' : 'copy'} size={16} /> {copied ? 'Copiado' : 'Copiar número'}
        </button>
      </div>
      <p style={{ marginTop: 14, fontSize: 13.5, color: 'var(--gray-600)' }}>Guardá este número para dar seguimiento a tu solicitud.</p>
      <ol className="gf-next">
        <li><span className="n">1</span><span><b>Confirmación por correo</b>Recibirás un correo en {done.email} con el resumen de tu solicitud.</span></li>
        <li><span className="n">2</span><span><b>Revisión de documentos</b>Nuestro equipo verifica la información, normalmente en 1 a 3 días hábiles.</span></li>
        <li><span className="n">3</span><span><b>Código de cliente</b>Te contactaremos por teléfono o correo con tu código o si necesitamos algún dato adicional.</span></li>
      </ol>
      <div style={{ marginTop: 24, display: 'flex', gap: 12, justifyContent: 'center', flexWrap: 'wrap' }}>
        <button className="btn btn-ghost" onClick={() => window.print()}><Icon name="print" size={18} /> Imprimir comprobante</button>
        <button className="btn btn-text" onClick={onRestart}>Enviar otra solicitud</button>
      </div>
    </div>
  );
}

function LegalModal({ onClose, onAccept }) {
  useEffect(() => { const k = e => e.key === 'Escape' && onClose(); window.addEventListener('keydown', k); return () => window.removeEventListener('keydown', k); }, []);
  return (
    <div className="gf-modal-bg" onClick={onClose}>
      <div className="gf-modal" role="dialog" aria-modal="true" aria-labelledby="legal-t" onClick={e => e.stopPropagation()}>
        <div className="gf-modal-h"><h3 id="legal-t">Política de privacidad y tratamiento de datos</h3><button className="gf-x" onClick={onClose} aria-label="Cerrar"><Icon name="x" size={18} /></button></div>
        <div className="gf-modal-b">
          <div className="gf-legal-ph mono">Espacio reservado para el texto legal aprobado por el departamento legal de La Guaca. Reemplazar este contenido o enlazar al documento oficial.</div>
          <h4>Responsable del tratamiento</h4>
          <p>Guaca Repuestos, como parte de La Guaca, es responsable de la base de datos donde se almacenará la información suministrada en este formulario.</p>
          <h4>Finalidad</h4>
          <p>Los datos se utilizarán exclusivamente para evaluar y gestionar la solicitud de código de cliente, la facturación electrónica y la comunicación comercial relacionada.</p>
          <h4>Derechos del titular</h4>
          <p>Podés ejercer tus derechos de acceso, rectificación y supresión de acuerdo con la Ley N.° 8968 y su reglamento.</p>
        </div>
        <div className="gf-modal-f"><button className="btn btn-primary" onClick={onAccept}>Entendido, acepto</button></div>
      </div>
    </div>
  );
}

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