// Auth — Auth0 splash gate (Phase 4.1)
//
// One Auth0 SPA client, created at module scope before <App/> mounts.
// <AuthGate> wraps the app root: resolving → neutral loading; signed-out →
// SignInSplash (Auth0 hosts the actual login page — popup mode, with a
// full-page-redirect fallback when the popup is blocked); signed-in → app.
//
// Export builds get their Bearer token from this session via
// window.dynamoGetAccessToken() (getTokenSilently) — no manual pasting.

const AUTH0_CONFIG = {
  domain: 'dynamo-labs.us.auth0.com',
  clientId: 'EtWX8kryfnrUGQh95RMa8q74B5hAA5UU',
  audience: 'https://api.dynamo-authoring.com',
};

// Where the redirect-fallback leg lands back. Strip query + hash so the
// callback params don't accumulate.
const AUTH0_REDIRECT_URI = window.location.origin + window.location.pathname;

const auth0Ready = (async () => {
  if (!window.auth0 || !window.auth0.createAuth0Client) {
    throw new Error('Auth0 SDK failed to load from CDN');
  }
  const client = await window.auth0.createAuth0Client({
    domain: AUTH0_CONFIG.domain,
    clientId: AUTH0_CONFIG.clientId,
    authorizationParams: {
      audience: AUTH0_CONFIG.audience,
      redirect_uri: AUTH0_REDIRECT_URI,
    },
    useRefreshTokens: true,
    cacheLocation: 'localstorage',
  });
  // Redirect-fallback return leg: consume ?code&state, then clean the URL.
  const q = window.location.search;
  if (q.includes('code=') && q.includes('state=')) {
    try { await client.handleRedirectCallback(); }
    catch { /* stale or foreign params — ignore */ }
    window.history.replaceState({}, document.title, AUTH0_REDIRECT_URI);
  }
  return client;
})();
// Handling lives in AuthGate; this no-op keeps a pre-mount rejection from
// surfacing as an unhandled-promise console error.
auth0Ready.catch(() => {});

// Access token for the export gateway, from the signed-in session.
async function dynamoGetAccessToken() {
  const client = await auth0Ready;
  return client.getTokenSilently({
    authorizationParams: { audience: AUTH0_CONFIG.audience },
  });
}

async function dynamoSignOut() {
  const client = await auth0Ready;
  client.logout({ logoutParams: { returnTo: window.location.origin } });
}

// ── Splash + gate UI ─────────────────────────────────────────────────────────

// Same mark as chrome.jsx's DynamoLogo, scaled up for the splash.
function SplashLogo({ size = 44 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
      <rect x="2" y="2" width="20" height="20" rx="5" fill="var(--text)"></rect>
      <path d="M8 7 L8 17 L13 17 C15.5 17 17 15 17 12 C17 9 15.5 7 13 7 Z" fill="var(--bg)"></path>
      <circle cx="17" cy="7" r="2" fill="var(--accent)"></circle>
    </svg>
  );
}

function AuthSpinner({ size = 16, light = false }) {
  return (
    <span className="spin" style={{
      width: size, height: size, flexShrink: 0,
      borderRadius: '50%', display: 'inline-block',
      border: `2px solid ${light ? 'rgba(255,255,255,0.35)' : 'var(--border-strong)'}`,
      borderTopColor: light ? '#fff' : 'var(--accent)',
    }}></span>
  );
}

function AuthResolving() {
  return (
    <div data-screen-label="Auth · resolving" style={{
      position: 'fixed', inset: 0, background: 'var(--bg)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
    }}>
      <AuthSpinner size={22} />
    </div>
  );
}

function SignInSplash({ onSignIn, busy, error }) {
  return (
    <div data-screen-label="Sign in" style={{
      position: 'fixed', inset: 0, background: 'var(--bg)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      fontFamily: 'var(--font-sans)',
    }}>
      <div style={{
        display: 'flex', flexDirection: 'column', alignItems: 'center',
        gap: 0, width: 340, maxWidth: 'calc(100vw - 48px)',
        padding: '40px 36px 32px',
        background: 'var(--surface)', border: '1px solid var(--border)',
        borderRadius: 'var(--radius-lg)', boxShadow: 'var(--shadow-lg)',
      }}>
        <SplashLogo size={44} />
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 16 }}>
          <span style={{ fontWeight: 600, fontSize: 17, color: 'var(--text)' }}>Dynamo</span>
          <span style={{ fontSize: 11.5, color: 'var(--text-faint)', padding: '2px 6px',
            background: 'var(--surface-inset)', borderRadius: 3, fontWeight: 500 }}>Authoring</span>
        </div>
        <p style={{ margin: '10px 0 0', fontSize: 13, color: 'var(--text-muted)',
          textAlign: 'center', lineHeight: 1.55 }}>
          Sign in to open the authoring workspace.
        </p>
        <button className="btn primary lg focusable" onClick={onSignIn} disabled={busy}
          style={{ marginTop: 24, width: '100%', justifyContent: 'center', gap: 8 }}>
          {busy ? (<><AuthSpinner size={14} light={true} />Waiting for Auth0…</>) : 'Sign in with Auth0'}
        </button>
        {error && (
          <p style={{ margin: '14px 0 0', fontSize: 12, color: 'var(--error-text)',
            textAlign: 'center', lineHeight: 1.5 }}>{error}</p>
        )}
        <p style={{ margin: '18px 0 0', fontSize: 11, color: 'var(--text-faint)',
          textAlign: 'center', lineHeight: 1.5 }}>
          A secure Auth0 window opens to handle the sign-in.
        </p>
      </div>
    </div>
  );
}

function AuthGate({ children }) {
  const [phase, setPhase] = React.useState('resolving'); // resolving | out | in
  const [busy, setBusy] = React.useState(false);
  const [error, setError] = React.useState(null);

  React.useEffect(() => {
    let alive = true;
    auth0Ready
      .then(c => c.isAuthenticated())
      .then(ok => { if (alive) setPhase(ok ? 'in' : 'out'); })
      .catch(() => {
        if (alive) {
          setPhase('out');
          setError('Could not reach the sign-in service. Check your connection and reload.');
        }
      });
    return () => { alive = false; };
  }, []);

  const signIn = React.useCallback(async () => {
    setBusy(true); setError(null);
    try {
      const client = await auth0Ready;
      try {
        await client.loginWithPopup();
      } catch (e) {
        const msg = String((e && (e.message || e.error)) || '');
        if (/unable to open|popup.{0,12}(block|open)/i.test(msg)) {
          // Popup blocked → full-page redirect fallback; the return leg is
          // consumed by handleRedirectCallback at startup.
          await client.loginWithRedirect({
            authorizationParams: { redirect_uri: AUTH0_REDIRECT_URI },
          });
          return; // navigation takes over
        }
        if (/timeout|cancell?ed|closed/i.test(msg)) {
          setError('The sign-in window was closed before finishing. Try again.');
          return;
        }
        throw e;
      }
      const ok = await client.isAuthenticated();
      setPhase(ok ? 'in' : 'out');
      if (!ok) setError('Sign-in did not complete. Try again.');
    } catch {
      setError('Sign-in failed. Try again.');
    } finally {
      setBusy(false);
    }
  }, []);

  if (phase === 'resolving') return <AuthResolving />;
  if (phase === 'out') return <SignInSplash onSignIn={signIn} busy={busy} error={error} />;
  return children;
}

Object.assign(window, {
  AuthGate, SignInSplash,
  auth0Ready, dynamoGetAccessToken, dynamoSignOut,
  AUTH0_CONFIG,
});
