// Fluentra Console v2 — app shell with auth, login, tenant selector & router.

const AuthCtx = React.createContext({});
window._AuthCtx = AuthCtx;
window.useAuth = () => React.useContext(AuthCtx);

function getPasswordStrength(pw) {
  let score = 0;
  if (pw.length >= 8) score++;
  if (/[A-Z]/.test(pw)) score++;
  if (/[a-z]/.test(pw)) score++;
  if (/[0-9]/.test(pw)) score++;
  if (/[^A-Za-z0-9]/.test(pw)) score++;
  const labels = ['Very weak','Weak','Medium','Strong','Very strong'];
  const colors = ['#F87171','#F87171','#FBBF24','#34D399','#34D399'];
  return { score, label: labels[score-1] || '', color: colors[score-1] || 'transparent' };
}

/* ══════════════════════════════════════════════════════════════
   FORGOT PASSWORD PAGE
   ══════════════════════════════════════════════════════════ */
function ForgotPasswordPage() {
  const [email, setEmail] = React.useState('');
  const [loading, setLoading] = React.useState(false);
  const [sent, setSent] = React.useState(false);
  const [error, setError] = React.useState('');

  const submit = async (e) => {
    e.preventDefault();
    setLoading(true); setError('');
    try {
      const res = await fetch(window.FLUENTRA_API + '/api/v1/users/forgot-password', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email }),
        credentials: 'include',
      });
      if (!res.ok) {
        const e2 = await res.json().catch(() => ({}));
        throw new Error(e2.detail || 'Request failed');
      }
      setSent(true);
    } catch(err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div style={{display:'flex',alignItems:'center',justifyContent:'center',minHeight:'100vh',background:'var(--bg)',fontFamily:"'Geist',sans-serif"}}>
      <div style={{position:'fixed',inset:0,pointerEvents:'none',
        backgroundImage:'linear-gradient(to right,rgba(255,255,255,.035) 1px,transparent 1px),linear-gradient(to bottom,rgba(255,255,255,.035) 1px,transparent 1px)',
        backgroundSize:'56px 56px',
        maskImage:'radial-gradient(ellipse 80% 80% at 50% 50%,#000 30%,transparent 100%)',
        WebkitMaskImage:'radial-gradient(ellipse 80% 80% at 50% 50%,#000 30%,transparent 100%)'}}/>
      <div style={{position:'fixed',top:'30%',left:'50%',transform:'translateX(-50%)',width:600,height:400,
        background:'radial-gradient(ellipse at center,rgba(99,102,241,.12) 0%,transparent 70%)',pointerEvents:'none'}}/>

      <div style={{width:'100%',maxWidth:400,padding:'0 20px',position:'relative',zIndex:1}}>
        <div style={{textAlign:'center',marginBottom:32}}>
          <div style={{display:'inline-flex',alignItems:'center',gap:10,marginBottom:8}}>
            <span style={{width:32,height:32,borderRadius:9,background:'linear-gradient(140deg,var(--primary) 0%,var(--accent) 100%)',display:'inline-block',boxShadow:'0 4px 20px -4px rgba(99,102,241,.6)'}}/>
            <span style={{fontSize:20,fontWeight:600,letterSpacing:'-.015em'}}>Fluentra</span>
          </div>
          <p style={{margin:0,color:'var(--ink-dim)',fontSize:14}}>Reset your password</p>
        </div>

        {sent ? (
          <div style={{background:'linear-gradient(180deg,var(--surface) 0%,var(--bg-2) 100%)',border:'1px solid var(--line-2)',borderRadius:16,padding:28,boxShadow:'0 40px 80px -20px rgba(0,0,0,.6)',textAlign:'center'}}>
            <p style={{margin:0,color:'var(--ink-dim)',fontSize:14,lineHeight:1.5}}>
              If an account exists for <b>{email}</b>, you will receive a password reset link.
            </p>
            <button onClick={()=>{window.location.hash='';}} className="btn btn-accent" style={{marginTop:20,width:'100%'}}>
              Back to sign in
            </button>
          </div>
        ) : (
          <form onSubmit={submit} style={{background:'linear-gradient(180deg,var(--surface) 0%,var(--bg-2) 100%)',border:'1px solid var(--line-2)',borderRadius:16,padding:28,boxShadow:'0 40px 80px -20px rgba(0,0,0,.6)'}}>
            {error && (
              <div style={{padding:'10px 14px',borderRadius:10,marginBottom:18,background:'rgba(248,113,113,.08)',border:'1px solid rgba(248,113,113,.25)',color:'var(--danger)',fontSize:13,display:'flex',alignItems:'center',gap:8}}>
                <I name="warn" size={14}/>{error}
              </div>
            )}
            <div className="field" style={{marginBottom:16}}>
              <label>Email</label>
              <input className="input" type="email" required autoFocus placeholder="you@example.com" value={email} onChange={e=>setEmail(e.target.value)}/>
            </div>
            <button type="submit" className="btn btn-accent" disabled={loading} style={{width:'100%',height:42,fontSize:15,justifyContent:'center'}}>
              {loading ? 'Sending…' : 'Send reset link →'}
            </button>
            <p style={{margin:'18px 0 0',textAlign:'center',fontSize:12.5,color:'var(--ink-faint)'}}>
              <a onClick={()=>{window.location.hash='';}} style={{color:'var(--accent-2)',borderBottom:'1px dashed currentColor',cursor:'pointer'}}>Back to sign in</a>
            </p>
          </form>
        )}
      </div>
    </div>
  );
}

/* ══════════════════════════════════════════════════════════════
   RESET PASSWORD PAGE
   ══════════════════════════════════════════════════════════ */
