// rd-shared.jsx — market data, brand atoms, shared components

const RD = {
  paper: 'var(--paper)', paperHi: 'var(--paper-hi)', dark: 'var(--dark)',
  ink: 'var(--ink)', ink2: 'var(--ink-2)', ink3: 'var(--ink-3)', tealInk: 'var(--teal-ink)',
  teal: 'var(--teal)', tealDeep: 'var(--teal-deep)', coral: 'var(--coral)',
  sunset: 'var(--sunset)', violet: 'var(--violet)',
  hairline: 'var(--hairline)', disp: 'var(--disp)', ui: 'var(--ui)',
};

// Two-layer system: everything below is the thin LOCAL ACCENT LAYER —
// the rail's official mark + local-language trust words. Core identity never changes.
const RD_MARKETS = {
  br: {
    railName: 'PIX', Mark: (p) => <PixMark {...p} />,
    vendor: 'Quiosque do Mar', vendorSub: 'Barraca 12 · Praia do Forte, BA',
    vendorInitials: 'QM',
    amountLocal: 'R$ 12,00', amountGbp: '£1.70', rateLine: '£1 = R$7.05',
    fee: '£0.00',
    balanceAfter: '£140.80',
    trustConfirm: 'Instant. Arrives the moment you pay', trustPaid: 'Pago',
    payVerb: 'Pay R$ 12,00', scanTitle: 'Scan any PIX code',
    scanHint: 'Menus, tills, machines. Every PIX code works',
    railId: 'E2E5f8c···8412',
  },
  in: {
    railName: 'UPI', Mark: (p) => <UpiMark {...p} />,
    vendor: 'Chai Point', vendorSub: 'Connaught Place · New Delhi',
    vendorInitials: 'CP',
    amountLocal: '₹180', amountGbp: '£1.69', rateLine: '£1 = ₹106.60',
    fee: '£0.00',
    balanceAfter: '£140.81',
    trustConfirm: 'Instant. Arrives the moment you pay', trustPaid: 'हो गया',
    payVerb: 'Pay ₹180', scanTitle: 'Scan any UPI code',
    scanHint: 'Every UPI QR works: stalls, shops, autos',
    railId: 'UPI914d···2260',
  },
};

// ── grain — subtle paper warmth, tweakable ──
const RD_GRAIN_URI = "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.4'/%3E%3C/svg%3E\")";
function RdGrain({ on = true, opacity = 0.05 }) {
  if (!on) return null;
  return <div aria-hidden="true" style={{ position: 'absolute', inset: 0, backgroundImage: RD_GRAIN_URI, opacity, pointerEvents: 'none', zIndex: 1 }}></div>;
}

// ── logo — the ONLY place the Shaka gradient lives (plus the success moment) ──
function RdLogo({ size = 38 }) {
  return (
    <div style={{ width: size, height: size, borderRadius: '50%', overflow: 'hidden', background: 'var(--shaka)', flexShrink: 0 }}>
      <img src="assets/shaka-hand.svg" alt="GrinGo" style={{ width: '100%', height: '100%', display: 'block' }} />
    </div>
  );
}

// ── rail slot — clearly bounded, mark never recoloured ──
function RdRailSlot({ market = 'br', h = 15, style = {} }) {
  const M = RD_MARKETS[market].Mark;
  return (
    <div style={{
      display: 'inline-flex', alignItems: 'center', padding: '7px 12px',
      background: '#FFFFFF', border: `1.5px solid ${RD.hairline}`,
      borderRadius: 'var(--r-chip)', ...style,
    }}><M h={h} /></div>
  );
}

