// src/features/calls/ui/call-button.jsx
//
// Renders a "Call" button inside the messages thread header for the teacher
// side of a conversation (student side now uses RequestCallButton in Phase 2).
//
// Two transports, in priority order:
//   1. Browser-audio (Twilio Voice SDK / WebRTC) — Phase 2. Teacher speaks
//      through her browser mic; only the student's phone rings. Solves the
//      Lebanon-teacher problem (no inbound US ring, no international receiving
//      charge, no foreign-number paranoia).
//   2. PSTN ring (Phase 1) — if the SDK fails to load, mic permission is
//      denied, or the token mint errors. Both phones ring; masked caller ID.
//
// Public: window.MaskedCalls.ui.CallButton
//
// Modes shown in the modal:
//   - confirm           → "Call X?" with Call now / Cancel
//   - browser-connecting → "Asking for microphone…"
//   - browser-active    → live call UI (duration + mute + hangup)
//   - pstn-falling-back → "Couldn't open browser audio, calling you on your phone instead"
//   - pstn-placed       → "Calling you first, then them"
//   - error             → red error block

(function () {
  const PRIMARY = 'oklch(50% 0.18 250)';
  const PRIMARY_HOVER = 'oklch(45% 0.18 250)';

  function fmtDuration(secs) {
    const m = Math.floor(secs / 60);
    const s = secs % 60;
    return `${m}:${s < 10 ? '0' : ''}${s}`;
  }

  function CallButton({ conversation, viewerUserId, instructorId }) {
    const [mode, setMode]     = React.useState('confirm');
    // mode in: 'confirm', 'browser-connecting', 'browser-active', 'pstn-falling-back', 'pstn-placed', 'error'
    const [open, setOpen]     = React.useState(false);
    const [err,  setErr]      = React.useState('');
    const [duration, setDuration] = React.useState(0);
    const [muted, setMuted]   = React.useState(false);
    const tickRef = React.useRef(null);
    const startedAtRef = React.useRef(null);
    // null = checking / not applicable; true = student has a phone on file;
    // false = none (gray out the teacher's Call button — nothing to bridge to).
    const [studentCallable, setStudentCallable] = React.useState(null);

    if (!conversation || !viewerUserId) return null;
    const isStudent    = conversation.student_id === viewerUserId;
    const isInstructor = instructorId && conversation.instructor_id === instructorId;
    if (!isStudent && !isInstructor) return null;

    const otherLabel = isStudent ? 'your teacher' : 'the student';

    function startDurationTicker() {
      startedAtRef.current = Date.now();
      tickRef.current = setInterval(() => {
        setDuration(Math.floor((Date.now() - startedAtRef.current) / 1000));
      }, 1000);
    }
    function stopDurationTicker() {
      if (tickRef.current) { clearInterval(tickRef.current); tickRef.current = null; }
    }
    React.useEffect(() => () => stopDurationTicker(), []);

    // Teacher side: does the student have a phone on file? Gray out the Call
    // button if not — there's nothing to bridge the call to. Fails open (leaves
    // the button enabled) if the check errors, so a flaky check never blocks a
    // legitimately-callable student.
    React.useEffect(() => {
      if (!isInstructor || !conversation.id || !(window.MaskedCalls && window.MaskedCalls.db && window.MaskedCalls.db.callEligibility)) return undefined;
      let alive = true;
      window.MaskedCalls.db.callEligibility(conversation.id)
        .then((r) => { if (alive) setStudentCallable(!!(r && r.studentCallable)); })
        .catch(() => { if (alive) setStudentCallable(null); });
      return () => { alive = false; };
    }, [isInstructor, conversation.id]);

    function reset(closeAfter = false) {
      stopDurationTicker();
      setDuration(0);
      setMuted(false);
      setErr('');
      setMode('confirm');
      if (closeAfter) setOpen(false);
    }

    async function placeBrowserCall() {
      setErr(''); setMode('browser-connecting');
      try {
        await window.MaskedCalls.client.startBrowserCall({
          conversationId: conversation.id,
          onRinging:    () => { /* keep "connecting" copy */ },
          onConnect:    () => { setMode('browser-active'); startDurationTicker(); },
          onDisconnect: () => { stopDurationTicker(); reset(true); },
          onError:      (e) => { setErr((e && e.message) || 'Call error'); setMode('error'); stopDurationTicker(); },
        });
      } catch (e) {
        // Browser-audio path failed — fall back to PSTN.
        setMode('pstn-falling-back');
        try {
          await window.MaskedCalls.db.startCall(conversation.id);
          setMode('pstn-placed');
          setTimeout(() => reset(true), 4000);
        } catch (e2) {
          setErr(e2.message || String(e2));
          setMode('error');
        }
      }
    }

    function hangUp() {
      window.MaskedCalls.client.hangUpBrowserCall();
      stopDurationTicker();
      reset(true);
    }

    function toggleMute() {
      const next = !muted;
      window.MaskedCalls.client.muteBrowserCall(next);
      setMuted(next);
    }

    // Gray out for the teacher when the student has no phone on file yet.
    const blocked = isInstructor && studentCallable === false;

    return (
      <React.Fragment>
        <button
          type="button"
          disabled={blocked}
          title={blocked ? "This student hasn't added a phone number yet — add it from the admin dashboard." : undefined}
          onClick={() => { if (blocked) return; setOpen(true); reset(false); }}
          style={{
            display: 'inline-flex', alignItems: 'center', gap: 6,
            padding: '6px 12px', borderRadius: 6,
            background: blocked ? 'oklch(88% 0.01 265)' : PRIMARY,
            color: blocked ? 'oklch(55% 0.02 265)' : '#fff',
            border: 'none', cursor: blocked ? 'not-allowed' : 'pointer',
            fontSize: 13, fontWeight: 600,
            fontFamily: "'Plus Jakarta Sans', sans-serif",
          }}
          onMouseEnter={(e) => { if (!blocked) e.currentTarget.style.background = PRIMARY_HOVER; }}
          onMouseLeave={(e) => { if (!blocked) e.currentTarget.style.background = PRIMARY; }}
        >
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true">
            <path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.37 1.9.72 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.9.35 1.85.59 2.81.72A2 2 0 0 1 22 16.92Z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
          </svg>
          Call
        </button>

        {open && (
          <div role="dialog" aria-modal="true"
            style={{
              position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.45)',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              zIndex: 5000, padding: 16,
              fontFamily: "'Plus Jakarta Sans', sans-serif",
            }}
            onClick={(e) => {
              if (e.target !== e.currentTarget) return;
              // Refuse to dismiss while a call is connecting / active
              if (mode === 'browser-connecting' || mode === 'browser-active' || mode === 'pstn-falling-back') return;
              setOpen(false);
            }}
          >
            <div style={{
              background: '#fff', borderRadius: 12, padding: 24,
              maxWidth: 420, width: '100%',
              boxShadow: '0 12px 40px rgba(0,0,0,0.2)',
            }}>
              {mode === 'confirm' && (
                <React.Fragment>
                  <div style={{ fontSize: 18, fontWeight: 700, color: 'oklch(22% 0.06 265)', marginBottom: 8 }}>
                    Call {otherLabel}?
                  </div>
                  <div style={{ fontSize: 14, color: 'oklch(40% 0.04 265)', marginBottom: 16, lineHeight: 1.5 }}>
                    Your browser will ask for microphone access, then we ring {otherLabel}'s
                    phone. Your phone won't ring. Neither side sees the other's real number.
                  </div>
                  <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
                    <button type="button" onClick={() => setOpen(false)} style={cancelBtnStyle()}>Cancel</button>
                    <button type="button" onClick={placeBrowserCall} style={primaryBtnStyle()}>Call now</button>
                  </div>
                </React.Fragment>
              )}

              {mode === 'browser-connecting' && (
                <React.Fragment>
                  <div style={{ fontSize: 18, fontWeight: 700, color: 'oklch(22% 0.06 265)', marginBottom: 8 }}>
                    Connecting…
                  </div>
                  <div style={{ fontSize: 14, color: 'oklch(40% 0.04 265)', marginBottom: 16, lineHeight: 1.5 }}>
                    Asking for microphone access and ringing {otherLabel}.
                  </div>
                </React.Fragment>
              )}

              {mode === 'browser-active' && (
                <React.Fragment>
                  <div style={{ fontSize: 18, fontWeight: 700, color: 'oklch(22% 0.06 265)', marginBottom: 4 }}>
                    On call with {otherLabel}
                  </div>
                  <div style={{ fontSize: 28, fontWeight: 700, color: 'oklch(36% 0.13 145)', marginBottom: 16, fontVariantNumeric: 'tabular-nums' }}>
                    {fmtDuration(duration)}
                  </div>
                  <div style={{ display: 'flex', gap: 8, justifyContent: 'space-between', alignItems: 'center' }}>
                    <button type="button" onClick={toggleMute} style={{
                      padding: '10px 16px', borderRadius: 6,
                      border: '1px solid oklch(86% 0.02 265)',
                      background: muted ? 'oklch(94% 0.06 80)' : '#fff',
                      cursor: 'pointer', fontSize: 14,
                      color: muted ? 'oklch(40% 0.15 80)' : 'oklch(35% 0.04 265)',
                      fontFamily: 'inherit', fontWeight: 600,
                    }}>{muted ? 'Muted — tap to unmute' : 'Mute'}</button>
                    <button type="button" onClick={hangUp} style={{
                      padding: '10px 20px', borderRadius: 6,
                      border: 'none', background: 'oklch(60% 0.20 25)', color: '#fff',
                      cursor: 'pointer', fontSize: 14, fontWeight: 700,
                      fontFamily: 'inherit',
                    }}>Hang up</button>
                  </div>
                </React.Fragment>
              )}

              {mode === 'pstn-falling-back' && (
                <React.Fragment>
                  <div style={{ fontSize: 18, fontWeight: 700, color: 'oklch(22% 0.06 265)', marginBottom: 8 }}>
                    Falling back to phone call…
                  </div>
                  <div style={{ fontSize: 14, color: 'oklch(40% 0.04 265)', marginBottom: 16, lineHeight: 1.5 }}>
                    Browser audio is unavailable. Calling your phone, then {otherLabel}.
                  </div>
                </React.Fragment>
              )}

              {mode === 'pstn-placed' && (
                <React.Fragment>
                  <div style={{ fontSize: 18, fontWeight: 700, color: 'oklch(22% 0.06 265)', marginBottom: 8 }}>
                    Calling…
                  </div>
                  <div style={{
                    padding: 10, borderRadius: 6,
                    background: 'oklch(96% 0.06 145)', color: 'oklch(36% 0.13 145)',
                    fontSize: 13, marginBottom: 12,
                  }}>
                    Your phone will ring first. When you answer, we&rsquo;ll ring {otherLabel}.
                  </div>
                </React.Fragment>
              )}

              {mode === 'error' && (
                <React.Fragment>
                  <div style={{ fontSize: 18, fontWeight: 700, color: 'oklch(40% 0.15 25)', marginBottom: 8 }}>
                    Couldn&rsquo;t place the call
                  </div>
                  <div style={{
                    padding: 10, borderRadius: 6,
                    background: 'oklch(96% 0.06 25)', color: 'oklch(40% 0.15 25)',
                    fontSize: 13, marginBottom: 16,
                  }}>{err || 'Unknown error'}</div>
                  <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
                    <button type="button" onClick={() => reset(true)} style={cancelBtnStyle()}>Close</button>
                    <button type="button" onClick={placeBrowserCall} style={primaryBtnStyle()}>Try again</button>
                  </div>
                </React.Fragment>
              )}
            </div>
          </div>
        )}
      </React.Fragment>
    );
  }

  function cancelBtnStyle() {
    return {
      padding: '8px 16px', borderRadius: 6,
      border: '1px solid oklch(86% 0.02 265)', background: '#fff',
      cursor: 'pointer', fontSize: 14, color: 'oklch(35% 0.04 265)',
      fontFamily: 'inherit',
    };
  }
  function primaryBtnStyle() {
    return {
      padding: '8px 16px', borderRadius: 6,
      border: 'none', background: 'oklch(50% 0.18 250)', color: '#fff',
      cursor: 'pointer', fontSize: 14, fontWeight: 600,
      fontFamily: 'inherit',
    };
  }

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