function ResetPasswordPage() {
  const [password, setPassword] = React.useState('');
  const [loading, setLoading] = React.useState(false);
  const [done, setDone] = React.useState(false);
  const [error, setError] = React.useState('');

  const token = new URLSearchParams(window.location.search).get('token');

  const submit = async (e) => {
    e.preventDefault();
    setLoading(true); setError('');
    try {
      const res = await fetch(window.FLUENTRA_API + '/api/v1/users/reset-password', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ token, new_password: password }),
        credentials: 'include',
      });
      if (!res.ok) {
        const e2 = await res.json().catch(() => ({}));
        throw new Error(e2.detail || 'Reset failed');
      }
      setDone(true);
    } catch(err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div style={{display:'flex',alignItems:'center',justifyContent:'center',minHeight:'100vh',background:'var(--bg)',fontFamily:"'Geist',sans-serif"}}>
      <div style={{position:'fixed',inset:0,pointerEvents:'none',
        backgroundImage:'linear-gradient(to right,rgba(255,255,255,.035) 1px,transparent 1px),linear-gradient(to bottom,rgba(255,255,255,.035) 1px,transparent 1px)',
        backgroundSize:'56px 56px',
        maskImage:'radial-gradient(ellipse 80% 80% at 50% 50%,#000 30%,transparent 100%)',
        WebkitMaskImage:'radial-gradient(ellipse 80% 80% at 50% 50%,#000 30%,transparent 100%)'}}/>
      <div style={{position:'fixed',top:'30%',left:'50%',transform:'translateX(-50%)',width:600,height:400,
        background:'radial-gradient(ellipse at center,rgba(99,102,241,.12) 0%,transparent 70%)',pointerEvents:'none'}}/>

      <div style={{width:'100%',maxWidth:400,padding:'0 20px',position:'relative',zIndex:1}}>
        <div style={{textAlign:'center',marginBottom:32}}>
          <div style={{display:'inline-flex',alignItems:'center',gap:10,marginBottom:8}}>
            <span style={{width:32,height:32,borderRadius:9,background:'linear-gradient(140deg,var(--primary) 0%,var(--accent) 100%)',display:'inline-block',boxShadow:'0 4px 20px -4px rgba(99,102,241,.6)'}}/>
            <span style={{fontSize:20,fontWeight:600,letterSpacing:'-.015em'}}>Fluentra</span>
          </div>
          <p style={{margin:0,color:'var(--ink-dim)',fontSize:14}}>Set a new password</p>
        </div>

        {done ? (
          <div style={{background:'linear-gradient(180deg,var(--surface) 0%,var(--bg-2) 100%)',border:'1px solid var(--line-2)',borderRadius:16,padding:28,boxShadow:'0 40px 80px -20px rgba(0,0,0,.6)',textAlign:'center'}}>
            <p style={{margin:0,color:'var(--ink-dim)',fontSize:14,lineHeight:1.5}}>
              Your password has been updated successfully.
            </p>
            <button onClick={()=>{window.location.hash='';window.location.search='';}} className="btn btn-accent" style={{marginTop:20,width:'100%'}}>
              Sign in
            </button>
          </div>
        ) : (
          <form onSubmit={submit} style={{background:'linear-gradient(180deg,var(--surface) 0%,var(--bg-2) 100%)',border:'1px solid var(--line-2)',borderRadius:16,padding:28,boxShadow:'0 40px 80px -20px rgba(0,0,0,.6)'}}>
            {error && (
              <div style={{padding:'10px 14px',borderRadius:10,marginBottom:18,background:'rgba(248,113,113,.08)',border:'1px solid rgba(248,113,113,.25)',color:'var(--danger)',fontSize:13,display:'flex',alignItems:'center',gap:8}}>
                <I name="warn" size={14}/>{error}
              </div>
            )}
            {!token && (
              <div style={{padding:'10px 14px',borderRadius:10,marginBottom:18,background:'rgba(248,113,113,.08)',border:'1px solid rgba(248,113,113,.25)',color:'var(--danger)',fontSize:13}}>
                Missing reset token in URL.
              </div>
            )}
            <div className="field" style={{marginBottom:22}}>
              <label>New Password</label>
              <input className="input" type="password" required autoFocus placeholder="••••••••" value={password} onChange={e=>setPassword(e.target.value)}/>
            </div>
            <button type="submit" className="btn btn-accent" disabled={loading || !token} style={{width:'100%',height:42,fontSize:15,justifyContent:'center'}}>
              {loading ? 'Updating…' : 'Update password →'}
            </button>
            <p style={{margin:'18px 0 0',textAlign:'center',fontSize:12.5,color:'var(--ink-faint)'}}>
              <a onClick={()=>{window.location.hash='';window.location.search='';}} style={{color:'var(--accent-2)',borderBottom:'1px dashed currentColor',cursor:'pointer'}}>Back to sign in</a>
            </p>
          </form>
        )}
      </div>
    </div>
  );
}

/* ══════════════════════════════════════════════════════════════
   LOGIN PAGE
   ══════════════════════════════════════════════════════════ */