// ── buttons ──
function RdButton({ children, kind = 'primary', onClick, style = {}, icon = null }) {
  const base = {
    width: '100%', minHeight: 64, border: 'none', cursor: 'pointer',
    display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 12,
    fontFamily: RD.disp, fontWeight: 700, fontSize: 20, letterSpacing: '-0.01em',
    borderRadius: 'var(--r-btn)', transition: 'transform 120ms ease, background 120ms ease',
    WebkitTapHighlightColor: 'transparent',
  };
  const kinds = {
    primary: { background: RD.teal, color: RD.tealInk },
    ink: { background: RD.ink, color: '#FFFFFF' },
    paper: { background: RD.paperHi, color: RD.ink, border: `1.5px solid ${RD.hairline}` },
    ghost: { background: 'transparent', color: RD.ink2, fontFamily: RD.ui, fontWeight: 600, fontSize: 16, minHeight: 48 },
    onGradient: { background: '#FFFFFF', color: RD.tealInk },
  };
  return (
    <button onClick={onClick} style={{ ...base, ...kinds[kind], ...style }}
      onMouseDown={(e) => { e.currentTarget.style.transform = 'scale(0.975)'; }}
      onMouseUp={(e) => { e.currentTarget.style.transform = 'scale(1)'; }}
      onMouseLeave={(e) => { e.currentTarget.style.transform = 'scale(1)'; }}>
      {icon}{children}
    </button>
  );
}

// ── screen shell (renders under the device status bar) ──
function RdScreen({ children, bg = RD.paper, grain = true, label, style = {} }) {
  return (
    <div data-screen-label={label} style={{
      width: '100%', height: '100%', background: bg, position: 'relative',
      overflow: 'hidden', fontFamily: RD.ui, color: RD.ink,
      display: 'flex', flexDirection: 'column', ...style,
    }}>
      <RdGrain on={grain} />
      <div style={{ position: 'relative', zIndex: 2, display: 'flex', flexDirection: 'column', height: '100%' }}>{children}</div>
    </div>
  );
}

// ── the FX trust line — the ONE moment two currencies meet, ONE line ──
function RdFxLine({ m, style = {} }) {
  return (
    <div style={{ borderTop: `1.5px solid ${RD.hairline}`, borderBottom: `1.5px solid ${RD.hairline}`, padding: '14px 2px', ...style }}>
      <div className="rd-num" style={{ display: 'flex', alignItems: 'baseline', gap: 7, flexWrap: 'nowrap', whiteSpace: 'nowrap', fontFamily: RD.ui, fontSize: 15.5, fontWeight: 600, color: RD.ink }}>
        <span style={{ fontWeight: 700 }}>Rate locked:</span>
        <span>{m.rateLine}</span>
        <span style={{ color: RD.ink3, fontWeight: 400 }}>·</span>
        <span style={{ color: RD.ink2 }}>GrinGo rate</span>
      </div>
      <div style={{ marginTop: 7, fontSize: 13.5, fontWeight: 600, color: RD.tealDeep, display: 'flex', alignItems: 'center', gap: 6 }}>
        <IcCheck size={14} color={RD.tealDeep} />Locked for 60s once you slide to pay
      </div>
    </div>
  );
}

// ── top bar for sub-screens ──
function RdTopBar({ title, onBack, right = null }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 13 }}>
      <button onClick={onBack} aria-label="Back" style={{
        width: 46, height: 46, borderRadius: 'var(--r-chip)', border: `1.5px solid ${RD.hairline}`,
        background: RD.paperHi, color: RD.ink, cursor: 'pointer',
        display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
      }}><IcBack size={20} /></button>
      <div className="rd-h1" style={{ fontSize: 21, color: RD.ink, flex: 1 }}>{title}</div>
      {right}
    </div>
  );
}

// ── big one-thumb keypad ──
function RdKeypad({ onKey, style = {} }) {
  const keys = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '', '0', 'del'];
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 6, ...style }}>
      {keys.map((k, i) => k === '' ? <div key={i}></div> : (
        <button key={i} onClick={() => onKey(k)} style={{
          height: 58, background: 'transparent', border: 'none', cursor: 'pointer',
          borderRadius: 'var(--r-chip)', color: RD.ink,
          fontFamily: RD.disp, fontWeight: 700, fontSize: 26,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          WebkitTapHighlightColor: 'transparent',
        }}
          onMouseDown={(e) => { e.currentTarget.style.background = 'rgba(10,43,34,0.08)'; }}
          onMouseUp={(e) => { e.currentTarget.style.background = 'transparent'; }}
          onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }}>
          {k === 'del' ? <IcDel size={24} /> : k}
        </button>
      ))}
    </div>
  );
}

