import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import User, { UserRoles } from 'App/Models/User'
import PaginationService from 'App/Services/PaginationService'
import { schema, rules } from '@ioc:Adonis/Core/Validator'
import randomstring from 'randomstring'
import Database from '@ioc:Adonis/Lucid/Database'
import { HttpException } from '@adonisjs/http-server/build/src/Exceptions/HttpException'
import { HttpStatusCode } from 'axios'

export default class UsersController {
    private paginationService = new PaginationService(User)

    public async index({ request }: HttpContextContract) {
        return await this.paginationService.paginate(request.all())
    }

    public async store({ request }: HttpContextContract) {
        await request.validate({
            schema: schema.create({
                username: schema.string([])
            })
        })
        return await User.create(request.all())
    }

    public async newAdminUser({ request, bouncer }: HttpContextContract) {
        await bouncer.authorize('admin')
        const data = await request.validate({
            schema: schema.create({
                username: schema.string([]),
                password: schema.string([]),
                email: schema.string.optional([rules.email()])
            })
        })
        return await User.create({
            ...data,
            role: UserRoles.Admin
        })
    }

    public async show({ params }: HttpContextContract) {
        return await User.findOrFail(params.id)
    }

    public async update({ params, request }: HttpContextContract) {
        const user = await User.findOrFail(params.id)
        const payload = await request.validate({
            schema: schema.create({
                username: schema.string.optional([rules.maxLength(20)]),
                avatar: schema.string.optional([rules.maxLength(255)])
            })
        })
        user.merge(payload)
        return await user.save()
    }

    public async updatePassword({ params, request, auth }: HttpContextContract) {
        if (!auth.user) {
            throw new HttpException('Unauthorized', HttpStatusCode.BadRequest)
        }
        const user = await User.findOrFail(auth.user.id)
        const payload = await request.validate({
            schema: schema.create({
                password: schema.string([rules.minLength(6), rules.maxLength(18)])
            })
        })
        user.password = payload.password
        return await user.save()
    }

    public async destroy({ params }: HttpContextContract) {
        const user = await User.findOrFail(params.id)
        await user.delete()
    }

    public async my({ auth }: HttpContextContract) {
        return auth.user
    }

    public async myAdmin({ auth, bouncer }: HttpContextContract) {
        // await bouncer.authorize('admin')
        return auth.user
    }

    public async guest({ auth }: HttpContextContract) {
        const user = await User.create({
            username: 'fs_' + randomstring.generate(8),
            email: randomstring.generate(8) + '@guest.com',
            visitor: true
        })

        return {
            user,
            token: (await auth.use('api').generate(user)).token
        }
    }

    public async invited({ auth }: HttpContextContract) {
        return (
            await Database.from('users').where('referrer', auth.user!.id).count('*', 'count')
        )[0]
    }
}
