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

const EMPTY = {
  // Paso 0 — código actual + responsable
  c_codigoActual: '',
  r_firstName: '', r_lastName: '',
  r_idType: 'fisica', r_idNumber: '',
  r_phoneCode: '+506', r_phone: '',
  // Paso 1 — datos del nuevo código
  n_idType: 'juridica', n_idNumber: '', n_name: '',
  n_email: '',
  n_provincia: '', n_canton: '', n_distrito: '',
  // Paso 2 — documentación
  f_cedula: null, f_evidencia: null,
  privacy: false,
};

const PERSON_ID = ['fisica', 'dimex', 'pasaporte'];
const BIZ_ID    = ['juridica', 'fisica', 'dimex', 'nite'];
const ID_TYPES  = { fisica: 'Cédula física', dimex: 'DIMEX', pasaporte: 'Pasaporte', juridica: 'Cédula jurídica', nite: '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 vCodigo(v) {
  const s = (v || '').trim().toUpperCase();
  if (!s) return 'Ingresá el código actual del cliente.';
  if (s.length < 3) return 'El código debe tener al menos 3 caracteres.';
  return '';
}

function validate(step, d) {
  const e = {};
  if (step === 0) {
    e.c_codigoActual = vCodigo(d.c_codigoActual);
    e.r_firstName    = vName(d.r_firstName, 'el nombre');
    e.r_lastName     = vName(d.r_lastName, 'los apellidos');
    e.r_idNumber     = vId(d.r_idType, d.r_idNumber);
    e.r_phone        = vPhone(d.r_phoneCode, d.r_phone);
  }
  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 o razón social del nuevo código.' : '';
    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.';
  }
  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.';
  }
  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 CambioApp() {
  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();

  // Auto-guardar borrador
  useEffect(() => {
    if (done) return;
    const t = setTimeout(() => {
      const lite = { ...d, f_cedula: d.f_cedula && { ...d.f_cedula, thumb: null }, f_evidencia: d.f_evidencia && { ...d.f_evidencia, thumb: null } };
      if (ST.set(DRAFT_KEY, JSON.stringify({ data: d, step }))) setSavedAt(new Date());
      else 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]);
  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),
        phoneCode: d.r_phoneCode,
        phone: d.r_phone,
        email: '',
      },
      negocio: {
        idType: d.n_idType,
        idNumber: clean(d.n_idNumber).replace(/[\s-]/g, ''),
        name: clean(d.n_name),
        phoneCode: '+506',
        phone: '',
        email: clean(d.n_email).toLowerCase(),
        provincia: d.n_provincia,
        canton: d.n_canton,
        distrito: d.n_distrito,
        direccion: 'Cambio de código. Código anterior: ' + clean(d.c_codigoActual).toUpperCase(),
      },
      docs: [['cedula', d.f_cedula], ['evidencia', d.f_evidencia]].filter(x => x[1]).map(([slot, f]) => ({ slot, ...f })),
      tipo: 'cambio',
      codigoActual: clean(d.c_codigoActual).toUpperCase(),
    }, token.current);
    setSending(false);
    if (!res.ok) {
      setSubmitErr(
        res.code === 'duplicate'
          ? 'Ya existe una solicitud en trámite para esta identificación. Si necesitás asistencia, escribinos con 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.n_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: 'Código actual y responsable',  s: 'Indicá tu código de cliente actual e identificación.' },
    { t: 'Datos del nuevo código',       s: 'Información para actualizar 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>Cambio o actualización de código</h1>
              <p>Completá la siguiente información para actualizar los datos de 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 && <StepCodigo d={d} set={set} blur={blur} err={err} ok={ok} />}
                    {step === 1 && <StepNuevoCodigo d={d} set={set} blur={blur} err={err} ok={ok} cantones={cantones} distritos={distritos} />}
                    {step === 2 && <StepDocs 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>
  );
}

// ---------- Segmented control de tipo de ID ----------
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>
  );
}

// ---------- Paso 0: Código actual + responsable ----------
function StepCodigo({ d, set, blur, err, ok }) {
  return (
    <div className="gf-grid">
      {/* Código actual */}
      <Field id="c_codigoActual" label="Código de cliente actual" required span
        error={err('c_codigoActual')} valid={ok('c_codigoActual')}
        hint="Encontrás tu código actual en facturas o correos anteriores de Guaca Repuestos.">
        <input id="c_codigoActual" className="input" autoComplete="off"
          placeholder="Ej.: GR-0001 o C0123"
          style={{ textTransform: 'uppercase' }}
          value={d.c_codigoActual}
          onChange={e => set('c_codigoActual', e.target.value.toUpperCase())}
          onBlur={blur('c_codigoActual')} />
      </Field>

      <div className="gf-sub" style={{ gridColumn: '1/-1', marginTop: 4 }}>Datos del responsable</div>

      {/* Nombre */}
      <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>

      {/* Tipo de ID del responsable */}
      <Field id="r_idType" label="Tipo de identificación del responsable" 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>

      {/* Teléfono */}
      <div className="gf-sub" style={{ gridColumn: '1/-1', marginTop: 4 }}>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>
    </div>
  );
}

