import type * as interfaces from '../ts_interfaces/index.js';

export type TSessionPhase = 'verifying' | 'anonymous' | 'authenticated' | 'logging-out';

export interface ISessionState {
  identity: interfaces.data.IIdentity | null;
  phase: TSessionPhase;
  generation: number;
  verificationError?: string | null;
}

export const isAuthenticatedSessionState = (
  sessionArg: ISessionState,
  nowArg = Date.now(),
): boolean => sessionArg.phase === 'authenticated'
  && Boolean(sessionArg.identity?.jwt)
  && (sessionArg.identity?.expiresAt ?? 0) > nowArg;

export const isSessionGenerationCurrent = (
  sessionArg: ISessionState,
  generationArg: number,
  nowArg = Date.now(),
): boolean => isAuthenticatedSessionState(sessionArg, nowArg)
  && sessionArg.generation === generationArg;

export const verifiedIdentityFromResponse = (
  responseArg: {
    valid: boolean;
    identity?: interfaces.data.IIdentity;
  },
  nowArg = Date.now(),
): interfaces.data.IIdentity | null => {
  const identity = responseArg.identity;
  if (
    !responseArg.valid
    || !identity?.jwt
    || identity.expiresAt <= nowArg
  ) {
    return null;
  }
  return identity;
};

export const normalizePersistedSession = (
  persistedArg: Partial<ISessionState> & {
    identity?: interfaces.data.IIdentity | null;
    isLoggedIn?: boolean;
  },
  generationArg: number,
  nowArg = Date.now(),
): ISessionState => {
  const identity = persistedArg.identity;
  if (identity?.jwt && identity.expiresAt > nowArg) {
    return {
      identity,
      phase: 'verifying',
      generation: generationArg,
      verificationError: null,
    };
  }

  return {
    identity: null,
    phase: 'anonymous',
    generation: generationArg,
    verificationError: null,
  };
};