// ── markets — one list, used by Home rail, Welcome marquee, Profile ──
const RD_MARKET_LIST = [
  { Flag: FlagBR, name: 'Brazil', Mark: (p) => <PixMark {...p} /> },
  { Flag: FlagCO, name: 'Colombia', rail: 'Bre-B', soon: true },
  { Flag: FlagMX, name: 'Mexico', rail: 'SPEI', soon: true },
  { Flag: FlagAR, name: 'Argentina', rail: 'MODO', soon: true },
  { Flag: FlagBO, name: 'Bolivia', rail: 'QR Simple', soon: true },
];
function RdMarketChips() {
  return <>{RD_MARKET_LIST.map((m, i) => <RdMarketChip key={i} {...m} />)}</>;
}

// ── chip rail — drag/swipe-scrollable row with an edge fade hint ──
function RdChipRail({ children, bleed = 22, style = {} }) {
  const ref = React.useRef(null);
  const st = React.useRef(null);
  const k = () => {
    const el = ref.current, r = el.getBoundingClientRect();
    return r.width ? el.offsetWidth / r.width : 1;
  };
  const down = (e) => {
    st.current = { x: e.clientX * k(), s: ref.current.scrollLeft };
    try { e.currentTarget.setPointerCapture(e.pointerId); } catch (err) {}
  };
  const move = (e) => {
    if (!st.current) return;
    ref.current.scrollLeft = st.current.s - (e.clientX * k() - st.current.x);
  };
  const up = () => { st.current = null; };
  return (
    <div style={{ position: 'relative', marginRight: -bleed, ...style }}>
      <div ref={ref} className="no-scrollbar" onPointerDown={down} onPointerMove={move} onPointerUp={up} onPointerCancel={up}
        style={{ display: 'flex', gap: 8, overflowX: 'auto', paddingRight: bleed + 30, cursor: 'grab', touchAction: 'pan-x', userSelect: 'none' }}>
        {children}
      </div>
      <div style={{ position: 'absolute', top: 0, bottom: 0, right: 0, width: 44, pointerEvents: 'none', background: 'linear-gradient(90deg, rgba(244,241,232,0), var(--paper))' }}></div>
    </div>
  );
}

// ── chip marquee — auto-scrolls the market list, loops forever ──
function RdChipMarquee({ children, bleed = 26, duration = 20, style = {} }) {
  const mask = 'linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent)';
  return (
    <div style={{ marginLeft: -bleed, marginRight: -bleed, overflow: 'hidden', WebkitMaskImage: mask, maskImage: mask, ...style }}>
      <div style={{ display: 'flex', gap: 8, width: 'max-content', animation: `rd-marquee ${duration}s linear infinite` }}>
        {children}{children}
      </div>
    </div>
  );
}

// ── toast — approval / status notification sliding in from the top ──
function RdToast({ show, title, body }) {
  if (!show) return null;
  return (
    <div style={{
      position: 'absolute', top: 64, left: 16, right: 16, zIndex: 6,
      display: 'flex', gap: 13, alignItems: 'center', padding: '14px 16px',
      background: RD.ink, borderRadius: 'var(--r-card)',
      boxShadow: '0 18px 40px rgba(7,20,16,0.35)',
      animation: 'rd-toast 420ms cubic-bezier(0.2, 0.9, 0.3, 1) both',
    }}>
      <div style={{ width: 40, height: 40, borderRadius: '50%', background: RD.teal, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, animation: 'rd-pop 300ms 150ms ease both' }}>
        <IcCheck size={22} color={RD.tealInk} />
      </div>
      <div style={{ minWidth: 0 }}>
        <div style={{ fontFamily: RD.disp, fontWeight: 700, fontSize: 16, color: '#FFFFFF', letterSpacing: '-0.01em' }}>{title}</div>
        <div className="rd-body" style={{ fontSize: 13.5, color: 'rgba(244,241,232,0.8)', marginTop: 2 }}>{body}</div>
      </div>
    </div>
  );
}

