// We import Fastify cookie here to ensure that the cookie plugin and its types are registered.
import '@fastify/cookie'

import type { UserInfo, UserRoles } from './authentication.types'

type MockAuthenticationResult = {
  /**
   * UserInfo to return from the mock service.
   */
  userInfo: UserInfo

  /**
   * Roles assigned to the user.
   */
  userRoles: UserRoles

  /**
   * Access token to return from the mock service.
   */
  accessToken: string

  /**
   * URL to redirect to after authenticating.
   */
  authRedirectUrl: string

  /**
   * URL to redirect to after logging out.
   */
  logoutRedirectUrl: string
}

const mockResult: MockAuthenticationResult = {
  accessToken: '',
  authRedirectUrl: '',
  logoutRedirectUrl: '',
  userInfo: {
    sub: 'test',
    name: 'Test User',
    preferred_username: 'test',
    given_name: 'Test',
    family_name: 'User',
    email: 'test@postxl.com',
    groups: undefined,
    exp: undefined,
  },
  userRoles: ['admin'],
}

export class MockAuthenticationService {
  public readonly cookieDomain = 'localhost'

  public refreshAccessToken(): Promise<
    | {
        ok: true
        accessToken: string
        refreshToken?: string
        state: null
      }
    | {
        ok: false
        error: unknown
      }
  > {
    return Promise.resolve({ ok: true, accessToken: mockResult.accessToken, state: null }) // NOSONAR - We want to adhere to the interface
  }
  public getAccessTokenFromURL(): Promise<
    | {
        ok: true
        accessToken: string
        state: null
      }
    | {
        ok: false
        error: unknown
      }
  > {
    return Promise.resolve({ ok: true, accessToken: mockResult.accessToken, state: null }) // NOSONAR - We want to adhere to the interface
  }
  public getAuthenticationUrl(): Promise<string> {
    return Promise.resolve(mockResult.authRedirectUrl) // NOSONAR - We want to adhere to the interface
  }

  public async getUserInfoFromRequest(): Promise<{ ok: true; userInfo: UserInfo } | { ok: false }> {
    const info = await this.getUserInfo()

    return info
  }

  public getUserInfo(): Promise<{ ok: true; userInfo: UserInfo } | { ok: false }> {
    // NOSONAR - We want to keep all validations async to adhere to the same interface
    return Promise.resolve({
      ok: true,
      userInfo: mockResult.userInfo,
    })
  }

  public async getUserRolesFromRequest(): Promise<{ ok: true; userRoles: UserRoles } | { ok: false }> {
    const roles = await this.getUserRoles()

    return roles
  }

  public getUserRoles(): Promise<{ ok: true; userRoles: UserRoles } | { ok: false }> {
    return Promise.resolve({ ok: true, userRoles: mockResult.userRoles }) // NOSONAR - We want to adhere to the interface
  }
  public getLogoutUrl(): Promise<string> {
    return Promise.resolve(mockResult.logoutRedirectUrl) // NOSONAR - We want to adhere to the interface
  }
}