function LoginPage({ onLogin }) {
  const [mode, setMode] = React.useState('login');
  const [username, setUsername] = React.useState('');
  const [email, setEmail]       = React.useState('');
  const [password, setPassword] = React.useState('');
  const [confirmPassword, setConfirmPassword] = React.useState('');
  const [tenantName, setTenantName] = React.useState('');
  const [loading, setLoading]   = React.useState(false);
  const [error, setError]       = React.useState('');
  const [message, setMessage]   = React.useState('');
  const strength = getPasswordStrength(password);

  // Check for invitation token in URL
  const urlParams = React.useMemo(() => new URLSearchParams(window.location.search), []);
  const invitationId = urlParams.get('invitation');

  const submit = async (e) => {
    e.preventDefault();
    setLoading(true); setError(''); setMessage('');
    try {
      if (mode === 'register') {
        if (password !== confirmPassword) {
          throw new Error('Passwords do not match');
        }
        const payload = { username, email, password };
        if (invitationId) {
          payload.invitation_id = invitationId;
        } else if (tenantName.trim()) {
          payload.tenant_name = tenantName.trim();
        }
        const res = await fetch(window.FLUENTRA_API + '/api/v1/users/register', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(payload),
          credentials: 'include',
        });
        if (!res.ok) {
          const e2 = await res.json().catch(() => ({}));
          throw new Error(e2.detail || 'Registration failed');
        }
        const data = await res.json().catch(() => ({}));
        if (invitationId) {
          setMessage('Account created and invitation accepted! You can now sign in.');
        } else if (data.tenant_request_id) {
          setMessage('Account created! Your tenant request has been submitted for approval. You can now sign in.');
        } else {
          setMessage('Account created! You can now sign in.');
        }
        setMode('login');
        setPassword('');
        setConfirmPassword('');
        setTenantName('');
      } else {
        // OAuth2 form login (cookie is set automatically by backend)
        const tr = await fetch(window.FLUENTRA_API + '/api/v1/users/token', {
          method: 'POST',
          headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
          body: 'username=' + encodeURIComponent(email) + '&password=' + encodeURIComponent(password),
          credentials: 'include',
        });
        if (!tr.ok) {
          const e2 = await tr.json().catch(() => ({}));
          throw new Error(e2.detail || 'Invalid credentials');
        }

        // Fetch /me + tenants in parallel (cookie sends token automatically)
        const [meRes, tenantsRes] = await Promise.all([
          fetch(window.FLUENTRA_API + '/api/v1/users/me',          { credentials: 'include' }),
          fetch(window.FLUENTRA_API + '/api/v1/users/me/tenants',  { credentials: 'include' }),
        ]);
        const user    = await meRes.json();
        const tenants = await tenantsRes.json().catch(() => []);

        let activeTenantId = user.active_tenant_id;

        // Auto-switch if single tenant and no active tenant yet
        if (!activeTenantId && Array.isArray(tenants) && tenants.length === 1) {
          const sr = await fetch(window.FLUENTRA_API + '/api/v1/users/me/tenants/switch', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ tenant_id: tenants[0].tenant_id }),
            credentials: 'include',
          });
          if (sr.ok) {
            activeTenantId = tenants[0].tenant_id;
          }
        }

        const stored = { ...user, active_tenant_id: activeTenantId, tenants: Array.isArray(tenants) ? tenants : [] };
        localStorage.setItem('fluentra_user', JSON.stringify(stored));
        onLogin(stored);
      }
    } catch(err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div style={{display:'flex',alignItems:'center',justifyContent:'center',minHeight:'100vh',background:'var(--bg)',fontFamily:"'Geist',sans-serif"}}>
      {/* grid bg */}
      <div style={{position:'fixed',inset:0,pointerEvents:'none',
        backgroundImage:'linear-gradient(to right,rgba(255,255,255,.035) 1px,transparent 1px),linear-gradient(to bottom,rgba(255,255,255,.035) 1px,transparent 1px)',
        backgroundSize:'56px 56px',
        maskImage:'radial-gradient(ellipse 80% 80% at 50% 50%,#000 30%,transparent 100%)',
        WebkitMaskImage:'radial-gradient(ellipse 80% 80% at 50% 50%,#000 30%,transparent 100%)'}}/>
      <div style={{position:'fixed',top:'30%',left:'50%',transform:'translateX(-50%)',width:600,height:400,
        background:'radial-gradient(ellipse at center,rgba(99,102,241,.12) 0%,transparent 70%)',pointerEvents:'none'}}/>

      <div style={{width:'100%',maxWidth:400,padding:'0 20px',position:'relative',zIndex:1}}>
        {/* Logo */}
        <div style={{textAlign:'center',marginBottom:32}}>
          <div style={{display:'inline-flex',alignItems:'center',gap:10,marginBottom:8}}>
            <span style={{width:32,height:32,borderRadius:9,background:'linear-gradient(140deg,var(--primary) 0%,var(--accent) 100%)',display:'inline-block',boxShadow:'0 4px 20px -4px rgba(99,102,241,.6)'}}/>
            <span style={{fontSize:20,fontWeight:600,letterSpacing:'-.015em'}}>Fluentra</span>
          </div>
          <p style={{margin:0,color:'var(--ink-dim)',fontSize:14}}>
            {mode === 'register'
              ? (invitationId ? 'Create your account to join the team' : 'Create your account')
              : 'Sign in to your console'}
          </p>
        </div>

        <form onSubmit={submit} style={{background:'linear-gradient(180deg,var(--surface) 0%,var(--bg-2) 100%)',border:'1px solid var(--line-2)',borderRadius:16,padding:28,boxShadow:'0 40px 80px -20px rgba(0,0,0,.6)'}}>
          {message && (
            <div style={{padding:'10px 14px',borderRadius:10,marginBottom:18,background:'rgba(34,211,238,.08)',border:'1px solid rgba(34,211,238,.25)',color:'var(--accent-2)',fontSize:13,display:'flex',alignItems:'center',gap:8}}>
              <I name="info" size={14}/>{message}
            </div>
          )}
          {error && (
            <div style={{padding:'10px 14px',borderRadius:10,marginBottom:18,background:'rgba(248,113,113,.08)',border:'1px solid rgba(248,113,113,.25)',color:'var(--danger)',fontSize:13,display:'flex',alignItems:'center',gap:8}}>
              <I name="warn" size={14}/>{error}
            </div>
          )}
          {mode === 'register' && (
            <div className="field" style={{marginBottom:16}}>
              <label>Username</label>
              <input className="input" type="text" required placeholder="johndoe" value={username} onChange={e=>setUsername(e.target.value)}/>
            </div>
          )}
          <div className="field" style={{marginBottom:16}}>
            <label>Email</label>
            <input className="input" type="email" required autoFocus={mode==='login'} placeholder="you@example.com" value={email} onChange={e=>setEmail(e.target.value)}/>
          </div>
          <div className="field" style={{marginBottom:mode==='register'?10:22}}>
            <label>Password</label>
            <input className="input" type="password" required placeholder="••••••••" value={password} onChange={e=>setPassword(e.target.value)}/>
            {mode === 'register' && password && (
              <div style={{marginTop:8}}>
                <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginBottom:4}}>
                  <span style={{fontSize:11,color:'var(--ink-dim)'}}>Strength</span>
                  <span style={{fontSize:11,color:strength.color,fontWeight:600}}>{strength.label}</span>
                </div>
                <div style={{height:4,borderRadius:2,background:'rgba(255,255,255,.06)',overflow:'hidden'}}>
                  <div style={{height:'100%',width:(strength.score/5*100)+'%',background:strength.color,transition:'all .2s'}}/>
                </div>
              </div>
            )}
          </div>
          {mode === 'register' && (
            <div className="field" style={{marginBottom:22}}>
              <label>Confirm Password</label>
              <input className="input" type="password" required placeholder="••••••••" value={confirmPassword} onChange={e=>setConfirmPassword(e.target.value)}/>
            </div>
          )}
          {mode === 'register' && !invitationId && (
            <div className="field" style={{marginBottom:22}}>
              <label>Tenant Name <span style={{color:'var(--ink-faint)',fontSize:12}}>(optional — your workspace)</span></label>
              <input className="input" type="text" placeholder="Acme Corp" value={tenantName} onChange={e=>setTenantName(e.target.value)}/>
            </div>
          )}
          <button type="submit" className="btn btn-accent" disabled={loading} style={{width:'100%',height:42,fontSize:15,justifyContent:'center'}}>
            {loading ? (mode === 'register' ? 'Creating account…' : 'Signing in…') : (mode === 'register' ? 'Create account →' : 'Sign in →')}
          </button>
          <p style={{margin:'18px 0 0',textAlign:'center',fontSize:12.5,color:'var(--ink-faint)'}}>
            {mode === 'login' ? (
              <>
                <a onClick={()=>{window.location.hash='#forgot-password';}} style={{color:'var(--accent-2)',borderBottom:'1px dashed currentColor',cursor:'pointer'}}>Forgot password?</a>
                <br style={{marginTop:8,display:'block'}}/>
                Don't have an account? <a onClick={()=>setMode('register')} style={{color:'var(--accent-2)',borderBottom:'1px dashed currentColor',cursor:'pointer'}}>Sign up</a>
              </>
            ) : (
              <>
                Already have an account? <a onClick={()=>setMode('login')} style={{color:'var(--accent-2)',borderBottom:'1px dashed currentColor',cursor:'pointer'}}>Log in</a>
              </>
            )}
          </p>
        </form>
      </div>
    </div>
  );
}

