// rd-app.jsx — prototype shell: full-app state machine + device frame + Tweaks.

const RD_TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "startAt": "Home",
  "scanOutcome": "Scans fine",
  "payOutcome": "Success",
  "grain": true
}/*EDITMODE-END*/;

function rdBuildSendData(cents, to) {
  const gbp = cents / 100 / RD_RATE_GBPBRL;
  const c = to || { name: 'Maria Souza', sub: 'PIX key · Nubank', initials: 'MS', pixKey: 'maria.souza@nubank.br' };
  return {
    vendor: c.name, vendorSub: c.sub, vendorInitials: c.initials,
    keyEntry: c.pixKey || 'maria.souza@nubank.br',
    amountLocal: fmtBRL(cents), amountGbp: fmtGBPNum(gbp),
    rateLine: '£1 = R$7.05',
    fee: '£0.00',
    balanceAfter: fmtGBPNum(Math.max(0, 142.5 - gbp)),
    payVerb: 'Pay ' + fmtBRL(cents),
    trustPaid: 'Pago',
  };
}

function RdApp() {
  const [t, setTweak] = useTweaks(RD_TWEAK_DEFAULTS);
  const [screen, setScreen] = React.useState(RD_TWEAK_DEFAULTS.startAt === 'First run' ? 'splash' : 'home');
  const [confirmData, setConfirmData] = React.useState(null); // null = scanned kiosk
  const [fresh, setFresh] = React.useState(false); // recovered (rescan / top-up)
  const loadFrom = React.useRef(null);
  const payTimer = React.useRef(null);

  // PIX rail approval — pending after first-run verification, approves with a toast
  const [pixApproved, setPixApproved] = React.useState(true);
  const [pixToast, setPixToast] = React.useState(false);
  const pixTimer = React.useRef(null);
  const toastTimer = React.useRef(null);
  React.useEffect(() => {
    if (screen === 'home' && !pixApproved) {
      pixTimer.current = setTimeout(() => {
        setPixApproved(true); setPixToast(true);
        toastTimer.current = setTimeout(() => setPixToast(false), 4200);
      }, 4500);
    }
    return () => clearTimeout(pixTimer.current);
  }, [screen, pixApproved]);
  React.useEffect(() => () => clearTimeout(toastTimer.current), []);

  const scanOutcome = t.scanOutcome === "Won't scan" ? 'badqr' : 'ok';
  const expired = t.payOutcome === 'Expired key' && !fresh;
  const short = t.payOutcome === 'Insufficient balance' && !fresh;
  const confirmState = expired ? 'expired' : short ? 'short' : 'ok';

  const startPay = (forceOk) => {
    setScreen('paying');
    clearTimeout(payTimer.current);
    payTimer.current = setTimeout(() => {
      setScreen(!forceOk && t.payOutcome === 'Connection lost' ? 'offline' : 'success');
    }, 1500);
  };
  React.useEffect(() => () => clearTimeout(payTimer.current), []);

  const goHome = () => { setScreen('home'); setFresh(false); setConfirmData(null); };

  const dark = ['scan', 'confirm', 'paying', 'success'].includes(screen);

  const screens = {
    splash: <RdSplash onNext={() => setScreen('welcome')} />,
    welcome: <RdWelcome grain={t.grain} onStart={() => setScreen('intro')} onSignIn={goHome} />,
    intro: <RdIntro grain={t.grain} onDone={() => setScreen('kyc')} onBack={() => setScreen('welcome')} />,
    kyc: <RdKyc grain={t.grain} onDone={(dest) => { setPixApproved(false); setPixToast(false); setScreen(dest); }} onBack={() => setScreen('intro')} />,
    home: <RdHome grain={t.grain} pixApproved={pixApproved} toast={pixToast} onScan={() => setScreen('scan')}
      onLoad={() => setScreen('load')} onReceive={() => setScreen('receive')}
      onSend={() => setScreen('send')}
      onProfile={() => setScreen('profile')} onHistory={() => setScreen('history')} />,
    scan: <RdScanner outcome={scanOutcome} onClose={goHome}
      onLocked={() => { setConfirmData(null); setScreen('confirm'); }}
      onTypeKey={() => setScreen('send')} />,
    send: <RdSend grain={t.grain} onBack={goHome}
      onReview={(cents, to) => { setConfirmData(rdBuildSendData(cents, to)); setScreen('confirm'); }} />,
    confirm: <RdConfirm market="br" grain={t.grain} data={confirmData} state={confirmState}
      onPay={() => startPay(false)} onCancel={goHome}
      onRescan={() => { setFresh(true); setScreen('scan'); }}
      onLoad={() => { loadFrom.current = 'confirm'; setScreen('load'); }} />,
    paying: <RdPaying market="br" />,
    success: <RdSuccess market="br" data={confirmData} onDone={goHome} />,
    offline: <RdOffline market="br" grain={t.grain} onRetry={() => startPay(true)} onCancel={goHome} />,
    load: <RdLoad grain={t.grain} onBack={goHome} onDone={() => {
      if (loadFrom.current === 'confirm') { loadFrom.current = null; setFresh(true); setScreen('confirm'); }
      else goHome();
    }} />,
    receive: <RdReceive grain={t.grain} onBack={goHome} />,
    history: <RdHistory grain={t.grain} onBack={goHome} />,
    profile: <RdProfile grain={t.grain} pixApproved={pixApproved} onBack={goHome} onSignOut={() => setScreen('splash')} />,
  };

  // fit device to viewport
  const [scale, setScale] = React.useState(1);
  React.useEffect(() => {
    const fit = () => setScale(Math.min(1, (window.innerHeight - 36) / 874, (window.innerWidth - 24) / 402));
    fit(); window.addEventListener('resize', fit);
    return () => window.removeEventListener('resize', fit);
  }, []);

  return (
    <div style={{ transform: `scale(${scale})`, transformOrigin: 'center center' }}>
      <IOSDevice width={402} height={874} dark={dark}>
        <div key={screen} style={{ height: '100%', animation: 'rd-fade 150ms ease both' }}>
          {screens[screen]}
        </div>
      </IOSDevice>

      <TweaksPanel>
        <TweakSection label="Flow" />
        <TweakRadio label="Start at" value={t.startAt}
          options={['Home', 'First run']}
          onChange={(v) => { setTweak('startAt', v); setConfirmData(null); setScreen(v === 'First run' ? 'splash' : 'home'); }} />
        <TweakButton label="Replay PIX approval" onClick={() => { clearTimeout(toastTimer.current); setPixToast(false); setPixApproved(false); setConfirmData(null); setScreen('home'); }} />
        <TweakSection label="Simulate failures" />
        <TweakRadio label="QR scan" value={t.scanOutcome}
          options={['Scans fine', "Won't scan"]}
          onChange={(v) => { setTweak('scanOutcome', v); setConfirmData(null); setScreen('scan'); }} />
        <TweakSelect label="Payment outcome" value={t.payOutcome}
          options={['Success', 'Connection lost', 'Expired key', 'Insufficient balance']}
          onChange={(v) => { setTweak('payOutcome', v); setFresh(false); goHome(); }} />
        <TweakSection label="Surface" />
        <TweakToggle label="Paper grain" value={t.grain} onChange={(v) => setTweak('grain', v)} />
      </TweaksPanel>
    </div>
  );
}

window.RdApp = RdApp;
