/* ============================================================
   SVLM — Full Profile. Ported from public/index.html's Profile tab
   (loadAccountTab()/PROFILE_SUBVIEW_LOADERS/loadRewards()/loadAddresses()/
   loadPaymentMethods()/requestAccountDeletion()) — same real endpoints,
   same menu -> subview navigation model. "File a complaint" and "My
   complaints" detail live in complaints.jsx (next slice); this screen's
   Help Center row is just a read-only list + link out to that flow.
   ============================================================ */
const Ppf = window.PALETTE;

function Row({ icon, label, sub, onClick, danger }) {
  return (
    <div onClick={onClick} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '14px 16px', borderRadius: 16, border: `1px solid ${Ppf.line}`, background: '#fff', cursor: onClick ? 'pointer' : 'default', marginBottom: 10 }}>
      <Icon name={icon} size={19} color={danger ? '#d23a3a' : Ppf.primary} />
      <div style={{ flex: 1 }}>
        <div style={{ fontWeight: 700, fontSize: 14, color: danger ? '#d23a3a' : Ppf.ink }}>{label}</div>
        {sub && <div style={{ fontSize: 11.5, color: Ppf.faint, marginTop: 2 }}>{sub}</div>}
      </div>
      {onClick && <Icon name="chevR" size={17} color={Ppf.faint} />}
    </div>
  );
}

function SubHeader({ title, onBack }) {
  return <AppHeader onBack={onBack} title={title} />;
}

/* ---- Personal data + photo + addresses ---- */
function PersonalDataView({ app, onBack, onSaved }) {
  const c = app.auth.customer;
  const [name, setName] = React.useState(c.name || '');
  const [phone, setPhone] = React.useState(c.phone || '');
  const [email, setEmail] = React.useState(c.email || '');
  const [err, setErr] = React.useState('');
  const [addresses, setAddresses] = React.useState(null);
  const [addrLabel, setAddrLabel] = React.useState('');
  const [addrText, setAddrText] = React.useState('');
  const fileRef = React.useRef(null);

  const loadAddresses = () => api('/customers/me/addresses').then(setAddresses);
  React.useEffect(() => { loadAddresses(); }, []);

  const save = async () => {
    setErr('');
    try {
      const updated = await api('/customers/me', { method: 'PATCH', body: JSON.stringify({ name: name.trim(), phone: phone.trim(), email: email.trim() }) });
      onSaved(updated);
    } catch (e) { setErr(e.message); }
  };

  const uploadPhoto = async (file) => {
    if (!file) return;
    const form = new FormData();
    form.append('photo', file);
    const result = await api('/customers/me/photo', { method: 'POST', body: form });
    onSaved({ photo_url: result.photo_url });
  };

  const addAddress = async () => {
    if (!addrText.trim()) return;
    await api('/customers/me/addresses', { method: 'POST', body: JSON.stringify({ label: addrLabel.trim(), address_text: addrText.trim() }) });
    setAddrLabel(''); setAddrText('');
    loadAddresses();
  };
  const deleteAddress = async (id) => { await api(`/customers/me/addresses/${id}`, { method: 'DELETE' }); loadAddresses(); };

  return (
    <div>
      <SubHeader title={t('customer', 'personal_data_label') || 'Personal Data'} onBack={onBack} />
      <div style={{ padding: '0 20px 40px' }}>
        <div style={{ display: 'flex', justifyContent: 'center', marginBottom: 20 }}>
          <div onClick={() => fileRef.current.click()} style={{ width: 84, height: 84, borderRadius: 99, background: Ppf.tintBlue, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 30, fontWeight: 800, color: Ppf.primary, cursor: 'pointer', overflow: 'hidden', position: 'relative' }}>
            {c.photo_url ? <img src={c.photo_url} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} /> : (c.name || '?').trim().charAt(0).toUpperCase()}
            <div style={{ position: 'absolute', bottom: 0, right: 0, width: 26, height: 26, borderRadius: 99, background: Ppf.primary, display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="camera" size={13} color="#fff" /></div>
          </div>
          <input ref={fileRef} type="file" accept="image/jpeg,image/png,image/webp" style={{ display: 'none' }} onChange={e => uploadPhoto(e.target.files[0])} />
        </div>

        <Field label={t('customer', 'name_label') || 'Name'}><input value={name} onChange={e => setName(e.target.value)} style={inputStyle} /></Field>
        <Field label={t('customer', 'phone_label') || 'Phone'}><input value={phone} onChange={e => setPhone(e.target.value)} style={inputStyle} /></Field>
        <Field label={t('customer', 'email_label') || 'Email'}><input type="email" value={email} onChange={e => setEmail(e.target.value)} style={inputStyle} /></Field>
        {err && <p style={{ color: '#d23a3a', fontSize: 13, marginBottom: 10 }}>{err}</p>}
        <Btn onClick={save} style={{ marginBottom: 28 }}>{t('customer', 'confirm_booking') ? (app.lang === 'th' ? 'บันทึก' : 'Save') : 'Save'}</Btn>

        <SectionHead title={t('customer', 'my_addresses') || 'My addresses'} />
        {addresses === null ? null : addresses.length === 0
          ? <p style={{ fontSize: 13, color: Ppf.faint }}>{app.lang === 'th' ? 'ยังไม่มีที่อยู่ที่บันทึกไว้' : 'No saved addresses'}</p>
          : addresses.map(a => (
            <div key={a.id} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '10px 0', borderBottom: `1px solid ${Ppf.lineSoft}` }}>
              <span style={{ fontSize: 13.5, color: Ppf.ink }}>{a.label && <b>{a.label}: </b>}{a.address_text}</span>
              <button onClick={() => deleteAddress(a.id)} style={{ background: 'none', border: 'none', color: '#d23a3a', fontWeight: 700, fontSize: 12.5, cursor: 'pointer' }}>{t('customer', 'delete_btn') || 'Delete'}</button>
            </div>
          ))}
        <div style={{ marginTop: 12 }}>
          <input value={addrLabel} onChange={e => setAddrLabel(e.target.value)} placeholder={t('customer', 'label_field') || 'Label'} style={{ ...inputStyle, height: 42, marginBottom: 8 }} />
          <input value={addrText} onChange={e => setAddrText(e.target.value)} placeholder={t('customer', 'address_field') || 'Address'} style={{ ...inputStyle, height: 42, marginBottom: 8 }} />
          <Btn variant="soft" size="sm" onClick={addAddress}>{t('customer', 'add_address') || 'Add address'}</Btn>
        </div>
      </div>
    </div>
  );
}

