// ═══════════════════════════════════════════════════════════════════
//  app/j/[token]/page.tsx  — GUEST JOIN with pre-join green room
//
//  Flow:  open link → see invite → enter name + "Continue"
//         → PRE-JOIN green room (camera/mic pick + preview)
//         → join the meeting
//
//  Place at TOP LEVEL of app/. Exclude /j/ from login middleware.
// ═══════════════════════════════════════════════════════════════════
'use client';

import React, { useCallback, useEffect, useState } from 'react';
import { useParams } from 'next/navigation';
import {
  peekInvite, redeemInvite, resendInviteOtp,
  type InvitePeek, type InviteRedeemResult,
} from '@/lib/api/meeting-invites';
import MeetingRoom from '@/components/meeting/MeetingRoom';
import PreJoin, { PreJoinResult } from '@/components/meeting/PreJoin';

const TEAL = '#4a0080';
const TEAL_LT = '#7c3aed';
const API_BASE = process.env.NEXT_PUBLIC_API_URL || '';
const SOCKET_URL = API_BASE.replace(/\/api\/?$/, '');

export default function InviteJoinPage() {
  const params = useParams<{ token: string }>();
  const token = String(params?.token ?? '');

  const [invite, setInvite] = useState<InvitePeek | null>(null);
  const [loading, setLoading] = useState(true);
  const [loadError, setLoadError] = useState<string | null>(null);

  const [otp, setOtp] = useState('');
  const [name, setName] = useState('');
  const [joining, setJoining] = useState(false);
  const [joinError, setJoinError] = useState<string | null>(null);
  const [resendMsg, setResendMsg] = useState<string | null>(null);
  const [joined, setJoined] = useState<InviteRedeemResult | null>(null);

  // pre-join device choices (set after redeem, before entering room)
  const [choice, setChoice] = useState<PreJoinResult | null>(null);

  const load = useCallback(async () => {
    if (!token) return;
    setLoading(true); setLoadError(null);
    try {
      const data = await peekInvite(token);
      setInvite(data);
      if (data.recipient_name) setName((n) => n || data.recipient_name || '');
      if (data.otp_expired) setResendMsg('Your passcode has expired — tap resend to get a new one.');
    } catch (e) {
      setLoadError((e as Error)?.message || 'This invite could not be opened.');
    } finally { setLoading(false); }
  }, [token]);

  useEffect(() => { load(); }, [load]);

  const otpRequestedByServer = !!joinError && /passcode|otp|code/i.test(joinError);
  const otpRequired = !!invite?.requires_otp || !!invite?.otp_expired || otpRequestedByServer;
  const showOtpField = !!invite && !invite.requires_login;

  const onContinue = async () => {
    if (!invite) return;
    if (otpRequired && otp.trim().length < 4) { setJoinError('Enter the passcode from your invitation.'); return; }
    setJoining(true); setJoinError(null);
    try {
      const result = await redeemInvite(token, {
        otp: otp.trim() ? otp.trim() : undefined,
        display_name: name.trim() || undefined,
      });
      setJoined(result);   // → now show the pre-join green room
    } catch (e) {
      setJoinError((e as Error)?.message || 'Could not verify that passcode. Please check it and try again.');
    } finally { setJoining(false); }
  };

  const onResend = async () => {
    setResendMsg(null);
    try { const r = await resendInviteOtp(token); setResendMsg(`A new passcode has been sent to ${r.sent_to}.`); setOtp(''); }
    catch (e) { setResendMsg((e as Error)?.message || 'Could not resend the passcode.'); }
  };

  // ── STEP 3: verified + device chosen → enter the meeting ──
  if (joined && joined.token && joined.room_code && choice) {
    return (
      <MeetingRoom
        socketUrl={SOCKET_URL}
        roomId={joined.room_code}
        token={joined.token}
        displayName={choice.displayName || joined.display_name || name || 'Guest'}
        role={(joined.grant_role || 'client').toLowerCase()}
        title={invite?.meeting?.title || 'Meeting'}
        audioDeviceId={choice.audioDeviceId}
        videoDeviceId={choice.videoDeviceId}
        startMuted={!choice.micOn}
        startCamOff={!choice.camOn}
      />
    );
  }

  // ── STEP 2: verified, not yet in room → PRE-JOIN green room ──
  if (joined && joined.token && joined.room_code && !choice) {
    return (
      <PreJoin
        title="Ready to join?"
        roomCode={joined.room_code}
        defaultName={joined.display_name || name || 'Guest'}
        onJoin={setChoice}
      />
    );
  }

  // ── STEP 1: invite details + name/passcode form ──
  return (
    <div style={shell}>
      <div style={card}>
        <div style={band}>
          <div style={{ fontSize: 16, fontWeight: 700 }}>Quality Registrar Systems</div>
          <div style={{ fontSize: 12, opacity: 0.9 }}>Meeting invitation</div>
        </div>
        <div style={{ padding: 24 }}>
          {loading && <p style={{ color: '#6b7280', fontSize: 14 }}>Opening your invitation…</p>}

          {!loading && loadError && (
            <div>
              <h2 style={{ margin: '0 0 8px', fontSize: 18, color: '#111827' }}>This invitation can’t be opened</h2>
              <p style={{ margin: '0 0 16px', fontSize: 14, color: '#6b7280', lineHeight: 1.6 }}>{loadError} Ask the host to send a new invitation.</p>
              <button onClick={load} style={btnGhost}>Try again</button>
            </div>
          )}

          {!loading && invite && (
            <>
              <p style={{ margin: '0 0 4px', fontSize: 14, color: '#111827' }}>{invite.recipient_name ? `Dear ${invite.recipient_name},` : 'Hello,'}</p>
              <p style={{ margin: '0 0 16px', fontSize: 14, color: '#374151', lineHeight: 1.6 }}>
                You have been invited to join an online meeting{invite.meeting.company ? ' for ' : '.'}
                {invite.meeting.company && <strong>{invite.meeting.company}</strong>}
              </p>

              <div style={summaryBox}>
                <Row label="Meeting" value={invite.meeting.title} />
                <Row label="Host" value={invite.meeting.host} />
                <Row label="Meeting ID" value={invite.meeting.room_code} mono />
              </div>

              {invite.requires_login ? (
                <p style={{ fontSize: 13, color: '#b45309', background: '#fffbeb', border: '1px solid #fde68a', borderRadius: 8, padding: '10px 12px', lineHeight: 1.5 }}>
                  This invitation is tied to a QRS account. Please sign in with your QRS login to join.
                </p>
              ) : (
                <>
                  <label style={labelStyle}>Your name</label>
                  <input value={name} onChange={(e) => setName(e.target.value)} placeholder="Your name" style={inputStyle} />

                  {showOtpField && (
                    <>
                      <label style={labelStyle}>Passcode{otpRequired ? '' : ' (if you were given one)'}</label>
                      <input value={otp} onChange={(e) => setOtp(e.target.value.replace(/\s/g, ''))} placeholder="Enter the passcode" inputMode="numeric" style={{ ...inputStyle, letterSpacing: 4, fontSize: 18 }} />
                      <button onClick={onResend} style={linkBtn} type="button">Didn’t get it? Resend passcode</button>
                      {resendMsg && <p style={{ fontSize: 12, color: TEAL, margin: '4px 0 0' }}>{resendMsg}</p>}
                    </>
                  )}

                  {joinError && <p style={{ fontSize: 13, color: '#dc2626', margin: '10px 0 0' }}>{joinError}</p>}

                  <button onClick={onContinue} disabled={joining || !name.trim()} style={{ ...btnPrimary, opacity: (joining || !name.trim()) ? 0.6 : 1 }}>
                    {joining ? 'Verifying…' : 'Continue'}
                  </button>
                </>
              )}
            </>
          )}
        </div>
      </div>
    </div>
  );
}

