const SESSION_STORAGE_KEY = 'auth-session';
const LEGACY_AUTH_STORAGE_KEY = 'auth-storage';
const ACCESS_TOKEN_KEY = 'accessToken';

export interface StoredSession {
  accessToken: string | null;
  refreshToken: string | null;
  expiresAt: number | null;
}

interface LegacyAuthStorageState {
  state?: {
    accessToken?: string | null;
  };
}

function canUseStorage(): boolean {
  return typeof window !== 'undefined';
}

function readLegacyAccessToken(): string | null {
  const authStorage = localStorage.getItem(LEGACY_AUTH_STORAGE_KEY);
  if (!authStorage) {
    return null;
  }

  const parsed: LegacyAuthStorageState = JSON.parse(authStorage);
  return parsed?.state?.accessToken ?? null;
}

function persistLegacyAccessToken(token: string | null): void {
  const authStorage = localStorage.getItem(LEGACY_AUTH_STORAGE_KEY);
  if (!authStorage) {
    return;
  }

  const parsed: LegacyAuthStorageState = JSON.parse(authStorage);
  if (!parsed?.state) {
    return;
  }

  parsed.state.accessToken = token;
  localStorage.setItem(LEGACY_AUTH_STORAGE_KEY, JSON.stringify(parsed));
}

export function getStoredSession(): StoredSession {
  if (!canUseStorage()) {
    return { accessToken: null, refreshToken: null, expiresAt: null };
  }

  try {
    const raw = localStorage.getItem(SESSION_STORAGE_KEY);
    if (raw) {
      const parsed = JSON.parse(raw) as Partial<StoredSession>;
      return {
        accessToken: parsed.accessToken ?? null,
        refreshToken: parsed.refreshToken ?? null,
        expiresAt: parsed.expiresAt ?? null,
      };
    }

    const directAccessToken = localStorage.getItem(ACCESS_TOKEN_KEY) ?? readLegacyAccessToken();
    if (directAccessToken) {
      const migratedSession: StoredSession = {
        accessToken: directAccessToken,
        refreshToken: null,
        expiresAt: null,
      };
      setStoredSession(migratedSession);
      return migratedSession;
    }
  } catch {
    // Ignore storage errors and fall back to empty session.
  }

  return { accessToken: null, refreshToken: null, expiresAt: null };
}

export function setStoredSession(session: StoredSession): void {
  if (!canUseStorage()) {
    return;
  }

  try {
    localStorage.setItem(SESSION_STORAGE_KEY, JSON.stringify(session));

    if (session.accessToken) {
      localStorage.setItem(ACCESS_TOKEN_KEY, session.accessToken);
    } else {
      localStorage.removeItem(ACCESS_TOKEN_KEY);
    }

    persistLegacyAccessToken(session.accessToken);
  } catch {
    // Ignore storage errors
  }
}

export function clearStoredSession(): void {
  if (!canUseStorage()) {
    return;
  }

  try {
    localStorage.removeItem(SESSION_STORAGE_KEY);
    localStorage.removeItem(ACCESS_TOKEN_KEY);
    persistLegacyAccessToken(null);
  } catch {
    // Ignore storage errors
  }
}

export function getAccessToken(): string | null {
  return getStoredSession().accessToken;
}

export function getRefreshToken(): string | null {
  return getStoredSession().refreshToken;
}

export function getExpiresAt(): number | null {
  return getStoredSession().expiresAt;
}

export function setAccessToken(token: string): void {
  const session = getStoredSession();
  setStoredSession({ ...session, accessToken: token });
}

export function removeAccessToken(): void {
  const session = getStoredSession();
  setStoredSession({ ...session, accessToken: null });
}