/* ---- Payment methods (label-only records — no card numbers ever touch this app) ---- */
function PaymentMethodsView({ app, onBack }) {
  const [methods, setMethods] = React.useState(null);
  const load = () => api('/customers/me/payment-methods').then(setMethods);
  React.useEffect(() => { load(); }, []);
  const del = async (id) => { await api(`/customers/me/payment-methods/${id}`, { method: 'DELETE' }); load(); };
  return (
    <div>
      <SubHeader title={t('customer', 'payment_methods') || 'Payment methods'} onBack={onBack} />
      <div style={{ padding: '0 20px 40px' }}>
        {methods === null ? null : methods.length === 0
          ? (
            <p style={{ fontSize: 13, color: Ppf.faint, lineHeight: 1.7 }}>
              {app.lang === 'th'
                ? 'ยังไม่มีบัตรที่บันทึกไว้ — เมื่อชำระด้วยบัตรครั้งถัดไป เลือก "บันทึกบัตรนี้" ได้ที่หน้าชำระเงิน'
                : 'No saved cards yet. Tick “save this card” next time you pay by card and it will appear here.'}
            </p>
          )
          : methods.map(m => (
            <div key={m.id} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '12px 0', borderBottom: `1px solid ${Ppf.lineSoft}` }}>
              <div>
                {/* A card is recognised by its brand and last four, not by a name someone typed. */}
                <div style={{ fontSize: 13.5, color: Ppf.ink, fontWeight: 600 }}>
                  {m.card_last4 ? `${m.card_brand} ····${m.card_last4}` : m.label}
                </div>
                {m.card_exp_month && (
                  <div style={{ fontSize: 11.5, color: Ppf.faint, marginTop: 2 }}>
                    {app.lang === 'th' ? 'หมดอายุ ' : 'Expires '}
                    {String(m.card_exp_month).padStart(2, '0')}/{String(m.card_exp_year).slice(-2)}
                  </div>
                )}
              </div>
              <button onClick={() => del(m.id)} style={{ background: 'none', border: 'none', color: '#d23a3a', fontWeight: 700, fontSize: 12.5, cursor: 'pointer' }}>{t('customer', 'delete_btn') || 'Delete'}</button>
            </div>
          ))}

        {/* The card itself lives with the payment provider, and saying so is the honest answer to
            "where are my card details" — a question this screen previously invited and never
            answered, since all it held was a label the customer typed themselves. */}
        <p style={{ fontSize: 11.5, color: Ppf.faint, lineHeight: 1.7, marginTop: 18 }}>
          {app.lang === 'th'
            ? 'บัตรของคุณถูกเก็บโดยผู้ให้บริการชำระเงิน ไม่ได้เก็บที่ SVLM — เราเห็นเพียงเลข 4 ตัวท้ายและวันหมดอายุเพื่อให้คุณจำได้ว่าเป็นบัตรใบไหน'
            : 'Your card is held by our payment provider, not by SVLM. We only see the last four digits and the expiry, so you can tell your cards apart.'}
        </p>
      </div>
    </div>
  );
}

