import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
import Role from 'App/Models/Role';
import Permission from 'App/Models/Permission';
import type { ModelQueryBuilderContract } from '@ioc:Adonis/Lucid/Orm';
import CreateRoleValidator from 'App/Validators/CreateRoleValidator';
import UpdateRoleValidator from 'App/Validators/UpdateRoleValidator';
import { RenderResponse } from '@ioc:EidelLev/Inertia';
// import { schema, rules } from '@ioc:Adonis/Core/Validator';

export default class RoleController {
    public async index({ auth, request, inertia }: HttpContextContract) {
        let roles: ModelQueryBuilderContract<typeof Role, Role> = Role.query();

        if (request.input('search')) {
            // users = users.whereRaw('name like %?%', [request.input('search')])
            const searchTerm = request.input('search');
            roles.where('name', 'ilike', `%${searchTerm}%`);
        }

        if (request.input('sort')) {
            type SortOrder = 'asc' | 'desc' | undefined;
            let attribute = request.input('sort');
            let sortOrder: SortOrder = 'asc';

            if (attribute.substr(0, 1) === '-') {
                sortOrder = 'desc';
                // attribute = substr(attribute, 1);
                attribute = attribute.substr(1);
            }
            roles.orderBy(attribute, sortOrder);
        } else {
            // users.orderBy('created_at', 'desc');
            roles.orderBy('id', 'asc');
        }

        // const users = await User.query().orderBy('login').paginate(page, limit);
        let rolesResult = await roles;

        return inertia.render('Admin/Role/Index', {
            // testing: 'this is a test',
            roles: rolesResult,
            filters: request.all(),
            can: {
                create: await auth.user?.can(['user-create']),
                edit: await auth.user?.can(['user-edit']),
                delete: await auth.user?.can(['user-delete']),
            },
        });
    }

    public async create({ inertia }: HttpContextContract) {
        const permissions = await Permission.query().select('id', 'name').pluck('name', 'id');
        return inertia.render('Admin/Role/Create', {
            permissions: permissions,
        });
    }

    public async store({ request, response, session }: HttpContextContract) {
        // node ace make:validator CreateUser
        try {
            //  Step 2 - Validate request body against  the schema
            await request.validate(CreateRoleValidator);
            // await request.validate({ schema: roleSchema });
            // console.log({ payload });
        } catch (error) {
            // Step 3 - Handle errors
            // return response.badRequest(error.messages);
            throw error;
        }
        const input = request.only(['name', 'display_name', 'description']);
        const role = await Role.create(input);

        if (request.input('permissions')) {
            const permissions: Array<number> = request.input('permissions');
            await role.related('permissions').attach(permissions);
        }

        session.flash('message', `Role ${role.name} has been created successfully`);
        return response.redirect().toRoute('role.index');
    }

    public async show({ request, inertia }: HttpContextContract): RenderResponse {
        const id = request.param('id');
        const role = await Role.query().where('id', id).firstOrFail();

        const permissions = await Permission.query().pluck('name', 'id');
        // const userHasRoles = user.roles;
        const rolePermsissions = await role.related('permissions').query().orderBy('name').pluck('id');

        return inertia.render('Admin/Role/Show', {
            permissions: permissions,
            role: role,
            roleHasPermissions: rolePermsissions,
        });
    }

    public async edit({ request, inertia }: HttpContextContract) {
        const id = request.param('id');
        const role = await Role.query().where('id', id).firstOrFail();

        const permissions = await Permission.query().pluck('name', 'id');
        // const userHasRoles = user.roles;
        const rolerHasPermissions = await role.related('permissions').query().orderBy('name').pluck('id');

        return inertia.render('Admin/Role/Edit', {
            permissions: permissions,
            role: role,
            roleHasPermissions: Object.keys(rolerHasPermissions).map((key) => rolerHasPermissions[key]), //convert object to array with role ids
        });
    }

    public async update({ request, response, session }: HttpContextContract) {
        // node ace make:validator UpdateUser
        const id = request.param('id');
        const role = await Role.query().where('id', id).firstOrFail();

        // validate update form
        await request.validate(UpdateRoleValidator);

        // password is optional

        const input = request.only(['name', 'description']);
        await role.merge(input).save();
        // await user.save();

        if (request.input('permissions')) {
            const permissions: Array<number> = request.input('permissions');
            await role.related('permissions').sync(permissions);
        }

        session.flash('message', 'Role has been updated successfully');
        return response.redirect().toRoute('role.index');
    }

    public async destroy({ request, response, session }: HttpContextContract) {
        const id = request.param('id');
        const role = await Role.findOrFail(id);
        await role.delete();

        session.flash('message', `Role ${role.name} has been deleted.`);
        return response.redirect().toRoute('role.index');
    }
}