/* ══════════════════════════════════════════════════════════════
   TENANT REQUEST FORM
   ══════════════════════════════════════════════════════════ */
function TenantRequestForm() {
  const [tenantName, setTenantName] = React.useState('');
  const [loading, setLoading] = React.useState(false);
  const [error, setError] = React.useState('');
  const [success, setSuccess] = React.useState('');
  const [requests, setRequests] = React.useState([]);

  const loadRequests = async () => {
    try {
      const res = await fetch(window.FLUENTRA_API + '/api/v1/users/my-tenant-requests', { credentials: 'include' });
      if (res.ok) {
        const data = await res.json();
        setRequests(Array.isArray(data) ? data : []);
      }
    } catch(e) {}
  };

  React.useEffect(() => {
    loadRequests();
  }, []);

  const submit = async (e) => {
    e.preventDefault();
    setLoading(true); setError(''); setSuccess('');
    try {
      const res = await fetch(window.FLUENTRA_API + '/api/v1/users/tenant-request', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ tenant_name: tenantName }),
        credentials: 'include',
      });
      if (!res.ok) {
        const e2 = await res.json().catch(() => ({}));
        throw new Error(e2.detail || 'Request failed');
      }
      setSuccess('Tenant request submitted for approval.');
      setTenantName('');
      loadRequests();
    } catch(err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div style={{textAlign:'left'}}>
      <form onSubmit={submit} style={{background:'linear-gradient(180deg,var(--surface) 0%,var(--bg-2) 100%)',border:'1px solid var(--line-2)',borderRadius:16,padding:24,boxShadow:'0 40px 80px -20px rgba(0,0,0,.6)'}}>
        {success && (
          <div style={{padding:'10px 14px',borderRadius:10,marginBottom:16,background:'rgba(34,211,238,.08)',border:'1px solid rgba(34,211,238,.25)',color:'var(--accent-2)',fontSize:13,display:'flex',alignItems:'center',gap:8}}>
            <I name="info" size={14}/>{success}
          </div>
        )}
        {error && (
          <div style={{padding:'10px 14px',borderRadius:10,marginBottom:16,background:'rgba(248,113,113,.08)',border:'1px solid rgba(248,113,113,.25)',color:'var(--danger)',fontSize:13,display:'flex',alignItems:'center',gap:8}}>
            <I name="warn" size={14}/>{error}
          </div>
        )}
        <div className="field" style={{marginBottom:16}}>
          <label>Tenant Name</label>
          <input className="input" type="text" required placeholder="My Organization" value={tenantName} onChange={e=>setTenantName(e.target.value)}/>
        </div>
        <button type="submit" className="btn btn-accent" disabled={loading} style={{width:'100%',height:40,fontSize:14,justifyContent:'center'}}>
          {loading ? 'Submitting…' : 'Request Tenant →'}
        </button>
      </form>

      {requests.length > 0 && (
        <div style={{marginTop:20}}>
          <h4 style={{fontSize:13,color:'var(--ink-dim)',margin:'0 0 10px',textTransform:'uppercase',letterSpacing:'.04em'}}>My Requests</h4>
          <div style={{display:'flex',flexDirection:'column',gap:8}}>
            {requests.map((r, i) => (
              <div key={i} style={{display:'flex',alignItems:'center',justifyContent:'space-between',padding:'10px 14px',background:'var(--surface)',border:'1px solid var(--line-2)',borderRadius:10}}>
                <span style={{fontSize:14,color:'var(--ink)'}}>{r.tenant_name}</span>
                <span style={{fontSize:12,color:'var(--ink-faint)',textTransform:'capitalize',border:'1px solid var(--line-2)',borderRadius:6,padding:'2px 8px'}}>{r.status}</span>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

/* ══════════════════════════════════════════════════════════════
   TENANT SELECTOR
   ══════════════════════════════════════════════════════════ */
function TenantSelector({ user, tenants, onSelect }) {
  const [loading, setLoading] = React.useState(null);

  const pick = async (tenantId) => {
    setLoading(tenantId);
    try {
      const res = await fetch(window.FLUENTRA_API + '/api/v1/users/me/tenants/switch', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ tenant_id: tenantId }),
        credentials: 'include',
      });
      if (!res.ok) throw new Error('Switch failed');
      const stored = JSON.parse(localStorage.getItem('fluentra_user') || '{}');
      stored.active_tenant_id = tenantId;
      localStorage.setItem('fluentra_user', JSON.stringify(stored));
      onSelect({ ...user, active_tenant_id: tenantId });
    } catch(e) {
      if (window.modalAlert) window.modalAlert('Failed to select tenant: ' + e.message);
      else alert('Failed to select tenant: ' + e.message);
    } finally { setLoading(null); }
  };

  return (
    <div style={{display:'flex',alignItems:'center',justifyContent:'center',minHeight:'100vh',background:'var(--bg)'}}>
      <div style={{width:'100%',maxWidth:480,padding:'0 20px'}}>
        <div style={{textAlign:'center',marginBottom:24}}>
          <div style={{fontSize:18,fontWeight:600,letterSpacing:'-.01em'}}>Select workspace</div>
          <p style={{margin:'4px 0 0',color:'var(--ink-dim)',fontSize:13}}>Choose a tenant to continue</p>
        </div>
        <div style={{display:'flex',flexDirection:'column',gap:10}}>
          {tenants.map(t => (
            <button key={t.tenant_id} onClick={() => pick(t.tenant_id)} disabled={!!loading}
              style={{display:'flex',alignItems:'center',gap:14,padding:'14px 18px',background:'linear-gradient(180deg,var(--surface) 0%,var(--bg-2) 100%)',border:'1px solid var(--line-2)',borderRadius:12,cursor:'pointer',textAlign:'left',transition:'border-color .15s',width:'100%'}}
              onMouseOver={e=>e.currentTarget.style.borderColor='rgba(99,102,241,.5)'}
              onMouseOut={e=>e.currentTarget.style.borderColor='var(--line-2)'}
            >
              <div style={{width:36,height:36,borderRadius:9,flexShrink:0,background:'linear-gradient(140deg,rgba(99,102,241,.3),rgba(34,211,238,.2))',border:'1px solid rgba(99,102,241,.3)',display:'flex',alignItems:'center',justifyContent:'center',color:'var(--accent-2)',fontWeight:700,fontSize:14,fontFamily:'Geist Mono,monospace'}}>
                {(t.tenant_name||'?')[0].toUpperCase()}
              </div>
              <div>
                <div style={{fontWeight:600,fontSize:14,letterSpacing:'-.01em',color:'var(--ink)'}}>{t.tenant_name || t.tenant_id}</div>
                <div style={{color:'var(--ink-faint)',fontSize:11.5,fontFamily:'Geist Mono,monospace',marginTop:2}}>{t.role} · {(t.tenant_id||'').slice(0,8)}…</div>
              </div>
              {loading === t.tenant_id && <span style={{marginLeft:'auto',color:'var(--ink-dim)',fontSize:12}}>…</span>}
            </button>
          ))}
        </div>
        <button onClick={async () => {
            await fetch(window.FLUENTRA_API + '/api/v1/users/logout', { method: 'POST', credentials: 'include' });
            localStorage.removeItem('fluentra_user');
            window.location.reload();
          }}
          style={{display:'block',margin:'20px auto 0',background:'transparent',border:'none',color:'var(--ink-faint)',fontSize:12.5,cursor:'pointer',fontFamily:'Geist,sans-serif'}}>
          Sign out
        </button>
      </div>
    </div>
  );
}

/* ══════════════════════════════════════════════════════════════
   CHANGE PASSWORD MODAL
   ══════════════════════════════════════════════════════════ */
function ChangePasswordModal({ onClose }) {
  const [current, setCurrent] = React.useState('');
  const [next, setNext] = React.useState('');
  const [loading, setLoading] = React.useState(false);
  const [error, setError] = React.useState('');
  const [done, setDone] = React.useState(false);

  const submit = async (e) => {
    e.preventDefault();
    setLoading(true); setError('');
    try {
      const res = await fetch(window.FLUENTRA_API + '/api/v1/users/me/change-password', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ current_password: current, new_password: next }),
        credentials: 'include',
      });
      if (!res.ok) {
        const e2 = await res.json().catch(() => ({}));
        throw new Error(e2.detail || 'Failed to change password');
      }
      setDone(true);
    } catch(err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  if (done) return (
    <div style={{position:'fixed',inset:0,background:'rgba(0,0,0,.5)',display:'flex',alignItems:'center',justifyContent:'center',zIndex:100}} onClick={onClose}>
      <div style={{background:'var(--surface)',border:'1px solid var(--line-2)',borderRadius:16,padding:28,maxWidth:360,width:'90%'}} onClick={e=>e.stopPropagation()}>
        <p style={{margin:0,color:'var(--ink-dim)',fontSize:14}}>Password updated successfully.</p>
        <button className="btn btn-accent" style={{marginTop:16,width:'100%'}} onClick={onClose}>Close</button>
      </div>
    </div>
  );

  return (
    <div style={{position:'fixed',inset:0,background:'rgba(0,0,0,.5)',display:'flex',alignItems:'center',justifyContent:'center',zIndex:100}} onClick={onClose}>
      <form onSubmit={submit} style={{background:'var(--surface)',border:'1px solid var(--line-2)',borderRadius:16,padding:28,maxWidth:360,width:'90%'}} onClick={e=>e.stopPropagation()}>
        <h3 style={{margin:'0 0 16px',fontSize:16}}>Change Password</h3>
        {error && <div style={{padding:'10px 14px',borderRadius:10,marginBottom:16,background:'rgba(248,113,113,.08)',border:'1px solid rgba(248,113,113,.25)',color:'var(--danger)',fontSize:13}}>{error}</div>}
        <div className="field" style={{marginBottom:12}}>
          <label>Current Password</label>
          <input className="input" type="password" required value={current} onChange={e=>setCurrent(e.target.value)}/>
        </div>
        <div className="field" style={{marginBottom:20}}>
          <label>New Password</label>
          <input className="input" type="password" required value={next} onChange={e=>setNext(e.target.value)}/>
        </div>
        <button type="submit" className="btn btn-accent" disabled={loading} style={{width:'100%'}}>{loading ? 'Updating…' : 'Update Password'}</button>
      </form>
    </div>
  );
}

/* ══════════════════════════════════════════════════════════════
   NOTIFICATIONS BELL
   ══════════════════════════════════════════════════════════ */
function NotificationsBell() {
  const [open, setOpen] = React.useState(false);
  const [notifs, setNotifs] = React.useState([]);
  const [unread, setUnread] = React.useState(0);
  const ref = React.useRef(null);

  const load = async () => {
    try {
      const r = await fetch(window.FLUENTRA_API + '/api/v1/users/me/notifications', { credentials: 'include' });
      if (!r.ok) return;
      const data = await r.json();
      const arr = Array.isArray(data) ? data : [];
      setNotifs(arr);
      setUnread(arr.filter(n => !n.read).length);
    } catch(e) {}
  };

  React.useEffect(() => {
    load();
    const iv = setInterval(load, 30000);
    return () => clearInterval(iv);
  }, []);

  React.useEffect(() => {
    const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', h);
    return () => document.removeEventListener('mousedown', h);
  }, []);

  const markOne = async (id) => {
    await fetch(window.FLUENTRA_API + '/api/v1/users/me/notifications/' + id + '/mark-read', { method: 'POST', credentials: 'include' });
    load();
  };

  const markAll = async () => {
    await fetch(window.FLUENTRA_API + '/api/v1/users/me/notifications/mark-all-read', { method: 'POST', credentials: 'include' });
    load();
  };

  return (
    <div ref={ref} style={{position:'relative'}}>
      <button className="icon-btn" title="Notifications" aria-label="Notifications" onClick={()=>{setOpen(v=>!v);load();}} style={{position:'relative'}}>
        <I name="bell" size={15}/>
        {unread > 0 && <span style={{position:'absolute',top:-2,right:-2,background:'var(--danger)',color:'#fff',fontSize:9,fontWeight:700,borderRadius:'50%',width:15,height:15,display:'flex',alignItems:'center',justifyContent:'center'}}>{unread}</span>}
      </button>
      {open && (
        <div style={{position:'absolute',top:'calc(100% + 8px)',right:0,width:340,background:'var(--surface)',border:'1px solid var(--line-2)',borderRadius:12,padding:10,boxShadow:'0 20px 40px -10px rgba(0,0,0,.5)',zIndex:50}}>
          <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',padding:'4px 6px 8px'}}>
            <span style={{fontSize:13,fontWeight:600}}>Notifications</span>
            {unread > 0 && <button className="btn btn-ghost btn-sm" onClick={markAll} style={{fontSize:11}}>Mark all read</button>}
          </div>
          <div style={{maxHeight:320,overflow:'auto'}}>
            {notifs.length === 0 ? <div style={{padding:12,fontSize:12,color:'var(--ink-faint)',textAlign:'center'}}>No notifications</div> : (
              notifs.map(n => (
                <div key={n.id} onClick={()=>markOne(n.id)} style={{padding:'8px 10px',borderRadius:8,cursor:'pointer',background:n.read?'transparent':'rgba(99,102,241,.06)',marginBottom:4,transition:'background .15s'}}>
                  <div style={{fontSize:12,color:'var(--ink)',lineHeight:1.4}}>{n.message||n.title||'Notification'}</div>
                  <div style={{fontSize:10,color:'var(--ink-faint)',marginTop:3}}>{n.created_at ? new Date(n.created_at).toLocaleString() : ''}</div>
                </div>
              ))
            )}
          </div>
        </div>
      )}
    </div>
  );
}

/* ══════════════════════════════════════════════════════════════
   INVITATIONS PANEL
   ══════════════════════════════════════════════════════════ */
function InvitationsPanel() {
  const [invites, setInvites] = React.useState([]);
  const [busy, setBusy] = React.useState(false);

  const load = async () => {
    try {
      const r = await fetch(window.FLUENTRA_API + '/api/v1/users/me/invitations', { credentials: 'include' });
      if (!r.ok) return;
      const data = await r.json();
      setInvites(Array.isArray(data) ? data : []);
    } catch(e) {}
  };

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

  const respond = async (id, action) => {
    setBusy(true);
    try {
      const r = await fetch(window.FLUENTRA_API + '/api/v1/invitations/' + id + '/' + action, { method: 'POST', credentials: 'include' });
      if (!r.ok) throw new Error('Failed');
      if (action === 'accept') {
        const tenantsRes = await fetch(window.FLUENTRA_API + '/api/v1/users/me/tenants', { credentials: 'include' });
        const tenants = await tenantsRes.json().catch(() => []);
        const stored = JSON.parse(localStorage.getItem('fluentra_user') || '{}');
        stored.tenants = Array.isArray(tenants) ? tenants : [];
        const inv = invites.find(i => i.id === id);
        if (inv && inv.tenant_id) {
          stored.active_tenant_id = inv.tenant_id;
          await fetch(window.FLUENTRA_API + '/api/v1/users/me/tenants/switch', {
            method: 'POST', headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ tenant_id: inv.tenant_id }), credentials: 'include',
          });
        }
        localStorage.setItem('fluentra_user', JSON.stringify(stored));
        window.location.reload();
      } else {
        load();
      }
    } catch(e) {
      if (window.modalAlert) window.modalAlert('Failed to ' + action + ' invitation');
    } finally { setBusy(false); }
  };

  if (invites.length === 0) return null;

  return (
    <div style={{padding:'10px 12px',borderTop:'1px solid var(--line-2)'}}>
      <div style={{fontSize:10,fontFamily:'Geist Mono,monospace',letterSpacing:'.06em',textTransform:'uppercase',color:'var(--ink-faint)',marginBottom:8}}>Invitations</div>
      {invites.map(inv => (
        <div key={inv.id} style={{display:'flex',alignItems:'center',gap:8,padding:'6px 0'}}>
          <span style={{fontSize:12,flex:1,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap',color:'var(--ink)'}}>{inv.tenant_name||inv.tenant_id}</span>
          <div style={{display:'flex',gap:4}}>
            <button className="btn btn-sm" disabled={busy} onClick={()=>respond(inv.id,'accept')} style={{padding:'2px 8px',fontSize:11}}>Accept</button>
            <button className="btn btn-ghost btn-sm" disabled={busy} onClick={()=>respond(inv.id,'decline')} style={{padding:'2px 8px',fontSize:11}}>Decline</button>
          </div>
        </div>
      ))}
    </div>
  );
}

/* ══════════════════════════════════════════════════════════════
   SIDEBAR
   ══════════════════════════════════════════════════════════ */
function Sidebar({ page, setPage, user, tenantName }) {
  const items = [
    { id:'dashboard', icon:'grid',    label:'Dashboard' },
    { id:'diagrams',  icon:'diagram', label:'Diagrams' },
    { id:'instances', icon:'play',    label:'Instances' },
    { id:'history',   icon:'history', label:'Instance history' },
    { id:'editor',    icon:'edit',    label:'Diagram editor' },
  ];
  const initials = (user?.email||'U').slice(0,2).toUpperCase();
  const [menuOpen, setMenuOpen] = React.useState(false);
  const [showChangePw, setShowChangePw] = React.useState(false);

  const handleLogout = async () => {
    await fetch(window.FLUENTRA_API + '/api/v1/users/logout', { method: 'POST', credentials: 'include' });
    localStorage.removeItem('fluentra_user');
    window.location.reload();
  };

  return (
    <aside className="sidebar">
      <div className="sb-brand">
        <span className="brand-mark"/>
        <b>Fluentra</b>
        <span className="tag">v2.0</span>
      </div>
      <nav className="sb-nav">
        <div className="sb-section">Workspace</div>
        {items.map(it => (
          <div key={it.id} className={'sb-link'+(page===it.id?' active':'')} onClick={()=>setPage(it.id)}>
            <I name={it.icon} size={16}/>{it.label}
          </div>
        ))}
        <div className="sb-section">Settings</div>
        <div className={'sb-link'+(page==='tenant'?' active':'')} onClick={()=>setPage('tenant')}>
          <I name="settings" size={16}/>Manage tenant
        </div>
      </nav>
      <div className="sb-foot" style={{flexDirection:'column',alignItems:'stretch',gap:8,position:'relative'}}>
        <InvitationsPanel/>
        <div style={{display:'flex',alignItems:'center',gap:10,cursor:'pointer'}} onClick={()=>setMenuOpen(v=>!v)}>
          <div className="avatar">{initials}</div>
          <div className="em" style={{flex:1,minWidth:0}}>
            <b>{(user?.email||'').split('@')[0]||'User'}</b>
            <span>{tenantName||'No tenant'}</span>
          </div>
          <I name="chevron" size={14} style={{transform: menuOpen ? 'rotate(180deg)' : 'none', transition: '.15s'}}/>
        </div>
        {menuOpen && (
          <div style={{position:'absolute',bottom:'calc(100% + 8px)',left:0,right:0,background:'var(--surface)',border:'1px solid var(--line-2)',borderRadius:12,padding:8,boxShadow:'0 20px 40px -10px rgba(0,0,0,.5)',zIndex:10}}>
            <div style={{padding:'6px 10px',fontSize:12,color:'var(--ink-dim)',wordBreak:'break-all'}}>{user?.email}</div>
            <div style={{height:1,background:'var(--line-2)',margin:'6px 0'}}/>
            <button onClick={()=>{setShowChangePw(true);setMenuOpen(false);}} style={{display:'flex',alignItems:'center',gap:8,width:'100%',padding:'6px 10px',background:'transparent',border:'none',borderRadius:6,color:'var(--ink)',fontSize:13,cursor:'pointer',textAlign:'left'}}>
              <I name="lock" size={14}/> Change Password
            </button>
            {user?.email_verified === false && (
              <button onClick={async ()=>{setMenuOpen(false);try{await fetch(window.FLUENTRA_API+'/api/v1/users/resend-verification',{method:'POST',credentials:'include'});if(window.modalAlert)window.modalAlert('Verification email sent.');else alert('Verification email sent.');}catch(e){if(window.modalAlert)window.modalAlert('Failed to send.');else alert('Failed to send.');}}} style={{display:'flex',alignItems:'center',gap:8,width:'100%',padding:'6px 10px',background:'transparent',border:'none',borderRadius:6,color:'var(--ink)',fontSize:13,cursor:'pointer',textAlign:'left'}}>
                <I name="mail" size={14}/> Verify Email
              </button>
            )}
            <button onClick={handleLogout} style={{display:'flex',alignItems:'center',gap:8,width:'100%',padding:'6px 10px',background:'transparent',border:'none',borderRadius:6,color:'var(--danger)',fontSize:13,cursor:'pointer',textAlign:'left'}}>
              <I name="logout" size={14}/> Sign out
            </button>
          </div>
        )}
        {showChangePw && <ChangePasswordModal onClose={()=>setShowChangePw(false)}/>}
      </div>
    </aside>
  );
}

/* ══════════════════════════════════════════════════════════════
   TOPBAR
   ══════════════════════════════════════════════════════════ */
function Topbar({ page, tenantTab, tenantName, onRefresh }) {
  const titles = { dashboard:'Dashboard', diagrams:'Diagrams', instances:'Instances', history:'Instance history', editor:'Diagram editor', tenant:'Tenant', instance:'Instance details' };
  return (
    <header className="topbar">
      <div className="crumbs">
        <span>{tenantName||'—'}</span>
        <span className="sep">/</span>
        <b>{titles[page]||page}</b>
        {page==='tenant' && tenantTab && (<><span className="sep">/</span><span style={{textTransform:'capitalize'}}>{tenantTab}</span></>)}
      </div>
      <div className="spacer"/>
      <div className="tenant-pill"><span className="dot"/><span>{tenantName||'—'}</span><I name="chevron" size={14}/></div>
      {onRefresh && <button className="icon-btn" title="Refresh" aria-label="Refresh" onClick={onRefresh}><I name="refresh" size={15}/></button>}
      <NotificationsBell/>
    </header>
  );
}

/* ══════════════════════════════════════════════════════════════
   ERROR BOUNDARY
   ══════════════════════════════════════════════════════════ */
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false, error: null };
  }
  static getDerivedStateFromError(error) {
    return { hasError: true, error };
  }
  componentDidCatch(error, info) {
    console.error('[ErrorBoundary]', error, info);
  }
  render() {
    if (this.state.hasError) {
      return (
        <div style={{display:'flex',alignItems:'center',justifyContent:'center',minHeight:'100vh',background:'var(--bg)',color:'var(--ink)',fontFamily:"'Geist',sans-serif",padding:24}}>
          <div style={{textAlign:'center',maxWidth:420}}>
            <h2 style={{margin:'0 0 12px',fontSize:22}}>Something went wrong</h2>
            <p style={{margin:0,color:'var(--ink-dim)',fontSize:14,lineHeight:1.5}}>
              The application encountered an unexpected error. Please refresh the page to try again.
            </p>
            <button onClick={()=>window.location.reload()} className="btn btn-accent" style={{marginTop:20}}>
              Refresh page
            </button>
          </div>
        </div>
      );
    }
    return this.props.children;
  }
}

