import LoginCode from '#models/login_code'
import UserTransformer from '#transformers/user_transformer'
import { issueTokenPair } from '#controllers/access_tokens_controller'
import type { HttpContext } from '@adonisjs/core/http'
import { createHash } from 'node:crypto'
import { DateTime } from 'luxon'

export default class MobileAuthController {
  async exchange({ request, response, serialize }: HttpContext) {
    const { code } = request.only(['code'])

    if (!code) {
      return response.badRequest({
        message: 'Login code is required',
      })
    }

    const codeHash = createHash('sha256').update(code).digest('hex')

    const loginCode = await LoginCode.query()
      .where('code_hash', codeHash)
      .whereNull('used_at')
      .preload('user', (query) => {
        query.preload('userPref').preload('roles')
      })
      .first()

    if (!loginCode) {
      return response.unauthorized({
        message: 'Invalid or already used login code',
      })
    }

    if (loginCode.expiresAt <= DateTime.now()) {
      return response.unauthorized({
        message: 'Login code has expired',
      })
    }

    // Consume the code so it cannot be used again.
    loginCode.usedAt = DateTime.now()
    await loginCode.save()

    const { accessToken, refreshToken } = await issueTokenPair(loginCode.user)

    return serialize({
      user: UserTransformer.transform(loginCode.user),
      accessToken,
      refreshToken,
    })
  }
}