/* ---- Rewards: coin wallet + loyalty points + gift vouchers, all real ---- */
function RewardsView({ app, onBack }) {
  const [data, setData] = React.useState(null);
  const load = () => Promise.all([
    api('/customers/me/wallet'), api('/customers/me/wallet/transactions'),
    api('/customers/me/loyalty-points'), api('/customers/me/loyalty-points/transactions'),
    api('/gift-vouchers/active'), api('/customers/me/vouchers'),
  ]).then(([wallet, coinTx, points, pointTx, vouchers, myVouchers]) => setData({ wallet, coinTx, points, pointTx, vouchers, myVouchers }));
  React.useEffect(() => { load(); }, []);
  if (!data) return <div><SubHeader title="Rewards" onBack={onBack} /></div>;
  const { wallet, coinTx, points, pointTx, vouchers, myVouchers } = data;
  const pendingVoucher = myVouchers.find(v => v.status === 'available');
  const redeem = async (id) => { try { await api(`/customers/me/redeem-voucher/${id}`, { method: 'POST' }); load(); } catch (e) { alert(e.message); } };

  return (
    <div>
      <SubHeader title={app.lang === 'th' ? 'สิทธิประโยชน์' : 'Rewards'} onBack={onBack} />
      <div style={{ padding: '0 20px 40px' }}>
        <div style={{ display: 'flex', gap: 10, marginBottom: 20 }}>
          <Card style={{ flex: 1, textAlign: 'center' }}><div style={{ fontSize: 22, fontWeight: 800, color: Ppf.ink }}>🪙 {wallet.coin_balance}</div><div style={{ fontSize: 11, color: Ppf.faint, marginTop: 2 }}>{app.lang === 'th' ? 'เหรียญ' : 'Coins'}</div></Card>
          <Card style={{ flex: 1, textAlign: 'center' }}><div style={{ fontSize: 22, fontWeight: 800, color: Ppf.ink }}>⭐ {points.points_balance}</div><div style={{ fontSize: 11, color: Ppf.faint, marginTop: 2 }}>{app.lang === 'th' ? 'คะแนน' : 'Points'}</div></Card>
        </div>

        {pendingVoucher && (
          <div style={{ background: Ppf.mintSoft, borderRadius: 14, padding: 12, marginBottom: 16, fontSize: 12.5, color: Ppf.mint, fontWeight: 700 }}>
            {app.lang === 'th' ? 'มีคูปองรอใช้งาน' : 'Voucher queued'}: {app.pick(pendingVoucher.title_en, pendingVoucher.title_th)}
          </div>
        )}

        <SectionHead title={app.lang === 'th' ? 'คูปองแลกของรางวัล' : 'Gift vouchers'} />
        {vouchers.length === 0
          ? <p style={{ fontSize: 13, color: Ppf.faint, marginBottom: 16 }}>{app.lang === 'th' ? 'ยังไม่มีคูปองให้แลก' : 'No vouchers available'}</p>
          : vouchers.map(v => (
            <div key={v.id} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '10px 0', borderBottom: `1px solid ${Ppf.lineSoft}` }}>
              <span style={{ fontSize: 13, color: Ppf.ink }}>{app.pick(v.title_en, v.title_th)} — {v.points_cost}⭐{v.value_thb ? ` (${baht(v.value_thb)})` : ''}</span>
              <button disabled={points.points_balance < v.points_cost} onClick={() => redeem(v.id)} style={{ padding: '6px 12px', borderRadius: 10, border: `1.5px solid ${Ppf.primary}`, background: '#fff', color: Ppf.primary, fontWeight: 700, fontSize: 11.5, cursor: 'pointer', opacity: points.points_balance < v.points_cost ? 0.4 : 1 }}>{app.lang === 'th' ? 'แลก' : 'Redeem'}</button>
            </div>
          ))}

        <SectionHead title={app.lang === 'th' ? 'ประวัติเหรียญ' : 'Coin history'} />
        {coinTx.length === 0 ? <p style={{ fontSize: 13, color: Ppf.faint }}>{app.lang === 'th' ? 'ยังไม่มีประวัติ' : 'No history yet'}</p> : coinTx.slice(0, 10).map((tx, i) => (
          <div key={i} style={{ display: 'flex', justifyContent: 'space-between', padding: '7px 0', fontSize: 12.5 }}>
            <span style={{ color: tx.reason === 'earned' ? Ppf.mint : '#d23a3a', fontWeight: 700 }}>{tx.reason === 'earned' ? '+' : '-'}{Math.abs(tx.delta)}{tx.booking_id ? ` (${tx.booking_id})` : ''}</span>
            <span style={{ color: Ppf.faint }}>{new Date(tx.created_at).toLocaleDateString()}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

function HelpCenterView({ app, onBack }) {
  const [complaints, setComplaints] = React.useState(null);
  React.useEffect(() => { api('/complaints/mine').then(setComplaints); }, []);
  return (
    <div>
      <SubHeader title={t('customer', 'help_center_label') || 'Help Center'} onBack={onBack} />
      <div style={{ padding: '0 20px 100px' }}>
        <Btn onClick={() => app.go('chat-thread', { kind: 'general', bookingId: null, name: t('customer', 'svlm_support_name') || 'SVLM Support', online: null })} style={{ marginBottom: 20 }}>
          {t('customer', 'ask_us_anything') || 'Ask us anything'}
        </Btn>
        <SectionHead title={t('customer', 'my_complaints') || 'My complaints'} />
        {complaints === null ? null : complaints.length === 0
          ? <p style={{ fontSize: 13, color: Ppf.faint }}>{app.lang === 'th' ? 'ยังไม่มีเรื่องร้องเรียน' : 'No complaints yet'}</p>
          : complaints.map(c => (
            <div key={c.id} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '10px 0', borderBottom: `1px solid ${Ppf.lineSoft}` }}>
              <span style={{ fontSize: 13, color: Ppf.ink }}>{c.id} — {c.reason_label_en || c.severity}</span>
              <Badge status={c.status} />
            </div>
          ))}
      </div>
      <BottomBar>
        <Btn onClick={() => app.go('complaint')}>{t('customer', 'file_complaint') || 'File complaint'}</Btn>
      </BottomBar>
    </div>
  );
}

/* ---- Notification settings — per-category push(LINE)/in-app toggles.
   'system' (account/security) is not muteable — see notification_categories.is_muteable — so it
   renders as fixed "Always on" text instead of interactive toggles, matching what the server would
   silently enforce anyway rather than showing a control that wouldn't actually do anything. ---- */
function ToggleSwitch({ on, onClick, disabled }) {
  return (
    <button onClick={disabled ? undefined : onClick} disabled={disabled} style={{
      width: 42, height: 24, borderRadius: 99, border: 'none', flexShrink: 0,
      background: on ? Ppf.primary : Ppf.line, position: 'relative', cursor: disabled ? 'default' : 'pointer',
      opacity: disabled ? 0.6 : 1, padding: 0,
    }}>
      <span style={{ position: 'absolute', top: 3, left: on ? 21 : 3, width: 18, height: 18, borderRadius: 99, background: '#fff', transition: 'left .15s ease', boxShadow: '0 1px 3px rgba(0,0,0,0.25)' }} />
    </button>
  );
}

// Converts the VAPID public key (URL-safe base64, as returned by the server) into the raw byte
// array PushManager.subscribe() requires — standard boilerplate for the Push API, no library needed.
function urlBase64ToUint8Array(base64String) {
  const padding = '='.repeat((4 - (base64String.length % 4)) % 4);
  const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
  const rawData = atob(base64);
  return Uint8Array.from([...rawData].map((c) => c.charCodeAt(0)));
}

// iOS only delivers web push to a site the customer has added to their Home Screen, and only when
// it is opened from that icon. In Safari the permission prompt never appears — the request just
// fails — so the toggle here reported a bare "Error" to every iPhone owner who tried it, with
// nothing to say what to do about it. That reads as a broken feature rather than a missing step.
//
// Detected rather than assumed: Safari sets navigator.standalone, and the display-mode query is
// what everything else answers to.
function isInstalledToHomeScreen() {
  if (typeof window === 'undefined') return false;
  return window.navigator.standalone === true
    || (window.matchMedia && window.matchMedia('(display-mode: standalone)').matches);
}

function isIos() {
  if (typeof navigator === 'undefined') return false;
  // iPadOS reports itself as a Mac, and is only distinguishable by having a touch screen.
  return /iphone|ipad|ipod/i.test(navigator.userAgent)
    || (/macintosh/i.test(navigator.userAgent) && navigator.maxTouchPoints > 1);
}

function BrowserPushRow({ app }) {
  const supported = typeof window !== 'undefined' && 'serviceWorker' in navigator && 'PushManager' in window;
  // An iPhone in Safari has the APIs but cannot actually subscribe. Treated as its own state so the
  // row can explain the one step that fixes it instead of offering a switch that cannot work.
  const needsInstall = supported && isIos() && !isInstalledToHomeScreen();
  const [status, setStatus] = React.useState(
    !supported ? 'unsupported' : needsInstall ? 'needs-install' : 'checking'
  ); // checking | off | on | busy | error | needs-install

  React.useEffect(() => {
    if (!supported || needsInstall) return;
    navigator.serviceWorker.register('/sw.js').then(async (reg) => {
      const sub = await reg.pushManager.getSubscription();
      setStatus(sub ? 'on' : 'off');
    }).catch(() => setStatus('error'));
  }, [supported, needsInstall]);

  const enable = async () => {
    setStatus('busy');
    try {
      const perm = await Notification.requestPermission();
      if (perm !== 'granted') { setStatus('off'); return; }
      const { publicKey } = await api('/push/vapid-public-key');
      const reg = await navigator.serviceWorker.register('/sw.js');
      const sub = await reg.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: urlBase64ToUint8Array(publicKey) });
      await api('/customers/me/push-subscription', { method: 'POST', body: JSON.stringify(sub.toJSON()) });
      setStatus('on');
    } catch (e) {
      setStatus('error');
    }
  };

  const disable = async () => {
    setStatus('busy');
    try {
      const reg = await navigator.serviceWorker.register('/sw.js');
      const sub = await reg.pushManager.getSubscription();
      if (sub) {
        await api('/customers/me/push-subscription', { method: 'DELETE', body: JSON.stringify({ endpoint: sub.endpoint }) });
        await sub.unsubscribe();
      }
      setStatus('off');
    } catch (e) {
      setStatus('error');
    }
  };

  if (!supported) return null;

  return (
    <Card style={{ marginBottom: 10 }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div>
          <div style={{ fontWeight: 800, fontSize: 14, color: Ppf.ink }}>{app.lang === 'th' ? 'การแจ้งเตือนในเบราว์เซอร์' : 'Browser notifications'}</div>
          <div style={{ fontSize: 11.5, color: Ppf.faint, marginTop: 2 }}>
            {app.lang === 'th' ? 'รับแจ้งเตือนแม้ไม่ได้เปิดแอปอยู่' : 'Get notified even when the app isn’t open'}
          </div>
        </div>
        {status === 'checking' || status === 'busy' ? (
          <span style={{ fontSize: 12, color: Ppf.faint }}>…</span>
        ) : status === 'needs-install' ? null : status === 'error' ? (
          <span style={{ fontSize: 11.5, color: '#c93b3b' }}>{app.lang === 'th' ? 'ผิดพลาด' : 'Error'}</span>
        ) : (
          <ToggleSwitch on={status === 'on'} onClick={status === 'on' ? disable : enable} />
        )}
      </div>

      {/* The one step that turns this on, spelled out, instead of a switch that silently fails. */}
      {status === 'needs-install' && (
        <div style={{ marginTop: 10, padding: '10px 12px', borderRadius: 12, background: Ppf.lineSoft || '#f4f5f7', fontSize: 12, color: Ppf.muted, lineHeight: 1.7 }}>
          {app.lang === 'th' ? (
            <>
              บน iPhone และ iPad ต้องเพิ่มแอปลงหน้าจอโฮมก่อนจึงจะเปิดแจ้งเตือนได้<br />
              กดปุ่ม <b>แชร์</b> ในแถบล่างของ Safari → <b>เพิ่มไปยังหน้าจอโฮม</b> แล้วเปิดแอปจากไอคอนนั้น
            </>
          ) : (
            <>
              On iPhone and iPad, notifications work once the app is on your Home Screen.<br />
              Tap <b>Share</b> in Safari’s bottom bar → <b>Add to Home Screen</b>, then open the app from that icon.
            </>
          )}
        </div>
      )}
    </Card>
  );
}

