import { externalRequest, rememberExternalCsrfToken } from "./client.js";
import { arrayValue, asRecord, textValue } from "./normalizers.js";

// These external-session auth routes intentionally have no main-admin OpenAPI operation.
const EXTERNAL_AUTH_PATHS = Object.freeze({
  changePassword: "/auth/change-password",
  login: "/auth/login",
  logout: "/auth/logout",
  me: "/auth/me"
});

export async function loginExternal(payload) {
  const data = await externalRequest(EXTERNAL_AUTH_PATHS.login, {
    body: {
      account: String(payload.account || "").trim(),
      password: String(payload.password || "")
    },
    method: "POST",
    notifyUnauthorized: false
  });
  rememberExternalCsrfToken(asRecord(data).csrfToken);
  return normalizeSession(data);
}

export async function getExternalSession() {
  const data = await externalRequest(EXTERNAL_AUTH_PATHS.me, { notifyUnauthorized: false });
  rememberExternalCsrfToken(asRecord(data).csrfToken);
  return normalizeSession(data);
}

export async function logoutExternal() {
  try {
    await externalRequest(EXTERNAL_AUTH_PATHS.logout, { method: "POST", notifyUnauthorized: false });
  } finally {
    rememberExternalCsrfToken("");
  }
}

export async function changeExternalPassword(payload) {
  const data = await externalRequest(EXTERNAL_AUTH_PATHS.changePassword, {
    body: {
      currentPassword: payload.oldPassword,
      newPassword: payload.newPassword
    },
    method: "POST"
  });
  return data ? normalizeSession(data) : null;
}

export function normalizeSession(data) {
  const root = asRecord(data);
  const accountRecord = asRecord(root.account);
  const linkedUser = asRecord(root.user || root.linkedUser || root.linked_user);
  const legacyAccount = asRecord(root.externalAdminUser || root.external_admin_user);
  const app = asRecord(root.app || linkedUser.app || accountRecord.app);
  const capabilities = [
    ...arrayValue(root.capabilities),
    ...arrayValue(root.permissions),
    ...arrayValue(accountRecord.capabilities, accountRecord.permissions),
    ...arrayValue(linkedUser.capabilities, linkedUser.permissions)
  ]
    .map(String)
    .filter(Boolean);

  return {
    account: textValue(accountRecord.username, accountRecord.account, legacyAccount.username, legacyAccount.account, root.accountName, typeof root.account === "string" ? root.account : "", root.username),
    appCode: textValue(root.appCode, root.app_code, app.appCode, app.app_code, accountRecord.appCode, accountRecord.app_code, linkedUser.appCode, linkedUser.app_code),
    appName: textValue(app.name, app.appName, app.app_name, root.appName, root.app_name),
    logoUrl: textValue(app.logoUrl, app.logo_url, root.logoUrl, root.logo_url),
    capabilities: [...new Set(capabilities)],
    displayName: textValue(linkedUser.displayName, linkedUser.display_name, linkedUser.name, linkedUser.username, accountRecord.username, legacyAccount.username, root.displayName),
    id: textValue(accountRecord.id, accountRecord.externalAdminUserId, accountRecord.external_admin_user_id, legacyAccount.id, root.accountId, root.account_id),
    passwordChangeRequired: Boolean(
      root.passwordChangeRequired ?? root.password_change_required ?? accountRecord.passwordChangeRequired ?? accountRecord.password_change_required
    )
  };
}
