import type { HttpContext } from '@adonisjs/core/http';
import User from '#models/user';
// import { RenderResponse } from '@ioc:EidelLev/Inertia';
import TwoFactorAuthProvider from '#app/services/TwoFactorAuthProvider';
import hash from '@adonisjs/core/services/hash';
// import { schema, rules } from '@adonisjs/validator';
import vine from '@vinejs/vine';
import BackupCodeStorage, { SecureRandom } from '#services/backup_code_storage';

// Here we are generating secret and recovery codes for the user that’s enabling 2FA and storing them to our database.
export default class UserController {
    /**
     * Show the user a form to change their personal information & password.
     *
     * @return — \Inertia\Response
     */
    public async accountInfo({ inertia, auth }: HttpContext) {
        // const user = auth.user;
        const user = (await User.find(auth.user?.id)) as User;
        // const id = request.param('id');
        // const user = await User.query().where('id', id).firstOrFail();

        let storage = new BackupCodeStorage(new SecureRandom());
        // const codes=  user.isTwoFactorEnabled? (await user.getBackupCodes()).map((role) => role.code) : [];
        let backupState = await storage.getBackupCodesState(user);

        return inertia.render('Auth/AccountInfo', {
            user: user,
            twoFactorEnabled: user.isTwoFactorEnabled,
            // code: await TwoFactorAuthProvider.generateQrCode(user),
            backupState:  backupState,
        });
    }

    public async accountInfoStore({ auth, request, response, session }: HttpContext) {
        // const passwordSchema = schema.create({
        //     old_password: schema.string({ trim: true }, [rules.required()]),
        //     new_password: schema.string({ trim: true }, [rules.minLength(8), rules.maxLength(255), rules.confirmed('confirm_password')]),
        //     confirm_password: schema.string({ trim: true }, [rules.required()]),
        // });
        const passwordSchema = vine.object({
            // first step
            old_password: vine
                .string()
                .trim()
                .regex(/^[a-zA-Z0-9]+$/),
            new_password: vine.string().confirmed({ confirmationField: 'confirm_password' }).trim().minLength(8).maxLength(255),
        });
        try {
            // await request.validate({ schema: passwordSchema });
            const validator = vine.compile(passwordSchema);
            await request.validateUsing(validator);
        } catch (error) {
            // return response.badRequest(error.messages);
            throw error;
        }
        
        try {
            const user = await auth.user as User;
            const { old_password, new_password } = request.only(['old_password', 'new_password']);

            // if (!(old_password && new_password && confirm_password)) {
            //     return response.status(400).send({ warning: 'Old password and new password are required.' });
            // }

            // Verify if the provided old password matches the user's current password
            const isSame = await hash.verify(user.password, old_password);
            if (!isSame) {
                return response.flash('warning', 'Old password is incorrect.').redirect().back();
            }

            // Hash the new password before updating the user's password
            user.password = new_password;
            await user.save();

            // return response.status(200).send({ message: 'Password updated successfully.' });
            session.flash({ message: 'Password updated successfully.' });
            return response.redirect().toRoute('settings.user');
        } catch (error) {
            // return response.status(500).send({ message: 'Internal server error.' });
            return response.flash('warning', `Invalid server state. Internal server error.`).redirect().back();
        }
    }

    public async enableTwoFactorAuthentication({ auth, response, session }: HttpContext): Promise<void> {
        // const user: User | undefined = auth?.user;
        const user = (await User.find(auth.user?.id)) as User;

        user.twoFactorSecret = TwoFactorAuthProvider.generateSecret(user);
        user.twoFactorRecoveryCodes = await TwoFactorAuthProvider.generateRecoveryCodes();
        await user.save();

        session.flash('message', 'Two factor authentication enabled.');
        return response.redirect().back();
        // return inertia.render('Auth/AccountInfo', {
        //     // status: {
        //     //     type: 'success',
        //     //     message: 'Two factor authentication enabled.',
        //     // },
        //     user: user,
        //     twoFactorEnabled: user.isTwoFactorEnabled,
        //     code: await TwoFactorAuthProvider.generateQrCode(user),
        //     recoveryCodes: user.twoFactorRecoveryCodes,
        // });
    }

    public async disableTwoFactorAuthentication({ auth, response, session }: HttpContext): Promise<void> {
        const user: User | undefined = auth.user;

        if (user) {
            user.twoFactorSecret = null;
            user.twoFactorRecoveryCodes = null;
            await user.save();
            session.flash('message', 'Two-factor authentication disabled.');
        } else {
            session.flash('error', 'User not found.');
        }
    
        return response.redirect().back();
        // return inertia.render('Auth/AccountInfo', {
        //     // status: {
        //     //     type: 'success',
        //     //     message: 'Two factor authentication disabled.',
        //     // },
        //     user: user,
        //     twoFactorEnabled: user.isTwoFactorEnabled,
        // });
    }

    // public async fetchRecoveryCodes({ auth, view }) {
    //     const user = auth?.user;

    //     return view.render('pages/settings', {
    //         twoFactorEnabled: user.isTwoFactorEnabled,
    //         recoveryCodes: user.twoFactorRecoveryCodes,
    //     });
    // }
}