function NotificationSettingsView({ app, onBack }) {
  const [prefs, setPrefs] = React.useState(null);
  const [saving, setSaving] = React.useState(false);

  React.useEffect(() => { api('/customers/me/notification-preferences').then(setPrefs); }, []);

  const update = (categoryId, field, value) => {
    setPrefs((rows) => rows.map((r) => (r.category_id === categoryId ? { ...r, [field]: value } : r)));
  };

  const save = async () => {
    setSaving(true);
    try {
      const updated = await api('/customers/me/notification-preferences', {
        method: 'PUT',
        body: JSON.stringify({ preferences: prefs.map((r) => ({ category_id: r.category_id, push: r.push, in_app: r.in_app })) }),
      });
      setPrefs(updated);
    } finally {
      setSaving(false);
    }
  };

  return (
    <div>
      <SubHeader title={t('customer', 'notif_settings_title') || 'Notification settings'} onBack={onBack} />
      <div style={{ padding: '0 20px 100px' }}>
        <p style={{ fontSize: 12.5, color: Ppf.muted, margin: '0 0 16px' }}>{t('customer', 'notif_settings_desc') || 'Choose what you hear about, and how.'}</p>
        <BrowserPushRow app={app} />
        {prefs === null ? null : prefs.map((row) => (
          <Card key={row.category_id} style={{ marginBottom: 10 }}>
            <div style={{ fontWeight: 800, fontSize: 14, color: Ppf.ink, marginBottom: row.is_muteable ? 10 : 4 }}>{app.pick(row.label_en, row.label_th)}</div>
            {!row.is_muteable ? (
              <div style={{ fontSize: 11.5, color: Ppf.faint, fontWeight: 600 }}>{app.lang === 'th' ? 'เปิดใช้งานเสมอ' : 'Always on'}</div>
            ) : (
              <>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '6px 0' }}>
                  <span style={{ fontSize: 13, color: Ppf.ink }}>{t('customer', 'notif_push_line') || 'LINE push'}</span>
                  <ToggleSwitch on={row.push} onClick={() => update(row.category_id, 'push', !row.push)} />
                </div>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '6px 0' }}>
                  <span style={{ fontSize: 13, color: Ppf.ink }}>{t('customer', 'notif_in_app') || 'In-app'}</span>
                  <ToggleSwitch on={row.in_app} onClick={() => update(row.category_id, 'in_app', !row.in_app)} />
                </div>
              </>
            )}
          </Card>
        ))}
      </div>
      <BottomBar>
        <Btn disabled={saving} onClick={save}>{saving ? '…' : (app.lang === 'th' ? 'บันทึก' : 'Save')}</Btn>
      </BottomBar>
    </div>
  );
}

