import {
  AdminUser,
  PORTAL_APP_URL,
  apiPost,
  fetchSessionOptions,
  getStoredUser,
  getToken,
  isPortalRoleName,
  setSessionContextApi,
  setStoredUser,
  setToken,
  switchAcademicYear,
  withoutAuthExpireRedirect,
} from "@/lib/api";
import { clearAcademicContext } from "@/lib/academic-context";
import { assignAdminHref, replaceAdminHref } from "@/lib/app-path";
import {
  clearSessionContext,
  restoreImpersonationBackup,
  setImpersonationBackup,
  setSessionContext,
} from "@/lib/session-context";

function portalRoles(user: unknown): boolean {
  const roles = (user as AdminUser | null)?.roles ?? [];
  return roles.includes("student") || roles.includes("parent");
}

export async function bootstrapAdminSession(): Promise<boolean> {
  const options = await fetchSessionOptions();
  const assignments = options.assignments.filter((item) => !isPortalRoleName(item.role_name));
  if (assignments.length !== 1) return false;

  const year =
    options.academic_years.find((item) => item.is_current) ?? options.academic_years[0];
  if (!year) return false;

  const assignmentId = assignments[0].id;
  const ctx = await setSessionContextApi(assignmentId, year.id);
  await switchAcademicYear(year.id);
  setSessionContext({
    active_role: ctx.active_role,
    active_role_label: ctx.active_role_label,
    active_branch_id: ctx.active_branch_id,
    active_branch_name: ctx.active_branch_name,
    active_academic_year_id: ctx.active_academic_year_id,
    assignment_id: ctx.assignment_id,
    permissions: ctx.permissions,
  });

  return true;
}

export async function startStaffImpersonation(userId: number): Promise<void> {
  const currentToken = getToken();
  const currentUser = getStoredUser();
  const data = await apiPost<{ token: string; user: unknown }>(`/users/${userId}/impersonate`, {});

  if (currentToken) {
    setImpersonationBackup(currentToken, currentUser);
  }

  clearSessionContext();
  clearAcademicContext();
  setToken(data.token);
  setStoredUser(data.user);

  if (portalRoles(data.user)) {
    window.location.href = `${PORTAL_APP_URL}/auth/impersonate?token=${encodeURIComponent(data.token)}`;
    return;
  }

  let bootstrapped = false;
  try {
    bootstrapped = await withoutAuthExpireRedirect(() => bootstrapAdminSession());
  } catch {
    bootstrapped = false;
  }

  assignAdminHref(bootstrapped ? "/dashboard" : "/select-context");
}

export function exitImpersonation(href = "/staff"): boolean {
  if (!restoreImpersonationBackup()) return false;
  replaceAdminHref(href);
  return true;
}
