// src/features/calls/ui/phone-verify-card.jsx
//
// Shared "Phone number" card with country picker + as-you-type national
// formatting (libphonenumber-js). Used by BOTH the instructor Settings card
// and the student dashboard banner so the two surfaces share one tested
// implementation.
//
//   <window.MaskedCalls.ui.PhoneVerifyCard
//      kind="instructor" instructorId={id} />
//   <window.MaskedCalls.ui.PhoneVerifyCard
//      kind="student" userId={id} title="Your phone number" onVerified={fn} />
//
// No OTP: a saved number is immediately usable for masked calls. SMS OTP
// doesn't deliver to some countries (e.g. Lebanon), so we trust whoever saves
// it — the admin who manages student numbers, the student, or the instructor.
// Degrades to a plain tel input if libphonenumber hasn't loaded.
//
// Public: window.MaskedCalls.ui.PhoneVerifyCard

(function () {
  function flagEmoji(iso) {
    try {
      const cc = String(iso || '').toUpperCase();
      if (cc.length !== 2) return '';
      return String.fromCodePoint(...[...cc].map(c => 0x1f1e6 + c.charCodeAt(0) - 65));
    } catch { return ''; }
  }

  function defaultCountry(lp) {
    try {
      const region = new Intl.Locale(navigator.language).region;
      if (lp && region && lp.getCountries().includes(region)) return region;
    } catch { /* fall through */ }
    return 'US';
  }

  function PhoneVerifyCard({ kind, instructorId, userId, title, onVerified }) {
    // Dispatch the data calls by kind so one component serves both surfaces.
    // Memoized on the identifying id so the load effect is stable.
    const api = React.useMemo(() => {
      const db = window.MaskedCalls.db;
      if (kind === 'student') {
        return { load: () => db.hasStudentPhone(userId), save: (e) => db.saveStudentPhone(e) };
      }
      return { load: () => db.hasInstructorDestination(instructorId), save: (e) => db.saveInstructorDestination(e) };
    }, [kind, instructorId, userId]);

    const ready = kind === 'student' ? !!userId : !!instructorId;

    const [hasIt, setHasIt]       = React.useState(null);   // null = loading
    const [verified, setVerified] = React.useState(false);
    const [editing, setEditing]   = React.useState(false);
    const [country, setCountry]   = React.useState('US');
    const [national, setNational] = React.useState('');
    const [busy,  setBusy]        = React.useState(false);
    const [err,   setErr]         = React.useState('');
    const [okMsg, setOk]          = React.useState('');
    const [libReady, setLibReady] = React.useState(() => !!window.libphonenumber);
    const userPickedCountry = React.useRef(false);

    React.useEffect(() => {
      if (libReady) return undefined;
      let cancelled = false;
      const startedAt = Date.now();
      const tick = () => {
        if (cancelled) return;
        if (window.libphonenumber) { setLibReady(true); return; }
        if (Date.now() - startedAt > 8000) return;
        setTimeout(tick, 120);
      };
      tick();
      return () => { cancelled = true; };
    }, [libReady]);

    React.useEffect(() => {
      if (libReady && !userPickedCountry.current) {
        setCountry(defaultCountry(window.libphonenumber));
      }
    }, [libReady]);

    React.useEffect(() => {
      if (!ready) return undefined;
      let cancelled = false;
      (async () => {
        try {
          const r = await api.load();
          if (cancelled) return;
          setHasIt(r.has);
          setVerified(r.verified);
          setEditing(!r.has);
          if (r.verified && onVerified) onVerified();
        } catch {
          if (!cancelled) { setHasIt(false); setVerified(false); setEditing(true); }
        }
      })();
      return () => { cancelled = true; };
    }, [api, ready]);

    const countryOptions = React.useMemo(() => {
      const lp = window.libphonenumber;
      if (!lp) return [];
      let dn = null;
      try { dn = new Intl.DisplayNames(['en'], { type: 'region' }); } catch { /* iso fallback */ }
      return lp.getCountries()
        .map((iso) => {
          let name = iso;
          try { if (dn) name = dn.of(iso) || iso; } catch { /* keep iso */ }
          let dc = '';
          try { dc = lp.getCountryCallingCode(iso); } catch { /* skip below */ }
          return { iso, name, code: dc, flag: flagEmoji(iso) };
        })
        .filter((o) => o.code)
        .sort((a, b) => a.name.localeCompare(b.name));
    }, [libReady]);

    const dialCode = React.useMemo(() => {
      const lp = window.libphonenumber;
      if (!lp) return '';
      try { return lp.getCountryCallingCode(country); } catch { return ''; }
    }, [country, libReady]);

    function onInputChange(raw) {
      setErr('');
      const lp = window.libphonenumber;
      if (!lp) { setNational(raw); return; }
      const trimmed = String(raw || '');
      if (trimmed.trim().startsWith('+')) {
        try {
          const ayt = new lp.AsYouType();
          const intlFormatted = ayt.input(trimmed.trim());
          const detected = ayt.getCountry();
          const num = ayt.getNumber();
          if (detected) {
            setCountry(detected);
            userPickedCountry.current = true;
            const natl = num && num.nationalNumber ? String(num.nationalNumber) : '';
            setNational(new lp.AsYouType(detected).input(natl));
          } else {
            setNational(intlFormatted);
          }
          return;
        } catch { setNational(trimmed); return; }
      }
      try {
        setNational(new lp.AsYouType(country).input(trimmed));
      } catch {
        setNational(trimmed);
      }
    }

    function onCountryChange(iso) {
      userPickedCountry.current = true;
      setCountry(iso);
      setErr('');
      const lp = window.libphonenumber;
      const digits = national.replace(/[^\d]/g, '');
      if (lp && digits) {
        try { setNational(new lp.AsYouType(iso).input(digits)); } catch { /* keep */ }
      }
    }

    function toE164() {
      const lp = window.libphonenumber;
      const digits = national.replace(/[^\d]/g, '');
      if (!digits) throw new Error('Enter a phone number');
      if (lp) {
        const parsed = lp.parsePhoneNumberFromString(digits, country);
        if (parsed && parsed.isValid()) return parsed.number;
        const intl = lp.parsePhoneNumberFromString(national.trim());
        if (intl && intl.isValid()) return intl.number;
        throw new Error('Enter a valid phone number');
      }
      const t = national.trim();
      if (t.startsWith('+')) return '+' + digits;
      if (dialCode) return '+' + dialCode + digits;
      return '+' + digits;
    }

    async function save() {
      setBusy(true); setErr(''); setOk('');
      try {
        const e164 = toE164();
        await api.save(e164);
        // No OTP — the saved number is immediately usable for masked calls.
        setHasIt(true);
        setVerified(true);
        setEditing(false);
        setNational('');
        setOk('Saved — your teacher can call this number.');
        setTimeout(() => setOk(''), 3000);
        if (onVerified) onVerified();
      } catch (e) {
        setErr(e.message || String(e));
      } finally {
        setBusy(false);
      }
    }

    function startEdit() {
      setEditing(true);
      setNational(''); setErr('');
    }

    const inputBase = {
      padding: '8px 12px', borderRadius: 6,
      border: '1px solid oklch(86% 0.02 265)',
      fontSize: 14, fontFamily: 'inherit', boxSizing: 'border-box',
    };
    const primaryBtn = (disabled) => ({
      padding: '8px 16px', borderRadius: 6, background: 'oklch(50% 0.18 250)',
      color: '#fff', border: 'none', cursor: disabled ? 'not-allowed' : 'pointer',
      fontSize: 14, fontWeight: 600, fontFamily: 'inherit', opacity: disabled ? 0.7 : 1,
    });
    const ghostBtn = {
      padding: '8px 12px', borderRadius: 6, border: '1px solid oklch(86% 0.02 265)',
      background: '#fff', cursor: 'pointer', fontSize: 13, color: 'oklch(35% 0.04 265)',
      fontFamily: 'inherit',
    };
    const errBox = {
      marginTop: 8, padding: '6px 10px', borderRadius: 4,
      background: 'oklch(96% 0.06 25)', color: 'oklch(40% 0.15 25)', fontSize: 12,
    };

    return (
      <div style={{
        background: '#fff', border: '1px solid oklch(92% 0.01 265)',
        borderRadius: 10, padding: 12, fontFamily: "'Plus Jakarta Sans', sans-serif",
      }}>
        <div style={{ fontSize: 14, fontWeight: 700, color: 'oklch(22% 0.06 265)', marginBottom: 10 }}>
          {title || 'Phone number'}
        </div>

        {hasIt === null && (
          <div style={{ fontSize: 13, color: 'oklch(50% 0.03 265)' }}>Loading…</div>
        )}

        {hasIt !== null && !editing && (
          <div style={{ display: 'flex', gap: 12, alignItems: 'center', flexWrap: 'wrap' }}>
            {verified ? (
              <div style={{ fontSize: 13, color: 'oklch(36% 0.06 145)', fontWeight: 600 }}>✓ On file — your teacher can reach you on this number.</div>
            ) : (
              <div style={{ fontSize: 13, color: 'oklch(45% 0.13 60)', fontWeight: 600 }}>Saved — tap Update to activate calling.</div>
            )}
            <button type="button" onClick={startEdit} style={ghostBtn}>
              {verified ? 'Update' : 'Change number'}
            </button>
          </div>
        )}

        {hasIt !== null && editing && (
          <React.Fragment>
            {libReady && countryOptions.length > 0 ? (
              <React.Fragment>
                <select
                  value={country} onChange={(e) => onCountryChange(e.target.value)}
                  disabled={busy} aria-label="Country"
                  style={{ ...inputBase, width: '100%', marginBottom: 8, background: '#fff', cursor: 'pointer' }}
                >
                  {countryOptions.map((o) => (
                    <option key={o.iso} value={o.iso}>{o.flag} {o.name} (+{o.code})</option>
                  ))}
                </select>
                <div style={{ display: 'flex', gap: 8, alignItems: 'stretch' }}>
                  <div style={{
                    display: 'flex', alignItems: 'center', padding: '8px 10px', borderRadius: 6,
                    border: '1px solid oklch(86% 0.02 265)', background: 'oklch(97% 0.007 265)',
                    fontSize: 14, fontWeight: 600, color: 'oklch(35% 0.04 265)', whiteSpace: 'nowrap',
                  }}>+{dialCode}</div>
                  <input
                    type="tel" inputMode="tel" autoComplete="tel-national" placeholder="555 123 4567"
                    value={national} onChange={(e) => onInputChange(e.target.value)} disabled={busy}
                    style={{ ...inputBase, flex: '1 1 auto', minWidth: 0 }}
                  />
                </div>
              </React.Fragment>
            ) : (
              <input
                type="tel" inputMode="tel" autoComplete="tel" placeholder="+1 555 123 4567"
                value={national} onChange={(e) => onInputChange(e.target.value)} disabled={busy}
                style={{ ...inputBase, width: '100%' }}
              />
            )}

            <div style={{ display: 'flex', gap: 8, marginTop: 8, flexWrap: 'wrap' }}>
              <button type="button" onClick={save} disabled={busy} style={primaryBtn(busy)}>
                {busy ? 'Saving…' : 'Save'}
              </button>
              {hasIt && (
                <button type="button" onClick={() => { setEditing(false); setNational(''); setErr(''); }}
                  disabled={busy} style={{ ...ghostBtn, fontSize: 14, padding: '8px 12px' }}>
                  Cancel
                </button>
              )}
            </div>
            {err && <div style={errBox}>{err}</div>}
          </React.Fragment>
        )}

        {okMsg && (
          <div style={{
            marginTop: 8, padding: '6px 10px', borderRadius: 4,
            background: 'oklch(96% 0.06 145)', color: 'oklch(36% 0.13 145)', fontSize: 12,
          }}>{okMsg}</div>
        )}
      </div>
    );
  }

  window.MaskedCalls = window.MaskedCalls || {};
  window.MaskedCalls.ui = window.MaskedCalls.ui || {};
  window.MaskedCalls.ui.PhoneVerifyCard = PhoneVerifyCard;
})();
