// src/features/admin/ui/admin-instructors-modals.jsx
//
// Shared widgets + the two smaller AdminInstructors modals. The big
// modals have been split into siblings to stay under the 400 LOC
// budget:
//
//   admin-instructors-modals.jsx        — this file: AddressAutosuggest,
//                                          MagicLinkPostCreate,
//                                          AIEditStudioModal, AIAvailModal
//   admin-instructors-modals-add.jsx    — AIAddModal
//   admin-instructors-modals-edit.jsx   — AIEditInstructorModal
//   admin-instructors-modals-2.jsx      — AIAddStudentModal, AIAssignStudentModal
//   admin-instructors-modals-3.jsx      — AIBookLessonModal, AIConfirmDelete
//
// All exposed on window. admin-instructors.jsx and
// admin-instructors-card.jsx reference them via <window.AIxxxModal />.

const AddressAutosuggest = ({ value, onChange, onPick, placeholder, style }) => {
  const [results, setResults] = React.useState([]);
  const [open, setOpen]       = React.useState(false);
  const [busy, setBusy]       = React.useState(false);
  const tRef = React.useRef(null);
  const handleChange = (v) => {
    onChange(v);
    if (tRef.current) clearTimeout(tRef.current);
    if (!v || v.length < 4) { setResults([]); setOpen(false); return; }
    tRef.current = setTimeout(async () => {
      setBusy(true);
      try {
        const r = await fetch(
          'https://nominatim.openstreetmap.org/search?format=jsonv2&addressdetails=1&limit=5&countrycodes=us,ca,gb,au&q=' + encodeURIComponent(v),
          { headers: { 'Accept-Language': 'en' } }
        );
        const j = await r.json();
        setResults(Array.isArray(j) ? j : []);
        setOpen(true);
      } catch (e) { setResults([]); }
      finally { setBusy(false); }
    }, 350);
  };
  const pick = (r) => {
    const a = r.address || {};
    const road = [a.house_number, a.road].filter(Boolean).join(' ') || r.display_name.split(',')[0];
    const city = a.city || a.town || a.village || a.hamlet || a.county || '';
    const state = a.state_code || (a.state ? a.state.slice(0, 2).toUpperCase() : '');
    const zip = a.postcode || '';
    onPick({ road, city, state, zip });
    setOpen(false);
  };
  return (
    <div style={{ position:'relative' }}>
      <input
        value={value}
        onChange={e => handleChange(e.target.value)}
        onFocus={() => results.length > 0 && setOpen(true)}
        onBlur={() => setTimeout(() => setOpen(false), 200)}
        placeholder={placeholder}
        style={style}
      />
      {open && (results.length > 0 || busy) && (
        <div style={{ position:'absolute', top:'100%', left:0, right:0, marginTop:4, background:'#fff', border:'1.5px solid oklch(88% 0.015 265)', borderRadius:8, boxShadow:'0 8px 24px rgba(0,0,0,0.1)', zIndex:50, maxHeight:240, overflowY:'auto' }}>
          {busy && <div style={{ padding:'8px 12px', fontSize:12, color:'oklch(60% 0.03 265)' }}>Searching…</div>}
          {results.map(r => (
            <button key={r.place_id} type="button" onMouseDown={() => pick(r)}
              style={{ display:'block', width:'100%', textAlign:'left', padding:'9px 12px', background:'#fff', border:'none', borderBottom:'1px solid oklch(96% 0.005 60)', cursor:'pointer', fontSize:12, color:'oklch(28% 0.05 265)', fontFamily:"'Plus Jakarta Sans', sans-serif" }}>
              {r.display_name}
            </button>
          ))}
          {!busy && results.length === 0 && (
            <div style={{ padding:'8px 12px', fontSize:12, color:'oklch(60% 0.03 265)' }}>No matches.</div>
          )}
        </div>
      )}
    </div>
  );
};