// ---------- Paso 1: Datos del nuevo código ----------
function StepNuevoCodigo({ d, set, blur, err, ok, cantones, distritos }) {
  return (
    <div className="gf-grid">
      {/* Tipo de identificación del negocio */}
      <Field id="n_idType" label="Tipo de identificación del nuevo código" required span>
        <IdTypeSeg label="Tipo de identificación del nuevo código" 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>

      {/* Nombre / Razón social */}
      <Field id="n_name" label="Nombre o razón social" required span
        error={err('n_name')} valid={ok('n_name')}
        hint="Nombre que quedará asociado al código actualizado.">
        <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>

      {/* Correo de facturación */}
      <div className="gf-sub" style={{ gridColumn: '1/-1', marginTop: 4 }}>Contacto y facturación</div>
      <Field id="n_email" label="Correo electrónico de facturación" required span
        error={err('n_email')} valid={ok('n_email')}
        hint="Aquí se enviarán las facturas electrónicas del nuevo código.">
        <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>

      {/* Ubicación */}
      <div className="gf-sub" style={{ gridColumn: '1/-1', marginTop: 4 }}>Ubicación del negocio</div>
      <div className="gf-geo" style={{ gridColumn: '1/-1' }}>
        <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>
    </div>
  );
}

// ---------- Paso 2: Documentación ----------
function StepDocs({ d, set, err }) {
  const count = [d.f_cedula, d.f_evidencia].filter(Boolean).length;
  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.&nbsp;
          <b>{count} de 2</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')} />
    </div>
  );
}

// ---------- Paso 3: Revisión ----------
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],
  ];
  return (
    <div className="gf-review">
      {/* Sección: Código actual */}
      <div className="gf-rv">
        <div className="gf-rv-h">
          <h3>Código actual y 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="Código actual"   v={d.c_codigoActual} />
          <Row k="Nombre completo" v={`${d.r_firstName} ${d.r_lastName}`} />
          <Row k={ID_TYPES[d.r_idType]} v={d.r_idNumber} />
          <Row k="Teléfono" v={GFmt.phone(d.r_phoneCode, d.r_phone)} />
        </dl>
      </div>

      {/* Sección: Nuevo código */}
      <div className="gf-rv">
        <div className="gf-rv-h">
          <h3>Datos del nuevo código</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="Correo de facturación"    v={d.n_email} full />
          <Row k="Ubicación" v={d.n_provincia && d.n_canton && d.n_distrito ? `${d.n_provincia}, ${d.n_canton}, ${d.n_distrito}` : ''} full />
        </dl>
      </div>

      {/* Sección: Documentos */}
      <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>
          ))}
          {files.every(f => !f[1]) && (
            <p style={{ color: 'var(--gray-500)', fontSize: 13 }}>No se han adjuntado documentos aún.</p>
          )}
        </div>
      </div>

      {/* Aceptar política */}
      <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>
  );
}

// ---------- Éxito ----------
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 de cambio 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>
      {done.email && (
        <p style={{ marginTop: 14, fontSize: 13.5, color: 'var(--gray-600)' }}>
          Guardá este número para dar seguimiento. También recibirás confirmación en <b>{done.email}</b>.
        </p>
      )}
      <ol className="gf-next">
        <li><span className="n">1</span><span><b>Revisión de datos</b>Nuestro equipo verificará la información ingresada, normalmente en 1 a 3 días hábiles.</span></li>
        <li><span className="n">2</span><span><b>Validación de documentos</b>Se verificarán la cédula y la referencia visual del negocio adjuntadas.</span></li>
        <li><span className="n">3</span><span><b>Confirmación del cambio</b>Te contactaremos por teléfono o correo para confirmar la actualización de tu código.</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>
        <a href="/" className="btn btn-text"><Icon name="arrowLeft" size={16} /> Volver al inicio</a>
      </div>
    </div>
  );
}

// ---------- Modal legal ----------
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 cambio o actualización 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(<CambioApp />);
