/* ── Clerk auth bridge (static site, vanilla ClerkJS) ──
   The CSV exports are gated behind sign-in. ClerkJS is hot-loaded in index.html
   from the Clerk frontend API using a publishable (public, safe-to-ship) key —
   the SAME Clerk instance as the kestrel-app product, so an account created
   there signs in here too. This module bridges ClerkJS into React: a
   `useClerkAuth` hook, open-sign-in / sign-out helpers, and the header
   SignInControl. No secret keys and no backend are involved. */

const CLERK_PUBLISHABLE_KEY = 'pk_test_bG92ZWQtYW50ZWxvcGUtNTAuY2xlcmsuYWNjb3VudHMuZGV2JA';

/* Resolve once ClerkJS is present and loaded. Resolves null if it never arrives
   (offline / blocked / ad-blocker) so callers degrade instead of hanging. */
let _clerkPromise = null;
const ensureClerk = () => {
  if (_clerkPromise) return _clerkPromise;
  _clerkPromise = new Promise((resolve) => {
    let tries = 0;
    const tick = () => {
      const C = window.Clerk;
      if (C && typeof C.load === 'function') {
        if (C.loaded) { resolve(C); return true; }
        C.load().then(() => resolve(C)).catch((e) => { console.warn('Clerk load failed', e); resolve(null); });
        return true;
      }
      if (++tries > 120) { console.warn('ClerkJS did not load in time'); resolve(null); return true; } // ~12s
      return false;
    };
    if (tick()) return;
    const iv = setInterval(() => { if (tick()) clearInterval(iv); }, 100);
  });
  return _clerkPromise;
};

/* React hook → { ready, signedIn, user }. Re-renders on any Clerk auth change. */
const useClerkAuth = () => {
  const read = () => {
    const C = window.Clerk;
    return { ready: !!(C && C.loaded), signedIn: !!(C && C.user), user: (C && C.user) || null };
  };
  const [state, setState] = React.useState(read);
  React.useEffect(() => {
    let alive = true, unsub = null;
    ensureClerk().then((C) => {
      if (!alive) return;
      if (!C) { setState((s) => ({ ...s, ready: true })); return; }
      const sync = () => { if (alive) setState({ ready: true, signedIn: !!C.user, user: C.user || null }); };
      sync();
      unsub = C.addListener(sync);
    });
    return () => { alive = false; if (typeof unsub === 'function') unsub(); };
  }, []);
  return state;
};

/* Open Clerk's hosted sign-in (modal overlay). */
const openClerkSignIn = (opts) => {
  ensureClerk().then((C) => {
    if (C) C.openSignIn(opts || {});
    else console.warn('Clerk unavailable — cannot open sign-in');
  });
};
const clerkSignOut = () => { ensureClerk().then((C) => { if (C) C.signOut(); }); };

/* Open Clerk's hosted sign-up (modal). With the instance in restricted mode this
   only completes for an invited user — the prebuilt component reads the
   __clerk_ticket from the URL and switches to the "accept invitation" flow. */
const openClerkSignUp = (opts) => {
  ensureClerk().then((C) => {
    if (C) C.openSignUp(opts || {});
    else console.warn('Clerk unavailable — cannot open sign-up');
  });
};

/* Invitation acceptance. When an approved client clicks the email link, Clerk
   redirects back here with `__clerk_ticket` (+ `__clerk_status`). Open the
   matching flow so they can create their account / join their org. Runs once. */
let _ticketHandled = false;
const handleInvitationTicket = () => {
  if (_ticketHandled) return;
  let params;
  try { params = new URLSearchParams(window.location.search); } catch (e) { return; }
  const ticket = params.get('__clerk_ticket');
  if (!ticket) return;
  _ticketHandled = true;
  const status = params.get('__clerk_status'); // sign_up | sign_in | complete
  ensureClerk().then((C) => {
    if (!C || C.user) return;          // not loaded, or already signed in
    if (status === 'complete') return; // Clerk already consumed the ticket
    if (status === 'sign_in') C.openSignIn({});
    else C.openSignUp({});             // new account (default) — picks up the ticket
  });
};

const clerkUserEmail = (user) => (user && (
  (user.primaryEmailAddress && user.primaryEmailAddress.emailAddress) ||
  (user.emailAddresses && user.emailAddresses[0] && user.emailAddresses[0].emailAddress)
)) || null;

/* Header control — "Sign in" when signed out; email + "Sign out" when signed in. */
const SignInControl = ({ compact = false }) => {
  const { ready, signedIn, user } = useClerkAuth();
  if (!ready) return null;
  const btnBase = {
    background: 'transparent', border: '1px solid var(--line)', color: 'var(--ink-2)',
    fontFamily: 'var(--mono)', fontSize: 13, cursor: 'pointer',
    padding: compact ? '12px 18px' : '8px 16px',
    ...(compact ? { width: '100%', justifyContent: 'center' } : {}),
  };
  if (signedIn) {
    const email = clerkUserEmail(user) || 'Account';
    return (
      <div style={{ display: compact ? 'flex' : 'inline-flex', alignItems: 'center', gap: 10, ...(compact ? { flexDirection: 'column' } : {}) }}>
        {!compact && <span title={email} style={{ fontFamily: 'var(--mono)', fontSize: 12, color: 'var(--ink-3)', maxWidth: 170, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{email}</span>}
        <button className="btn" style={btnBase} onClick={() => clerkSignOut()}>Sign out</button>
      </div>
    );
  }
  return <button className="btn" style={{ ...btnBase, color: 'var(--ink)' }} onClick={() => openClerkSignIn()}>Sign in</button>;
};

Object.assign(window, {
  CLERK_PUBLISHABLE_KEY, ensureClerk, useClerkAuth,
  openClerkSignIn, openClerkSignUp, clerkSignOut, clerkUserEmail, SignInControl,
});

// Auto-handle an invitation link the moment the script loads.
handleInvitationTicket();
