import {
  SdkBase,
  E_RESPONSE_STATUS,
  E_RESPONSE_NO_VALUE,
  E_INVALID_JSON,
  E_RESPONSE_UNKNOWN,
  SdkOptions,
} from './SdkBase.js'
import { RouteBuilder } from './RouteBuilder.js'
import { IUser } from '../models/store/User.js'
import { Exception } from '../exceptions/exception.js'

export interface IJwtInfo {
  /**
   * The information about the user that is read from the JWT.
   */
  data: IJwtUser
  /**
   * The name of the provider.
   */
  provider: string
}

export interface IJwtUser {
  /**
   * The provider's unique ID.
   */
  id: string
  /**
   * The user's email address.
   */
  email: string
  /**
   * true, if the provider has verified the email address.
   */
  email_verified: boolean
  /**
   * The user's full name.
   */
  name: string
  /**
   * If present, a URL to user's profile picture
   */
  picture?: string
  given_name?: string
  family_name?: string
  /**
   * If present, the host domain of the user's GSuite email address.
   * Google specific.
   */
  hd?: string
}

export interface IRegistrationInfo {
  reason: 'new-organization' | 'existing-organization'
  /**
   * The decoded JWT user information.
   * Used to create a user account.
   */
  user: IJwtInfo
}

export interface IOrganizationRegistrationInfo extends IRegistrationInfo {
  reason: 'new-organization'
  /**
   * The name of the organization to create for the user.
   */
  organizationName: string
}

export interface IOrganizationAddUserInfo extends IRegistrationInfo {
  reason: 'existing-organization'
  /**
   * Set when adding a user to an existing organization.
   */
  organizationId: string
  /**
   * The invitation code used to invite the user.
   */
  invitation: string
}

export class UsersSdk extends SdkBase {
  /**
   * Reads the current user.
   * @param request Optional request options.
   */
  async me(request: SdkOptions = {}): Promise<IUser> {
    const { token } = request
    const url = this.sdk.getUrl(RouteBuilder.usersMe())
    const result = await this.sdk.http.get(url.toString(), { token })
    this.inspectCommonStatusCodes(result)
    const E_PREFIX = 'Unable to read a user. '
    if (result.status !== 200) {
      this.logInvalidResponse(result)
      throw this.createApiError(`${E_PREFIX}${E_RESPONSE_STATUS}${result.status}`, result.body)
    }
    if (!result.body) {
      throw new Exception(`${E_PREFIX}${E_RESPONSE_NO_VALUE}`, { code: 'E_RESPONSE_NO_VALUE', status: result.status })
    }
    let data: IUser
    try {
      data = JSON.parse(result.body)
    } catch {
      throw new Exception(`${E_PREFIX}${E_INVALID_JSON}`, { code: 'E_INVALID_JSON', status: result.status })
    }
    if (!data.key) {
      throw new Exception(`${E_PREFIX}${E_RESPONSE_UNKNOWN}`, { code: 'E_RESPONSE_UNKNOWN', status: result.status })
    }
    return data
  }
}
