import { normalizeAuth, setStoredAuth } from "./storage.js";
import { exchangeLaunchToken } from "./sessionExchange.js";
import {
  decodeJwtPayload,
  JWT_AUD,
  JWT_PURPOSE,
} from "./tokenClaims.js";
import { roleFromJwt, userFromJwt, rolesFromJwt, roleIdsFromJwt } from "./jwtPayload.js";
import { redirectToHseLogin } from "./loginRedirect.js";

const TOKEN_PARAMS = ["token", "access_token", "accessToken"];

function stripTokenFromUrl() {
  const params = new URLSearchParams(window.location.search);
  for (const name of TOKEN_PARAMS) {
    params.delete(name);
  }
  const qs = params.toString();
  const next = `${window.location.pathname}${qs ? `?${qs}` : ""}${window.location.hash}`;
  window.history.replaceState({}, "", next);
}

function authFromSessionToken(urlToken) {
  return normalizeAuth({
    token: urlToken,
    user: userFromJwt(urlToken),
    roles: rolesFromJwt(urlToken),
    roleIds: roleIdsFromJwt(urlToken),
    role: roleFromJwt(urlToken),
  });
}

function authFromLoginUrlToken(urlToken) {
  return normalizeAuth({
    token: urlToken,
    user: userFromJwt(urlToken),
    roles: rolesFromJwt(urlToken),
    roleIds: roleIdsFromJwt(urlToken),
    role: roleFromJwt(urlToken),
  });
}

function isMasterLoginPayload(payload) {
  if (!payload) return false;
  if (
    payload.purpose === JWT_PURPOSE.LOGIN &&
    payload.aud === JWT_AUD.MASTER
  ) {
    return true;
  }
  // Legacy login JWT
  const userId = payload.userId ?? payload.user_id ?? payload.id;
  return (
    !payload.purpose &&
    !payload.aud &&
    userId != null &&
    payload.purpose !== JWT_PURPOSE.APP_LAUNCH &&
    payload.purpose !== JWT_PURPOSE.APP_SESSION
  );
}

/**
 * Read ?token= from the URL.
 * @param {{ master?: boolean }} [options] — Master Dashboard: only accept login JWTs; ignore child tokens.
 */
export async function consumeTokenFromUrl(options = {}) {
  if (typeof window === "undefined") return null;

  const params = new URLSearchParams(window.location.search);
  let urlToken = "";
  for (const name of TOKEN_PARAMS) {
    const v = params.get(name);
    if (v && String(v).trim()) {
      urlToken = String(v).trim();
      break;
    }
  }

  if (!urlToken) return null;

  const payload = decodeJwtPayload(urlToken);
  const purpose = payload?.purpose;
  const aud = payload?.aud;

  if (options.master) {
    if (isMasterLoginPayload(payload)) {
      const auth = authFromLoginUrlToken(urlToken);
      setStoredAuth(auth, { scope: "master" });
      stripTokenFromUrl();
      return auth;
    }
    stripTokenFromUrl();
    return null;
  }

  try {
    let auth = null;
    if (purpose === JWT_PURPOSE.APP_LAUNCH && aud) {
      auth = await exchangeLaunchToken(urlToken, aud);
    } else if (purpose === JWT_PURPOSE.APP_SESSION && aud) {
      auth = authFromSessionToken(urlToken);
    } else {
      stripTokenFromUrl();
      redirectToHseLogin();
      return null;
    }

    setStoredAuth(auth);
    stripTokenFromUrl();
    return auth;
  } catch {
    stripTokenFromUrl();
    redirectToHseLogin();
    return null;
  }
}
