import { Page, TestFixture, TestInfo } from "@playwright/test";

//#region src/index.d.ts
type SessionValueType = string | number | Date | null | undefined;
type SessionType = Record<string, SessionValueType | {
  [key: string]: SessionValueType;
}>;
interface PersonaOptions<Session extends SessionType> {
  createSession: CreateSessionFunction<Session>;
  verifySession: VerifySessionFunction<Session>;
  destroySession?: DestroySessionFunction<Session>;
}
interface CreateSessionContext {
  page: Page;
}
interface VerifySessionContext<Session extends SessionType> {
  session: Session;
  page: Page;
}
interface DestroySessionContext<Session extends SessionType> {
  session: Session;
  page: Page;
}
interface Persona<Name extends string, Session extends SessionType> {
  name: Name;
  createSession: CreateSessionFunction<Session>;
  verifySession: VerifySessionFunction<Session>;
  destroySession?: DestroySessionFunction<Session>;
}
type CreateSessionFunction<Session extends SessionType> = (context: CreateSessionContext, testInfo: TestInfo) => Promise<Session>;
type VerifySessionFunction<Session extends SessionType> = (context: VerifySessionContext<Session>, testInfo: TestInfo) => Promise<void>;
type DestroySessionFunction<Session extends SessionType> = (context: DestroySessionContext<Session>, testInfo: TestInfo) => Promise<void>;
declare function definePersona<Name extends string, Session extends SessionType>(name: Name, options: PersonaOptions<Session>): Persona<Name, Session>;
type AuthenticateFunction<Personas extends Array<Persona<any, any>>> = (options: {
  as: ExtractPersonaNames<Personas>;
}) => Promise<ExtractSessionTypes<Personas>[(typeof options)['as']]>;
type ExtractPersonaNames<Personas extends Array<Persona<any, any>>> = Personas extends Array<infer P> ? P extends Persona<infer Name, any> ? Name : never : never;
type ExtractSessionTypes<Personas extends Array<Persona<any, any>>> = Personas extends Array<infer P> ? P extends Persona<infer Name, infer Session> ? Record<Name, Session> : never : never;
declare function combinePersonas<Personas extends Array<Persona<any, any>>>(...personas: Personas): TestFixture<AuthenticateFunction<Personas>, any>;
//#endregion
export { AuthenticateFunction, CreateSessionContext, CreateSessionFunction, DestroySessionContext, DestroySessionFunction, Persona, PersonaOptions, SessionType, VerifySessionContext, VerifySessionFunction, combinePersonas, definePersona };