import type { HttpContext } from '@adonisjs/core/http';
import User from '#models/user';
import Role from '#models/role';
import { ModelQueryBuilderContract } from '@adonisjs/lucid/types/model';
import { createUserValidator, updateUserValidator } from '#validators/user';
// import { schema, rules } from '@ioc:Adonis/Core/Validator';
// import Hash from '@ioc:Adonis/Core/Hash';
// import { schema, rules } from '@ioc:Adonis/Core/Validator';

export default class AdminuserController {
    public async index({ auth, request, inertia }: HttpContext) {
        const page = request.input('page', 1);
        // const limit = 10

        let users: ModelQueryBuilderContract<typeof User, User> = User.query();

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

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

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

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

        let usersResult = await users // User.query()
            // .orderBy('login')
            // .filter(qs)
            // .preload('focusInterests')
            // .preload('role')
            .paginate(page, 10);

        // var test = request.all();

        return inertia.render('Admin/User/Index', {
            // testing: 'this is a test',
            users: usersResult.toJSON(),
            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 }: HttpContext) {
        // let rolesPluck = {};
        // (await Role.query().select('id', 'name')).forEach((user) => {
        // 	rolesPluck[user.id] = user.name;
        // });
        const roles = await Role.query().select('id', 'name').pluck('name', 'id');

        return inertia.render('Admin/User/Create', {
            roles: roles,
        });
    }

    public async store({ request, response, session }: HttpContext) {
        // node ace make:validator CreateUser
        try {
            //  Step 2 - Validate request body against  the schema
            // await request.validate(CreateUserValidator);
            await request.validateUsing(createUserValidator);
            // console.log({ payload });
        } catch (error) {
            // Step 3 - Handle errors
            // return response.badRequest(error.messages);
            throw error;
        }
       
        const input: Record<string, any> = request.only(['login', 'email','first_name', 'last_name']);
        input.password = request.input('new_password'); 
        const user = await User.create(input);
        if (request.input('roles')) {
            const roles: Array<number> = request.input('roles');
            await user.related('roles').attach(roles);
        }

        session.flash('message', 'User has been created successfully');
        return response.redirect().toRoute('settings.user.index');
    }
    public async show({ request, inertia }: HttpContext) {
        const id = request.param('id');
        const user = await User.query().where('id', id).firstOrFail();

        const roles = await Role.query().pluck('name', 'id');
        // const userHasRoles = user.roles;
        const userRoles = await user.related('roles').query().orderBy('name').pluck('id');

        return inertia.render('Admin/User/Show', {
            roles: roles,
            user: user,
            userHasRoles: userRoles,
        });
    }

    public async edit({ request, inertia }: HttpContext) {
        const id = request.param('id');
        const user = await User.query().where('id', id).firstOrFail();

        const roles = await Role.query().pluck('name', 'id');
        // const userHasRoles = user.roles;
        const userHasRoles = await user.related('roles').query().orderBy('name').pluck('id');
        // let test = Object.keys(userHasRoles).map((key) => userHasRoles[key]);
        return inertia.render('Admin/User/Edit', {
            roles: roles,
            user: user,
            userHasRoles: Object.keys(userHasRoles).map((key) => userHasRoles[key]), //convert object to array with role ids
        });
    }

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

        // validate update form
        await request.validateUsing(updateUserValidator, {
            meta: {
                objId: user.id,
            },
        });

        // password is optional
        let input: Record<string, any>;

        if (request.input('new_password')) {
            input = request.only(['login', 'email', 'first_name', 'last_name']);
            input.password = request.input('new_password');
        } else {
            input = request.only(['login', 'email', 'first_name', 'last_name']);
        }
        await user.merge(input).save();
        // await user.save();

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

        session.flash('message', 'User has been updated successfully');
        return response.redirect().toRoute('settings.user.index');
    }
    public async destroy({ request, response, session }: HttpContext) {
        const id = request.param('id');
        const user = await User.findOrFail(id);
        await user.delete();

        session.flash('message', `User ${user.login} has been deleted.`);
        return response.redirect().toRoute('settings.user.index');
    }

    // private async syncRoles(objId: number, roleIds: Array<number>) {
    // 	const user = await User.findOrFail(objId)
    // 	// const roles: Role[] = await Role.query().whereIn('id', roleIds);

    // 	// await user.roles().sync(roles.rows.map(role => role.id))
    // 	await user.related("roles").sync(roleIds);

    // 	return user
    //   }
}
