import oidc, { User } from 'oidc-client'

const log = globalThis.console

export const oidcManager = new oidc.UserManager({
  userStore: new oidc.WebStorageStateStore({}),
  authority: import.meta.env.VUE_APP_API_STEERING_OIDC_URI,
  client_id: import.meta.env.VUE_APP_OIDC_CLIENT_ID,
  redirect_uri: import.meta.env.VUE_APP_API_STEERING_OIDC_REDIRECT_URI,
  silent_redirect_uri: import.meta.env.VUE_APP_API_STEERING_OIDC_REDIRECT_URI_SILENT,
  accessTokenExpiringNotificationTime: import.meta.env
    .VUE_APP_API_STEERING_OIDC_EXPIRE_NOTIFICATION,
  response_type: 'id_token token',
  scope: 'openid profile email username aura_shows',
  post_logout_redirect_uri: import.meta.env.VUE_APP_API_STEERING_OIDC_REDIRECT_URI_POSTLOGOUT,
  loadUserInfo: true,
})

export class OIDCError extends Error {}
export class OIDCNoUserError extends OIDCError {}

export async function getUser(): Promise<User> {
  let user: User | null

  try {
    user = await oidcManager.getUser()
  } catch (e) {
    log.error('Could not fetch OIDC user object.', e)
    throw new OIDCError('Unable to fetch OIDC user.')
  }

  if (user === null) {
    throw new OIDCNoUserError()
  }

  const expiry = new Date(user.expires_at * 1000)
  // If we have a token, but it has already expired, log out the user
  if (expiry <= new Date()) {
    log.debug(`Token has already expired at ${expiry.toLocaleString()}. Logging out...`)
    await logoutRedirect()
    throw new OIDCNoUserError()
  }

  return user
}

export async function logoutRedirect() {
  try {
    await oidcManager.signoutRedirect()
    log.debug('Signed out.')
  } catch (e) {
    log.error('Unable to logout.', e)
  }
}

export async function loginRedirect() {
  try {
    await oidcManager.signinRedirect()
  } catch (e) {
    log.error('Unable to login', e)
  }
}