/* ══════════════════════════════════════════════════════════════
   APP ROOT
   ══════════════════════════════════════════════════════════ */
function App() {
  const [authState, setAuthState] = React.useState(() => {
    try {
      const stored = localStorage.getItem('fluentra_user');
      if (stored) return JSON.parse(stored);
    } catch(e){}
    return null;
  });

  const [page, setPage]                     = React.useState('dashboard');
  const [tenantTab, setTenantTab]           = React.useState('details');
  const [tenantName, setTenantName]         = React.useState('');
  const [refreshKey, setRefreshKey]         = React.useState(0);
  const [selectedInstanceId, setSelectedInstanceId] = React.useState(null);
  const [modal, setModal]                   = React.useState(null);

  // ── Modal API ─────────────────────────────────────────────────
  React.useEffect(() => {
    window.modalConfirm = (msg) => new Promise((resolve) => setModal({type:'confirm', msg, resolve}));
    window.modalPrompt = (msg, def='') => new Promise((resolve) => setModal({type:'prompt', msg, defaultValue:def, resolve}));
    window.modalAlert = (msg) => new Promise((resolve) => setModal({type:'alert', msg, resolve}));
    window.setAppPage = (p) => setPage(p);
  }, []);

  // ── Derived (safe even when authState is null) ────────────────
  const tenantId = authState?.active_tenant_id || null;
  const tenants  = authState?.tenants || [];

  // ── ALL hooks BEFORE any conditional return (Rules of Hooks) ──
  // Load tenant name whenever tenantId becomes known
  React.useEffect(() => {
    if (!tenantId) return;
    window.__FETCH__('/api/v1/tenants/' + tenantId)
      .then(r => r?.json())
      .then(d => { if (d?.tenant_name) setTenantName(d.tenant_name); })
      .catch(()=>{});
  }, [tenantId]);

  // Hash-based routing (read once on mount)
  React.useEffect(() => {
    try {
      const h = location.hash.replace('#','');
      if (h && ['dashboard','diagrams','instances','instance','history','editor','tenant'].includes(h)) setPage(h);
    } catch(e){}
  }, []);

  // Keep URL hash in sync with current page
  React.useEffect(() => { try { history.replaceState(null,'','#'+page); } catch(e){} }, [page]);

  // Email verification redirect handling
  React.useEffect(() => {
    try {
      const params = new URLSearchParams(window.location.search);
      const verified = params.get('verified');
      if (verified === 'success') {
        // Refetch user data so email_verified is updated in state
        fetch(window.FLUENTRA_API + '/api/v1/users/me', { credentials: 'include' })
          .then(r => r.ok ? r.json() : null)
          .then(user => {
            if (user && authState) {
              const stored = JSON.parse(localStorage.getItem('fluentra_user') || '{}');
              stored.email_verified = user.email_verified;
              localStorage.setItem('fluentra_user', JSON.stringify(stored));
              setAuthState(stored);
            }
          })
          .catch(()=>{})
          .finally(() => {
            if (window.modalAlert) window.modalAlert('Your email has been verified successfully.');
            else alert('Your email has been verified successfully.');
            history.replaceState(null, '', window.location.pathname + window.location.hash);
          });
      } else if (verified === 'error') {
        const msg = params.get('message') || 'Email verification failed.';
        if (window.modalAlert) window.modalAlert(msg);
        else alert(msg);
        history.replaceState(null, '', window.location.pathname + window.location.hash);
      }
    } catch(e){}
  }, []);

  // Track hash in state so child components can navigate via window.location.hash
  const [hash, setHash] = React.useState(window.location.hash);
  React.useEffect(() => {
    const onHashChange = () => setHash(window.location.hash);
    window.addEventListener('hashchange', onHashChange);
    return () => window.removeEventListener('hashchange', onHashChange);
  }, []);

  // ── Conditional rendering AFTER all hooks ─────────────────────

  if (!authState) {
    if (hash === '#forgot-password') return <ForgotPasswordPage />;
    if (hash === '#reset-password') return <ResetPasswordPage />;
    return <LoginPage onLogin={u => setAuthState(u)}/>;
  }

  if (!tenantId) {
    if (tenants.length === 0)
      return (
        <div style={{display:'flex',alignItems:'center',justifyContent:'center',minHeight:'100vh',background:'var(--bg)'}}>
          <div style={{maxWidth:400,margin:'40px auto',textAlign:'center',padding:'0 20px'}}>
            <h2 style={{fontSize:18,fontWeight:600,letterSpacing:'-.01em',margin:'0 0 8px'}}>No Tenant Access</h2>
            <p style={{margin:'0 0 24px',color:'var(--ink-dim)',fontSize:13}}>You don't belong to any tenant yet.</p>
            <TenantRequestForm />
            <p style={{marginTop:16,fontSize:12,color:'var(--ink-faint)'}}>
              Once approved by a platform admin, you'll be able to access your tenant.
            </p>
            <button onClick={async () => {
                await fetch(window.FLUENTRA_API + '/api/v1/users/logout', { method: 'POST', credentials: 'include' });
                localStorage.removeItem('fluentra_user');
                window.location.reload();
              }}
              style={{display:'block',margin:'20px auto 0',background:'transparent',border:'none',color:'var(--ink-faint)',fontSize:12.5,cursor:'pointer',fontFamily:'Geist,sans-serif'}}>
              Sign out
            </button>
          </div>
        </div>
      );
    return <TenantSelector user={authState} tenants={tenants} onSelect={u => setAuthState(u)}/>;
  }

  const sidebarPage = page === 'instance' ? 'instances' : page;
  const auth = {
    userId:    authState.user_id,
    email:     authState.email,
    tenantId,
    tenants,
    token:     authState.token,
    isAdmin:   authState.is_platform_admin || false,
    email_verified: authState.email_verified,
  };

  const goInstance = (id) => { setSelectedInstanceId(id); setPage('instance'); };

  const closeModal = (value) => {
    if (modal) { modal.resolve(value); setModal(null); }
  };

  return (
    <AuthCtx.Provider value={auth}>
      <div className="app">
        <Sidebar page={sidebarPage} setPage={setPage} user={auth} tenantName={tenantName}/>
        <div className="main">
          <Topbar page={page} tenantTab={page==='tenant'?tenantTab:null} tenantName={tenantName} onRefresh={()=>setRefreshKey(k=>k+1)}/>
          <main className="content">
            <div className="gridbg"/>
            {page==='dashboard' && <DashboardPage  key={refreshKey} onView={goInstance}/>}
            {page==='diagrams'  && <DiagramsPage   key={refreshKey}/>}
            {page==='instances' && <InstancesPage  key={refreshKey} onView={goInstance}/>}
            {page==='instance'  && <InstanceDetailsPage instanceId={selectedInstanceId} onBack={()=>setPage('instances')}/>}
            {page==='history'   && <HistoryPage    key={refreshKey}/>}
            {page==='editor'    && <EditorPage/>}
            {page==='tenant'    && <TenantPage tab={tenantTab} setTab={setTenantTab}/>}
          </main>
        </div>
      </div>

      {/* Custom Modals */}
      {modal && (
        <div style={{position:'fixed',inset:0,background:'rgba(0,0,0,.5)',display:'flex',alignItems:'center',justifyContent:'center',zIndex:200}} onClick={()=>closeModal(modal.type==='confirm'?false:null)}>
          <div style={{background:'var(--surface)',border:'1px solid var(--line-2)',borderRadius:16,padding:28,maxWidth:400,width:'90%'}} onClick={e=>e.stopPropagation()}>
            {modal.type==='confirm' && (
              <>
                <p style={{margin:'0 0 20px',color:'var(--ink)',fontSize:14,lineHeight:1.5,whiteSpace:'pre-wrap'}}>{modal.msg}</p>
                <div style={{display:'flex',gap:10,justifyContent:'flex-end'}}>
                  <button className="btn btn-ghost" onClick={()=>closeModal(false)}>Cancel</button>
                  <button className="btn btn-accent" onClick={()=>closeModal(true)}>OK</button>
                </div>
              </>
            )}
            {modal.type==='alert' && (
              <>
                <p style={{margin:'0 0 20px',color:'var(--ink)',fontSize:14,lineHeight:1.5,whiteSpace:'pre-wrap'}}>{modal.msg}</p>
                <div style={{display:'flex',justifyContent:'flex-end'}}>
                  <button className="btn btn-accent" onClick={()=>closeModal()}>OK</button>
                </div>
              </>
            )}
            {modal.type==='prompt' && (
              <PromptModalContent msg={modal.msg} defaultValue={modal.defaultValue} onSubmit={(v)=>closeModal(v)} onCancel={()=>closeModal(null)}/>
            )}
          </div>
        </div>
      )}
    </AuthCtx.Provider>
  );
}

function PromptModalContent({ msg, defaultValue, onSubmit, onCancel }) {
  const [val, setVal] = React.useState(defaultValue||'');
  const ref = React.useRef(null);
  React.useEffect(() => { setTimeout(()=>ref.current?.focus(), 50); }, []);
  return (
    <>
      <p style={{margin:'0 0 14px',color:'var(--ink)',fontSize:14,lineHeight:1.5,whiteSpace:'pre-wrap'}}>{msg}</p>
      <input ref={ref} className="input" value={val} onChange={e=>setVal(e.target.value)} onKeyDown={e=>{if(e.key==='Enter')onSubmit(val);}} style={{marginBottom:20,width:'100%'}}/>
      <div style={{display:'flex',gap:10,justifyContent:'flex-end'}}>
        <button className="btn btn-ghost" onClick={onCancel}>Cancel</button>
        <button className="btn btn-accent" onClick={()=>onSubmit(val)}>OK</button>
      </div>
    </>
  );
}

ReactDOM.createRoot(document.getElementById('app')).render(<ErrorBoundary><App/></ErrorBoundary>);