function Row({ label, value, mono }: { label: string; value?: string | null; mono?: boolean }) {
  if (!value) return null;
  return (
    <div style={{ display: 'flex', gap: 12, padding: '5px 0' }}>
      <span style={{ width: 96, flex: 'none', fontSize: 12, color: '#6b7280' }}>{label}</span>
      <span style={{ fontSize: 13, fontWeight: 600, color: '#111827', fontFamily: mono ? 'ui-monospace, monospace' : 'inherit', letterSpacing: mono ? 1 : 0 }}>{value}</span>
    </div>
  );
}

const shell: React.CSSProperties = { minHeight: '100vh', background: '#f1f5f9', display: 'flex', alignItems: 'flex-start', justifyContent: 'center', padding: '48px 16px', fontFamily: 'system-ui, sans-serif' };
const card: React.CSSProperties = { width: '100%', maxWidth: 480, background: '#fff', borderRadius: 16, overflow: 'hidden', border: '1px solid #e2e8f0', boxShadow: '0 10px 30px rgba(15,23,42,0.08)' };
const band: React.CSSProperties = { background: `linear-gradient(135deg, ${TEAL} 0%, ${TEAL_LT} 100%)`, color: '#fff', padding: '20px 24px' };
const summaryBox: React.CSSProperties = { background: '#f8fafc', border: '1px solid #e2e8f0', borderRadius: 12, padding: '12px 16px', marginBottom: 16 };
const labelStyle: React.CSSProperties = { display: 'block', fontSize: 12, color: '#6b7280', margin: '10px 0 4px', fontWeight: 600 };
const inputStyle: React.CSSProperties = { width: '100%', padding: '10px 12px', borderRadius: 8, border: '1px solid #cbd5e1', fontSize: 14, color: '#111827', outline: 'none', boxSizing: 'border-box' };
const btnPrimary: React.CSSProperties = { width: '100%', marginTop: 16, padding: '12px', borderRadius: 10, border: 'none', background: `linear-gradient(135deg, ${TEAL} 0%, ${TEAL_LT} 100%)`, color: '#fff', fontSize: 15, fontWeight: 700, cursor: 'pointer' };
const btnGhost: React.CSSProperties = { padding: '9px 16px', borderRadius: 8, border: '1px solid #cbd5e1', background: '#fff', color: '#374151', fontSize: 14, fontWeight: 600, cursor: 'pointer' };
const linkBtn: React.CSSProperties = { background: 'none', border: 'none', color: TEAL, fontSize: 12, fontWeight: 600, cursor: 'pointer', padding: '6px 0 0' };