import type { HttpContext } from '@adonisjs/core/http'
import { registerValidator, loginValidator } from '#validators/auth'
import User from '#models/user'
import logger from '@adonisjs/core/services/logger'

export default class AuthController {
  /**
   * Registers a user using the provided email, password, and full name.
   *
   * @bodyParam *email* - string | The email of the user.
   * @bodyParam *password* - string | The password of the user.
   * @bodyParam *fullName* - string | The full name of the user.
   * @returns The user access token.
   */
  async register({ request }: HttpContext) {
    try {
      const data = await request.validateUsing(registerValidator)
      const user = await User.create(data)
      logger.info('User registered: %s, %s, %s', user.fullName, user.email, request.ip())
      return User.accessTokens.create(user)
    } catch (error) {
      logger.error('Registration failed: %s', error)
      throw error
    }
  }

  /**
   * Log in a user using the provided email and password.
   *
   * @bodyParam *email* -  string | The email of the user.
   * @bodyParam *password* -  string | The password of the user.
   * @returns The access token of the user.
   */
  async login({ request }: HttpContext) {
    try {
      const { email, password } = await request.validateUsing(loginValidator)
      const user = await User.verifyCredentials(email, password)
      logger.info('User logged in: %s', email)
      return User.accessTokens.create(user)
    } catch (error) {
      logger.error('Login failed: %s', error)
      throw error
    }
  }

  /**
   * Deletes the user's access token and logs them out. If the user is not
   * authenticated, returns an unauthorized message.
   */
  async logout({ auth }: HttpContext) {
    const user = auth.user!
    logger.info('User logout: %s', auth.getUserOrFail().email)
    try {
      await User.accessTokens.delete(user, user.currentAccessToken.identifier)
      return { message: 'User logged out' }
    } catch (error) {
      logger.error('Logout failed: %s', error)
      throw error
    }
  }

  /**
   * Retrieves the authenticated user's information if authenticated,
   * otherwise deletes the access token and returns an unauthorized message.
   *
   * @param auth - The HTTP context's auth object.
   * @returns An object containing the user data if authenticated,
   *          otherwise an unauthorized message.
   */

  async me({ auth }: HttpContext) {
    if (await auth.check()) {
      return { user: auth.user }
    } else {
      await User.accessTokens.delete(auth.user!, auth.user!.currentAccessToken.identifier)
      return { message: 'Unauthorized' }
    }
  }
}
