/* global React, window */
/**
 * Auth gate for invited application links (?invite=<token>).
 *
 * The loan was created by a loan officer in the LOS and carries their data,
 * so the island shows nothing until the borrower proves who they are. First
 * visit sets a password (the borrower-invitation accept flow); returning
 * visits sign in. Both end with the bevri_token cookie on this domain, after
 * which the island hydrates exactly like any resumed session. A borrower who
 * is already signed in on this device passes straight through.
 */
(function () {
  const { useState, useEffect } = React;

  async function fetchInviteContext(token) {
    const res = await fetch(`/api/pos/invite/context?token=${encodeURIComponent(token)}`, {
      credentials: 'same-origin',
      headers: { 'x-pos-session-id': window.BevriPosStorage?.sessionId || '' },
    });
    const body = await res.json().catch(() => ({}));
    if (!res.ok || !body.success) return { status: 'invalid' };
    return body;
  }

  async function adoptAndHydrate(loanId) {
    const store = window.BevriPosStorage;
    if (!store || !loanId) return;
    if (!store.loanId) store.adoptIssuedLoan(loanId);
    await store.hydrateNow();
  }

  function GateShell({ children, subtitle }) {
    return (
      <div className="app app-welcome" style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '24px 16px' }}>
        <div style={{ width: '100%', maxWidth: 420, background: 'var(--panel, #fff)', border: '1px solid var(--line, #e5e2da)', borderRadius: 16, padding: '28px 26px', boxShadow: '0 12px 40px rgba(0,0,0,0.08)' }}>
          <div style={{ fontSize: 13, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--sage, #7d8c6f)', fontWeight: 700, marginBottom: 6 }}>
            Your loan application
          </div>
          {subtitle ? <div style={{ fontSize: 14, color: 'var(--muted, #77746c)', marginBottom: 18 }}>{subtitle}</div> : null}
          {children}
        </div>
      </div>
    );
  }

  function Field({ label, children }) {
    return (
      <label style={{ display: 'block', marginBottom: 14 }}>
        <span style={{ display: 'block', fontSize: 13, fontWeight: 600, marginBottom: 6 }}>{label}</span>
        {children}
      </label>
    );
  }

  const inputStyle = {
    width: '100%', boxSizing: 'border-box', padding: '10px 12px', fontSize: 15,
    border: '1px solid var(--line, #d8d4cb)', borderRadius: 10, background: 'var(--bg, #fff)', color: 'inherit',
  };
  const buttonStyle = {
    width: '100%', padding: '11px 14px', fontSize: 15, fontWeight: 700, cursor: 'pointer',
    border: 'none', borderRadius: 10, background: 'var(--sage, #7d8c6f)', color: '#fff',
  };

  function ErrorLine({ text }) {
    if (!text) return null;
    return <div style={{ color: 'var(--danger, #b3452f)', fontSize: 13, marginBottom: 12 }}>{text}</div>;
  }

  function InviteGate({ token, onUnlocked }) {
    const [ctx, setCtx] = useState(null);
    const [busy, setBusy] = useState(false);
    const [error, setError] = useState('');
    const [mode, setMode] = useState('loading'); // loading | create | login | dead | unlocking
    const [password, setPassword] = useState('');
    const [confirm, setConfirm] = useState('');

    useEffect(() => {
      let alive = true;
      fetchInviteContext(token).then(async (c) => {
        if (!alive) return;
        setCtx(c);
        if (c.authorized && c.loanId) {
          setMode('unlocking');
          await adoptAndHydrate(c.loanId);
          onUnlocked();
          return;
        }
        if (c.status === 'pending') setMode('create');
        else if (c.status === 'accepted') setMode('login');
        else setMode('dead');
      }).catch(() => { if (alive) setMode('dead'); });
      return () => { alive = false; };
    }, [token]);

    async function unlockFromContext() {
      const c = await fetchInviteContext(token);
      if (c.authorized && c.loanId) {
        setMode('unlocking');
        await adoptAndHydrate(c.loanId);
        onUnlocked();
        return true;
      }
      return false;
    }

    async function handleCreate(e) {
      e.preventDefault();
      setError('');
      if (password.length < 8) { setError('Password must be at least 8 characters.'); return; }
      if (password !== confirm) { setError('Passwords do not match.'); return; }
      setBusy(true);
      try {
        const res = await fetch('/api/pos/invite/accept', {
          method: 'POST',
          credentials: 'same-origin',
          headers: { 'Content-Type': 'application/json', 'x-pos-session-id': window.BevriPosStorage?.sessionId || '' },
          body: JSON.stringify({ token, password }),
        });
        const body = await res.json().catch(() => ({}));
        if (!res.ok || !body.success) {
          setError(body.error || 'Could not set up your access. Please try again.');
          return;
        }
        if (body.signedIn && body.loanId) {
          setMode('unlocking');
          await adoptAndHydrate(body.loanId);
          onUnlocked();
          return;
        }
        setMode('login');
        setError(body.error || 'Account created. Please sign in with your new password.');
      } catch {
        setError('Something went wrong. Please try again.');
      } finally {
        setBusy(false);
      }
    }

    async function handleLogin(e) {
      e.preventDefault();
      setError('');
      if (!password) { setError('Please enter your password.'); return; }
      setBusy(true);
      try {
        const res = await fetch('/api/auth/login', {
          method: 'POST',
          credentials: 'same-origin',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ email: ctx?.email || '', password, rememberMe: false }),
        });
        if (!res.ok) {
          const body = await res.json().catch(() => ({}));
          setError(body.error || 'Invalid password. Please try again.');
          return;
        }
        const unlocked = await unlockFromContext();
        if (!unlocked) setError('Signed in, but this invitation does not match your account.');
      } catch {
        setError('Something went wrong. Please try again.');
      } finally {
        setBusy(false);
      }
    }

    if (mode === 'loading' || mode === 'unlocking') {
      return (
        <GateShell subtitle={mode === 'unlocking' ? 'Opening your application...' : 'Checking your invitation...'}>
          <div style={{ height: 6, borderRadius: 3, background: 'var(--line, #eee)', overflow: 'hidden' }}>
            <div style={{ width: '40%', height: '100%', background: 'var(--sage, #7d8c6f)', animation: 'pos-gate-slide 1.1s ease-in-out infinite alternate' }} />
          </div>
          <style>{'@keyframes pos-gate-slide { from { margin-left: 0; } to { margin-left: 60%; } }'}</style>
        </GateShell>
      );
    }

    if (mode === 'dead') {
      const reason = ctx?.status === 'expired'
        ? 'This invitation link has expired.'
        : ctx?.status === 'revoked'
          ? 'This invitation link is no longer active.'
          : 'This invitation link is not valid.';
      return (
        <GateShell subtitle={reason}>
          <p style={{ fontSize: 14, color: 'var(--muted, #77746c)', margin: 0 }}>
            Please ask your loan officer to send you a fresh link. Everything already entered on
            your application is safe.
          </p>
        </GateShell>
      );
    }

    const hello = ctx?.borrowerFirstName ? `Hi ${ctx.borrowerFirstName}. ` : '';
    const loanLine = ctx?.loanCode ? ` (loan ${ctx.loanCode})` : '';

    if (mode === 'create') {
      return (
        <GateShell subtitle={`${hello}${ctx?.tenantName || 'Your loan team'} has your application ready${loanLine}. Create a password to open it.`}>
          <form onSubmit={handleCreate}>
            <Field label="Email"><input style={inputStyle} type="email" value={ctx?.email || ''} disabled readOnly /></Field>
            <Field label="Create password"><input style={inputStyle} type="password" autoComplete="new-password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="At least 8 characters" /></Field>
            <Field label="Confirm password"><input style={inputStyle} type="password" autoComplete="new-password" value={confirm} onChange={(e) => setConfirm(e.target.value)} /></Field>
            <ErrorLine text={error} />
            <button style={{ ...buttonStyle, opacity: busy ? 0.7 : 1 }} disabled={busy} type="submit">
              {busy ? 'Setting up...' : 'Create password and open my application'}
            </button>
          </form>
        </GateShell>
      );
    }

    return (
      <GateShell subtitle={`${hello}Welcome back. Sign in to continue your application${loanLine}.`}>
        <form onSubmit={handleLogin}>
          <Field label="Email"><input style={inputStyle} type="email" value={ctx?.email || ''} disabled readOnly /></Field>
          <Field label="Password"><input style={inputStyle} type="password" autoComplete="current-password" value={password} onChange={(e) => setPassword(e.target.value)} /></Field>
          <ErrorLine text={error} />
          <button style={{ ...buttonStyle, opacity: busy ? 0.7 : 1 }} disabled={busy} type="submit">
            {busy ? 'Signing in...' : 'Sign in and continue'}
          </button>
          <div style={{ marginTop: 12, fontSize: 13, textAlign: 'center' }}>
            <a href="/borrower/forgot-password" style={{ color: 'var(--sage, #7d8c6f)' }}>Forgot password?</a>
          </div>
        </form>
      </GateShell>
    );
  }

  window.BevriInviteGate = InviteGate;
})();
