import User from '../models/User.js';
import bcrypt from 'bcrypt';
import TokenService from './TokenService.js';
import UserDto from '../dtos/UserDto.js';
import jwt from 'jsonwebtoken';
import config from "config";
import sendConfirm from '../messages/confirmEmail.js';
import ApiError from '../controllers/ErrorController.js';
class AuthService {
    async register(user) {
        const candidate = await User.findOne({email: user.email});

        if(candidate) {
            throw ApiError.BadRequest('Пользователь с введенным email уже существует');
        }

        const hashPassword = await bcrypt.hash(user.password, 5);
        const createdUser = await User.create({...user, password: hashPassword});
        await sendConfirm(createdUser.id, createdUser.email);
        const userDto = new UserDto(createdUser);
        const tokens = TokenService.generateTokens({...userDto});
        await TokenService.saveToken(userDto._id, tokens.refreshToken);

        return {...tokens, user: userDto};
    }

    async login(user) {
        const getUser = await User.findOne({email: user.email});

        if(!getUser) {
            throw ApiError.BadRequest('Пользователя с введенным email не существует');
        }

        const isPasswordValid = bcrypt.compareSync(user.password , getUser.password);
        if(!isPasswordValid) {
            throw ApiError.BadRequest('Не верный пароль');
        }
        
        if(!getUser.verify) {
            throw ApiError.BadRequest('Для входа, необходимо подтвердить почту');
        }

        const userDto = new UserDto(getUser);
        const tokens = TokenService.generateTokens({...userDto});
        await TokenService.saveToken(userDto._id, tokens.refreshToken);

        return {...tokens, user: userDto};
    }

    async confirm( { id } ) {
        const candidate = await User.findById(id);

        if(!candidate) {
            throw ApiError.BadRequest('Не верная ссылка для подтверждения аккаунта');
        }

        if(candidate.verify) {
            throw ApiError.BadRequest('Этот аккаунт уже подтвержден');
        }

        candidate.verify = true;
        await candidate.save();

        return {message: "Аккаунт успешно подтвержден, вы можете перейти к форме авторизации"};
    }

    async logout(refreshToken) {
        const token = await TokenService.removeToken(refreshToken);
        return token;
    }

    async refresh(refreshToken) {
        if(!refreshToken) {
            throw ApiError.UnauthorizedError();
        }
        const user = TokenService.validateRefreshToken(refreshToken);
        const getToken = await TokenService.findToken(refreshToken);
        if(!user || !getToken ) {
            throw ApiError.UnauthorizedError();
        }

        const getUser = await User.findById(user._id)
        const userDto = new UserDto(getUser);
        const tokens = TokenService.generateTokens({...userDto});
        await TokenService.saveToken(userDto._id, tokens.refreshToken);

        return {...tokens, user: userDto};
    }
}

export default new AuthService();