import { IsEmail, IsOptional, IsString } from 'class-validator';
import { getConnectionManager } from 'typeorm';
import { ResetAlreadyRequestedError, UserDisabledError, UserNotFoundError } from '../../errors/AuthError';
import { UsernameOrEmailNeededError } from '../../errors/UserErrors';
import { JwtCreator } from '../../jwtcreator';
import { User } from '../entities/User';

/**
 * This calss is used to create password reset tokens for users.
 * These password reset token can be used to set a new password for the user for the next 15mins.
 */
export class CreateResetToken {
    /**
     * The username of the user that wants to reset their password.
     */
    @IsOptional()
    @IsString()
    username?: string;

    /**
     * The email address of the user that wants to reset their password.
     */
    @IsOptional()
    @IsEmail()
    @IsString()
    email?: string;


    /**
     * Create a password reset token based on this.
     */
    public async toResetToken(): Promise<any> {
        if (this.email === undefined && this.username === undefined) {
            throw new UsernameOrEmailNeededError();
        }
        let found_user = await getConnectionManager().get().getRepository(User).findOne({ where: [{ username: this.username }, { email: this.email }] });
        if (!found_user) { throw new UserNotFoundError(); }
        if (found_user.enabled == false) { throw new UserDisabledError(); }
        if (found_user.resetRequestedTimestamp > (Math.floor(Date.now() / 1000) - 15 * 60)) { throw new ResetAlreadyRequestedError(); }

        found_user.refreshTokenCount = found_user.refreshTokenCount + 1;
        found_user.resetRequestedTimestamp = Math.floor(Date.now() / 1000);
        await getConnectionManager().get().getRepository(User).save(found_user);

        //Create the reset token
        let reset_token = JwtCreator.createReset(found_user);

        return reset_token;
    }
}