// ── Reusable: post-creation magic-link sender ────────────────────────────────
// `mode='create'` (default): the account was just created. The Supabase signUp
//   call already emails a login link, so we just show a confirmation — no
//   second-send button needed.
// `mode='resend'`: the account already exists — used by the Students-tab
//   magic-link button. Auto-sends the link on open so the admin doesn't have
//   to click twice; the modal just shows progress + outcome.
const MagicLinkPostCreate = ({ name, email, onClose, mode = 'create', studentId }) => {
  const data = window.useAdminData();
  const [sent, setSent] = React.useState(false);
  const [busy, setBusy] = React.useState(true);
  const [err, setErr]   = React.useState('');

  // Auto-send the link in BOTH 'create' and 'resend' modes. Previously
  // 'create' mode just claimed a link was sent without actually firing
  // one — leading to silent no-email bugs.
  React.useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        // studentId (v56) lets the helper stamp student_info.magic_link_sent_at
        // so the dashboard's "No invite sent" chip clears immediately.
        await data.sendInviteMagicLink(email, studentId);
        if (!cancelled) setSent(true);
      } catch (e) {
        if (!cancelled) setErr(window.friendlyError(e, 'Could not send'));
      } finally {
        if (!cancelled) setBusy(false);
      }
    })();
    return () => { cancelled = true; };
  }, [email]);

  return (
    <div style={{ position:'fixed', inset:0, background:'rgba(10,12,24,0.4)', display:'flex', alignItems:'center', justifyContent:'center', zIndex:9000 }} onClick={onClose}>
      <div style={{ background:'#fff', borderRadius:16, padding:'28px', width:460, boxShadow:'0 20px 60px rgba(0,0,0,0.2)', fontFamily:"'Plus Jakarta Sans', sans-serif", textAlign:'center' }} onClick={e=>e.stopPropagation()}>
        <div style={{ fontSize:34, marginBottom:12 }}>{busy ? '⏳' : (err ? '⚠️' : '📧')}</div>
        <div style={{ fontWeight:700, fontSize:16, color:'oklch(18% 0.03 265)', marginBottom:6 }}>
          {busy
            ? `Sending login link to ${name}…`
            : err
              ? "Couldn't send login link"
              : (mode === 'create' ? 'Account created — login link sent' : 'Login link sent')}
        </div>
        <div style={{ fontSize:13, color:'oklch(52% 0.03 265)', marginBottom:18, lineHeight:1.6 }}>
          {err
            ? <>We couldn't send a link to <strong>{email}</strong>. The account itself was created — try Resend on their row later.</>
            : sent
              ? <>A login link was sent to <strong>{email}</strong>. <strong>{name}</strong> just clicks it to log in.</>
              : <>Asking Supabase to send a magic link to <strong>{email}</strong>…</>
          }
        </div>
        {err && <div style={{ background:'oklch(95% 0.06 25)', color:'oklch(40% 0.15 25)', padding:'9px 12px', borderRadius:8, fontSize:12, marginBottom:14, textAlign:'left' }}>{err}</div>}
        <div style={{ display:'flex', gap:10, justifyContent:'center' }}>
          <button onClick={onClose} style={{ background:'oklch(22% 0.06 265)', color:'#fff', border:'none', borderRadius:8, padding:'10px 22px', fontWeight:600, fontSize:13, cursor:'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif" }}>Done</button>
        </div>
      </div>
    </div>
  );
};


// ── Edit Studio Modal ────────────────────────────────────────────────────────
const AIEditStudioModal = ({ instructor, onClose }) => {
  const data = window.useAdminData();
  const s = instructor.studio || {};
  const [form, setForm] = React.useState({
    address: s.address || '', city: s.city || instructor.city || '',
    state: s.state || instructor.state || '', zip: s.zip || '',
    phone: s.phone || '', note: s.note || '',
  });
  const [busy, setBusy] = React.useState(false);
  const [error, setError] = React.useState('');
  const set = (k,v) => setForm(f=>({...f,[k]:v}));

  const fld = { width:'100%', padding:'12px 14px', borderRadius:8, border:'1.5px solid oklch(88% 0.015 265)', fontSize:16, minHeight:44, fontFamily:"'Plus Jakarta Sans', sans-serif", color:'oklch(22% 0.06 265)', background:'#fff', outline:'none', boxSizing:'border-box' };
  const lbl = { display:'block', fontSize:10, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.06em', color:'oklch(52% 0.04 265)', marginBottom:5 };

  const save = async (e) => {
    e.preventDefault();
    setBusy(true); setError('');
    try {
      const studio = { ...form, state: form.state.toUpperCase() };
      await data.updateInstructorStudio(instructor.id, studio);
      onClose();
    } catch (err) {
      setError(err.message || 'Could not save.');
    } finally {
      setBusy(false);
    }
  };

  return (
    <div style={{ position:'fixed', inset:0, background:'rgba(10,12,24,0.4)', display:'flex', alignItems:'center', justifyContent:'center', zIndex:9000 }} onClick={onClose}>
      <div style={{ background:'#fff', borderRadius:16, padding:'24px', width:440, boxShadow:'0 20px 60px rgba(0,0,0,0.2)', fontFamily:"'Plus Jakarta Sans', sans-serif" }} onClick={e=>e.stopPropagation()}>
        <div style={{ fontWeight:700, fontSize:15, color:'oklch(18% 0.03 265)', marginBottom:4 }}>Studio for {instructor.name}</div>
        <div style={{ fontSize:12, color:'oklch(60% 0.03 265)', marginBottom:18 }}>Where students go for in-person lessons.</div>
        <form onSubmit={save}>
          <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:12, marginBottom:14 }}>
            <div style={{ gridColumn:'1/-1' }}>
              <label style={lbl}>Street address</label>
              <AddressAutosuggest
                value={form.address}
                onChange={(v) => set('address', v)}
                onPick={(parts) => {
                  set('address', parts.road);
                  if (parts.city)  set('city',  parts.city);
                  if (parts.state) set('state', parts.state.toUpperCase());
                  if (parts.zip)   set('zip',   parts.zip);
                }}
                placeholder="Start typing an address…"
                style={fld}
              />
            </div>
            <div><label style={lbl}>City</label><input value={form.city} onChange={e=>set('city',e.target.value)} style={fld} /></div>
            <div><label style={lbl}>State</label><input value={form.state} onChange={e=>set('state',e.target.value.toUpperCase())} maxLength={2} style={fld} /></div>
            <div><label style={lbl}>ZIP</label><input value={form.zip} onChange={e=>set('zip',e.target.value)} style={fld} /></div>
            <div><label style={lbl}>Phone</label><input value={form.phone} onChange={e=>set('phone',e.target.value)} style={fld} /></div>
            <div style={{ gridColumn:'1/-1' }}><label style={lbl}>Note for students</label><input value={form.note} onChange={e=>set('note',e.target.value)} placeholder="Suite 3B · ring bell" style={fld} /></div>
          </div>
          {error && <div style={{ background:'oklch(95% 0.06 25)', color:'oklch(40% 0.15 25)', padding:'8px 12px', borderRadius:8, fontSize:12, marginBottom:12 }}>{error}</div>}
          <div style={{ display:'flex', gap:10 }}>
            <button type="submit" disabled={busy} style={{ flex:1, background:'oklch(22% 0.06 265)', color:'#fff', border:'none', borderRadius:9, padding:'11px 0', fontWeight:600, fontSize:13, cursor:busy?'wait':'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif", opacity:busy?0.7:1 }}>{busy ? 'Saving…' : 'Save'}</button>
            <button type="button" onClick={onClose} style={{ padding:'11px 16px', background:'oklch(95% 0.01 265)', border:'none', borderRadius:9, fontSize:13, cursor:'pointer', color:'oklch(46% 0.04 265)', fontFamily:"'Plus Jakarta Sans', sans-serif" }}>Cancel</button>
          </div>
        </form>
      </div>
    </div>
  );
};


// ── Availability Editor (uses shared AvailabilityPicker) ─────────────────────
const AIAvailModal = ({ instructor, onClose }) => {
  const data = window.useAdminData();
  const [avail, setAvail] = React.useState(null);  // multi-block shape: {0:{enabled,blocks:[...]},...}
  const [busy, setBusy] = React.useState(false);
  const [error, setError] = React.useState('');
  // Timezone lives on profiles.timezone for the instructor's user_id.
  // Loaded with the avail slots so the dropdown can show the current value
  // immediately. Saved alongside on Save. Phase 2 auto-detect: if the
  // instructor's profile has no timezone yet, prefill with the admin's
  // detected browser zone — better than always defaulting to EST when the
  // admin is in Beirut adding teachers in Lebanon.
  const [tz, setTz] = React.useState(() => window.Calendar.time.detect());

  React.useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const [slotsR, profR] = await Promise.all([
          window.supa.from('availability_slots').select('*').eq('instructor_id', instructor.id),
          instructor.userId
            ? window.supa.from('profiles').select('timezone').eq('id', instructor.userId).maybeSingle()
            : Promise.resolve({ data: null }),
        ]);
        if (slotsR.error) throw slotsR.error;
        if (cancelled) return;
        setAvail(window.Calendar.shape.slotsToBlocks(slotsR.data || []));
        if (profR?.data?.timezone) setTz(profR.data.timezone);
      } catch (e) {
        if (!cancelled) {
          setError(e.message || 'Could not load availability.');
          setAvail(Object.fromEntries([0,1,2,3,4,5,6].map(i => [i, { enabled:false, blocks:[{from:9,to:17}] }])));
        }
      }
    })();
    return () => { cancelled = true; };
  }, [instructor.id, instructor.userId]);

  const save = async () => {
    setBusy(true); setError('');
    try {
      // Convert blocks → DB rows (Sun=0 day-of-week, HH:MM:SS times).
      const rows = window.Calendar.shape.blocksToSlots(avail);
      // Replace all of this instructor's slots with the new ones in one shot.
      const { error: delE } = await window.supa.from('availability_slots').delete().eq('instructor_id', instructor.id);
      if (delE) throw delE;
      if (rows.length) {
        const payload = rows.map(r => ({ instructor_id: instructor.id, day_of_week: r.dayOfWeek, start_time: r.startTime, end_time: r.endTime }));
        const { error } = await window.supa.from('availability_slots').insert(payload);
        if (error) throw error;
      }
      // Save timezone to profiles.timezone. Soft-fails: if it errors we still
      // close because availability saved.
      if (instructor.userId) {
        try {
          await window.supa.from('profiles').update({ timezone: tz }).eq('id', instructor.userId);
        } catch (e) { console.warn('[admin avail] timezone save failed', e); }
      }
      onClose();
    } catch (e) { setError(e.message || 'Could not save.'); }
    finally { setBusy(false); }
  };

  return (
    <div style={{ position:'fixed', inset:0, background:'rgba(10,12,24,0.38)', display:'flex', alignItems:'center', justifyContent:'center', zIndex:9000 }} onClick={onClose}>
      <div style={{ background:'#fff', borderRadius:16, padding:'24px 22px 20px', maxWidth:560, width:'92vw', boxShadow:'0 20px 60px rgba(0,0,0,0.18)', fontFamily:"'Plus Jakarta Sans', sans-serif", maxHeight:'86vh', overflowY:'auto' }} onClick={e=>e.stopPropagation()}>
        <div style={{ fontWeight:700, fontSize:15, color:'oklch(18% 0.03 265)', marginBottom:2 }}>Availability — {instructor.name}</div>
        <div style={{ fontSize:12, color:'oklch(60% 0.03 265)', marginBottom:18 }}>Pick start/end times per day. Add multiple blocks if there's a break.</div>
        {avail === null ? (
          <div style={{ padding:32, textAlign:'center', fontSize:13, color:'oklch(58% 0.03 265)' }}>Loading…</div>
        ) : (
          <window.AvailabilityPicker value={avail} onChange={setAvail} compact timezone={tz} onTimezoneChange={setTz} />
        )}
        {error && <div style={{ marginTop:12, background:'oklch(95% 0.06 25)', color:'oklch(40% 0.15 25)', padding:'8px 12px', borderRadius:8, fontSize:12 }}>{error}</div>}
        <div style={{ display:'flex', gap:8, marginTop:18 }}>
          <button onClick={save} disabled={busy || avail === null} style={{ flex:1, background:'oklch(22% 0.06 265)', color:'#fff', border:'none', borderRadius:8, padding:'11px 0', fontWeight:600, fontSize:13, cursor:(busy || avail===null)?'wait':'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif", opacity:busy?0.7:1 }}>
            {busy ? 'Saving…' : 'Save availability'}
          </button>
          <button onClick={onClose} style={{ padding:'11px 16px', background:'oklch(95% 0.01 265)', border:'none', borderRadius:8, fontSize:13, cursor:'pointer', color:'oklch(46% 0.04 265)', fontFamily:"'Plus Jakarta Sans', sans-serif" }}>Cancel</button>
        </div>
      </div>
    </div>
  );
};

Object.assign(window, {
  AddressAutosuggest,
  MagicLinkPostCreate,
  AIEditStudioModal,
  AIAvailModal,
  // Legacy alias for admin-view-as.jsx. AdminEditInstructorModal +
  // AdminBookLessonModal travel with their components in -edit.jsx
  // and -modals-3.jsx respectively.
  AdminAvailabilityModal: AIAvailModal,
});
// AIAddModal lives in admin-instructors-modals-add.jsx.
// AIEditInstructorModal lives in admin-instructors-modals-edit.jsx.