function AccountScreenFull({ app }) {
  const [subview, setSubview] = React.useState(null);
  const [customer, setCustomer] = React.useState(app.auth.customer);
  const [delReq, setDelReq] = React.useState(customer.deletion_requested_at);

  const applyPatch = (patch) => {
    const updated = { ...customer, ...patch };
    setCustomer(updated);
    localStorage.setItem('svlm_customer', JSON.stringify(updated));
    app.auth.customer = updated; // keep the shared app.auth object in sync (name shown in header etc.)
    app.auth.name = updated.name;
  };

  const requestDeletion = async () => {
    if (!window.confirm(t('customer', 'confirm_deletion_message') || 'This will submit a request to permanently close your account. An admin will review it. Continue?')) return;
    const updated = await api('/customers/me/request-deletion', { method: 'POST' });
    applyPatch(updated);
    setDelReq(updated.deletion_requested_at);
  };

  const referralLink = `${window.location.origin}${window.location.pathname}?ref=${customer.id}`;
  const copyReferral = () => { navigator.clipboard?.writeText(referralLink); };

  if (subview === 'personal') return <PersonalDataView app={app} onBack={() => setSubview(null)} onSaved={applyPatch} />;
  if (subview === 'payment') return <PaymentMethodsView app={app} onBack={() => setSubview(null)} />;
  if (subview === 'rewards') return <RewardsView app={app} onBack={() => setSubview(null)} />;
  if (subview === 'help') return <HelpCenterView app={app} onBack={() => setSubview(null)} />;
  if (subview === 'notification-settings') return <NotificationSettingsView app={app} onBack={() => setSubview(null)} />;

  return (
    <div>
      <AppHeader title={app.t('tab_account') || 'Profile'} />
      <div style={{ padding: '0 20px 40px' }}>
        <Card style={{ marginBottom: 20, background: `linear-gradient(135deg, ${Ppf.navy}, #8a4a10)` }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
            <div style={{ width: 58, height: 58, borderRadius: 99, background: 'rgba(255,255,255,0.16)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontWeight: 800, fontSize: 22, overflow: 'hidden' }}>
              {customer.photo_url ? <img src={customer.photo_url} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} /> : (customer.name || 'G')[0]}
            </div>
            <div style={{ flex: 1 }}>
              <div style={{ fontWeight: 800, fontSize: 18, color: '#fff' }}>{customer.name || 'Guest'}</div>
              <div style={{ fontSize: 13, color: 'rgba(255,255,255,0.7)' }}>{customer.email ? `${customer.phone} · ${customer.email}` : customer.phone}</div>
            </div>
          </div>
        </Card>

        <Row icon="user" label={t('customer', 'personal_data_label') || 'Personal Data'} onClick={() => setSubview('personal')} />
        <Row icon="cal" label={app.t('tab_bookings') || 'My Bookings'} onClick={() => app.go('bookings')} />
        <Row icon="chat" label={app.t('tab_chat') || 'Chat'} onClick={() => app.go('chat')} />
        <Row icon="wallet" label={t('customer', 'payment_methods') || 'Payment methods'} onClick={() => setSubview('payment')} />
        <Row icon="star" label={app.lang === 'th' ? 'สิทธิประโยชน์' : 'Rewards'} onClick={() => setSubview('rewards')} />
        <Row icon="chat" label={t('customer', 'help_center_label') || 'Help Center'} onClick={() => setSubview('help')} />

        <a href={window.LINE_OA} target="_blank" rel="noopener noreferrer" style={{ textDecoration: 'none', display: 'block', marginBottom: 16 }}>
          <Card style={{ display: 'flex', alignItems: 'center', gap: 13, background: '#06c75510', border: '1px solid #06c75533' }}>
            <div style={{ width: 42, height: 42, borderRadius: 12, background: '#06c755', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontWeight: 800, fontSize: 17, flexShrink: 0 }}>L</div>
            <div style={{ flex: 1 }}>
              <div style={{ fontWeight: 800, fontSize: 14.5, color: Ppf.ink }}>{app.lang === 'th' ? 'ร้องเรียน / แชทกับ SVLM' : 'Complaints / chat with SVLM'}</div>
              <div style={{ fontSize: 12.5, color: Ppf.muted }}>{app.lang === 'th' ? 'คุยกับทีมงานทาง LINE @SVLM' : 'Talk to our team on LINE @SVLM'}</div>
            </div>
            <Icon name="chevR" size={20} color="#06c755" />
          </Card>
        </a>

        <div style={{ margin: '18px 0 8px' }}>
          <div style={{ fontSize: 11.5, fontWeight: 700, color: Ppf.faint, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 8, padding: '0 4px' }}>{t('customer', 'refer_friend') || 'Refer a friend'}</div>
          <Card>
            <p style={{ fontSize: 12.5, color: Ppf.muted, margin: '0 0 10px' }}>{t('customer', 'refer_desc') || 'Share your link — friends who sign up through it are tracked as your referrals.'}</p>
            <div style={{ display: 'flex', gap: 8 }}>
              <input readOnly value={referralLink} style={{ ...inputStyle, flex: 1, height: 40, fontSize: 12, color: Ppf.muted }} />
              <button onClick={copyReferral} style={{ padding: '0 16px', borderRadius: 12, border: `1.5px solid ${Ppf.primary}`, background: '#fff', color: Ppf.primary, fontWeight: 700, fontSize: 12.5, cursor: 'pointer' }}>{app.lang === 'th' ? 'คัดลอก' : 'Copy'}</button>
            </div>
          </Card>
        </div>

        <div style={{ margin: '18px 0 8px' }}>
          <div style={{ fontSize: 11.5, fontWeight: 700, color: Ppf.faint, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 8, padding: '0 4px' }}>{t('customer', 'settings_label') || 'Settings'}</div>
          <button onClick={app.toggleLang} style={{ width: '100%', display: 'flex', alignItems: 'center', gap: 12, padding: '14px 16px', borderRadius: 16, border: `1px solid ${Ppf.line}`, background: '#fff', cursor: 'pointer', fontFamily: 'inherit', marginBottom: 10 }}>
            <Icon name="globe" size={19} color={Ppf.primary} />
            <span style={{ flex: 1, textAlign: 'left', fontWeight: 700, fontSize: 14, color: Ppf.ink }}>{t('customer', 'language_label') || 'Language'}</span>
            <span style={{ fontSize: 13, color: Ppf.faint, fontWeight: 700 }}>{app.lang === 'th' ? 'ไทย' : 'English'}</span>
          </button>
          <Row icon="bell" label={t('customer', 'notif_settings_title') || 'Notification settings'} onClick={() => setSubview('notification-settings')} />
          {delReq ? (
            <Row icon="x" label={t('customer', 'deletion_requested_message') || 'Account deletion requested — pending admin review'} />
          ) : (
            <Row icon="x" label={t('customer', 'request_account_deletion') || 'Request Account Deletion'} onClick={requestDeletion} danger />
          )}
        </div>

        <button onClick={app.logout} style={{ width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, padding: '14px', borderRadius: 16, border: `1px solid ${Ppf.line}`, background: '#fff', cursor: 'pointer', fontFamily: 'inherit', fontWeight: 700, fontSize: 14, color: '#d23a3a', marginTop: 14 }}>
          <Icon name="logout" size={19} color="#d23a3a" /> {app.lang === 'th' ? 'ออกจากระบบ' : 'Log out'}
        </button>
      </div>
    </div>
  );
}

Object.assign(window, { AccountScreenFull });