// money helpers (cents → strings). ONE rate in the whole app: GBP → BRL, locked at the moment of payment.
const RD_RATE_GBPBRL = 7.05;   // £1 = R$7.05, GrinGo rate
const fmtBRL = (c) => 'R$ ' + Math.floor(c / 100) + ',' + String(c % 100).padStart(2, '0');
const fmtGBP = (c) => '£' + Math.floor(c / 100) + '.' + String(c % 100).padStart(2, '0');
const fmtGBPNum = (x) => '£' + x.toFixed(2);

// ── slide to pay ──
function RdSlidePay({ label = 'Slide to pay', onComplete }) {
  const trackRef = React.useRef(null);
  const [x, setX] = React.useState(0);
  const [drag, setDrag] = React.useState(false);
  const [done, setDone] = React.useState(false);
  const THUMB = 60, PAD = 6;
  const maxX = () => (trackRef.current ? trackRef.current.offsetWidth - THUMB - PAD * 2 : 260);

  const onDown = (e) => {
    if (done) return;
    try { e.currentTarget.setPointerCapture(e.pointerId); } catch (err) {}
    setDrag(true);
  };
  const onMove = (e) => {
    if (!drag || done) return;
    const rect = trackRef.current.getBoundingClientRect();
    // preview scales the device frame; convert screen px to local px
    const k = trackRef.current.offsetWidth / rect.width;
    setX(Math.max(0, Math.min(maxX(), (e.clientX - rect.left) * k - PAD - THUMB / 2)));
  };
  const onUp = () => {
    if (done) return;
    setDrag(false);
    if (x > maxX() * 0.75) { setX(maxX()); setDone(true); setTimeout(() => onComplete && onComplete(), 180); }
    else setX(0);
  };

  return (
    <div ref={trackRef} onPointerDown={onDown} onPointerMove={onMove} onPointerUp={onUp}
      style={{
        position: 'relative', height: 72, borderRadius: 'var(--r-btn)', background: RD.ink,
        touchAction: 'none', cursor: 'grab', userSelect: 'none', overflow: 'hidden',
      }}>
      {/* teal fill behind the thumb */}
      <div style={{ position: 'absolute', top: 0, bottom: 0, left: 0, width: PAD + THUMB + x, background: RD.teal, borderRadius: 'var(--r-btn)', transition: drag ? 'none' : 'width 180ms ease' }}></div>
      <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: RD.disp, fontWeight: 700, fontSize: 19, color: '#fff', opacity: done ? 0 : Math.max(0.25, 1 - x / 140), paddingLeft: 40 }}>{label}</div>
      <div style={{
        position: 'absolute', top: PAD, left: PAD, width: THUMB, height: 72 - PAD * 2,
        transform: `translateX(${x}px)`, transition: drag ? 'none' : 'transform 180ms ease',
        background: RD.teal, borderRadius: '22px 22px 22px 5px',
        display: 'flex', alignItems: 'center', justifyContent: 'center', color: RD.tealInk,
      }}>{done ? <IcCheck size={26} color={RD.tealInk} /> : <IcArrowUpR size={26} color={RD.tealInk} />}</div>
    </div>
  );
}

Object.assign(window, { RD, RD_MARKETS, RD_MARKET_LIST, RdMarketChips, RdChipRail, RdChipMarquee, RdToast, RdGrain, RdLogo, RdRailSlot, RdButton, RdScreen, RdFxLine, RdTopBar, RdKeypad, RdSlidePay, RD_RATE_GBPBRL, fmtBRL, fmtGBP, fmtGBPNum });
