"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const models_1 = require("../users/models");
const helpers_1 = __importDefault(require("../../utils/helpers"));
const constants_1 = __importDefault(require("../../utils/constants"));
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
const services_1 = __importDefault(require("../../utils/services"));
function postLogin(req, res) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            let { email, password, phone, remember, platform, fcmToken } = req.body;
            if (typeof remember !== 'boolean') {
                remember = true;
            }
            const user = yield models_1.User.findOne({ email });
            if (!user) {
                return res.status(401).json({ message: 'authentication failed' });
            }
            if (user.deactivatedAt) {
                return res.status(403).json({ message: 'Account is currently scheduled for deletion, It will be automatically deleted within 7 days' });
            }
            if (user.terminated) {
                return res.status(403).json({ message: 'Your account has been terminated due to a violation of our Terms and Conditions and in accordance with our Privacy Policy.', terminated: true });
            }
            const hash = helpers_1.default.getHash(password);
            if (user.auth.password !== hash) {
                return res.status(401).json({ message: 'authentication failed' });
            }
            if (!user.auth.emailVerified) {
                return res.status(403).json({ message: 'Please verify your email first', verificationRequired: true });
            }
            if (user.auth.twoFactorAuthentication) {
                if (phone && !user.phone) {
                    return res.status(404).json({ message: 'User with this phone don\'t exist' });
                }
                const payload = { _id: `${user._id}`, phone, remember, platform };
                // @ts-ignore
                const tfaToken = jsonwebtoken_1.default.sign(payload, process.env.JWT_SECRET, { expiresIn: '5m' });
                yield services_1.default.sendOtp(user, phone ? 'phone' : 'email');
                return res.json({ '2faToken': tfaToken });
            }
            const token = yield services_1.default.createLoggedinDevice(user, platform, fcmToken, remember);
            return res.json({ token, id: user._id });
        }
        catch (error) {
            console.log(error);
            return res.status(500).json({ message: 'server error' });
        }
    });
}
function postGoogleLogin(req, res) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            let { googleToken, platform, remember, fcmToken } = req.body;
            const decoded = yield helpers_1.default.decodeGoogleToken(googleToken, process.env.GOOGLE_CLIENT_ID);
            if (!decoded) {
                return res.status(401).json({ message: 'authentication failed' });
            }
            const user = yield models_1.User.findOne({ email: decoded.email });
            if (!user) {
                return res.status(404).json({ message: 'user not found, registration required', decoded });
            }
            if (user.deactivatedAt) {
                return res.status(403).json({ message: 'Account is currently scheduled for deletion, It will be automatically deleted within 7 days' });
            }
            if (user.terminated) {
                return res.status(403).json({ message: 'Your account has been terminated due to a violation of our Terms and Conditions and in accordance with our Privacy Policy.', terminated: true });
            }
            if (!user.auth.emailVerified) {
                return res.status(403).json({ message: 'Please verify your email first', verificationRequired: true, decoded });
            }
            const token = yield services_1.default.createLoggedinDevice(user, platform, fcmToken, remember);
            return res.json({ token, id: user._id, decoded });
        }
        catch (error) {
            console.log(error);
            return res.status(500).json({ message: 'server error' });
        }
    });
}
function postRegister(req, res) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            const { dob, email, password } = req.body;
            let user = yield models_1.User.findOne({ email });
            if (user) {
                return res.status(409).json({ message: 'user already exist with this email' });
            }
            const otp = helpers_1.default.getRandomOtp();
            const now = new Date();
            now.setMinutes(now.getMinutes() + constants_1.default.emailOtpExpiry);
            user = yield models_1.User.create({
                dob,
                email,
                auth: {
                    password: helpers_1.default.getHash(password),
                    emailOtp: otp,
                    emailOtpExpiry: now,
                    lastEmailOtpSentAt: new Date()
                }
            });
            yield helpers_1.default.sendOauthGmail(user.email, 'Email Verification OTP', `OTP to verify your email is ${otp}`);
            return res.status(201).json({ message: 'user registered successfully' });
        }
        catch (error) {
            console.log(error);
            return res.status(500).json({ message: 'server error' });
        }
    });
}
function postSendOtp(req, res) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            const { email, phone } = req.body;
            const user = yield models_1.User.findOne({ email });
            if (!user) {
                return res.status(404).json({ message: 'user not found' });
            }
            if (user.deactivatedAt) {
                return res.status(403).json({ message: 'Account is currently scheduled for deletion, It will be automatically deleted within 7 days' });
            }
            if (user.terminated) {
                return res.status(403).json({ message: 'Your account has been terminated due to a violation of our Terms and Conditions and in accordance with our Privacy Policy.', terminated: true });
            }
            if (phone && !user.phone) {
                return res.status(404).json({ message: 'user not found' });
            }
            yield services_1.default.sendOtp(user, phone ? 'phone' : 'email');
            return res.json({ message: `${phone ? 'Phone' : 'Email'} OTP sent successfully` });
        }
        catch (error) {
            console.log(error);
            return res.status(500).json({ message: 'server error' });
        }
    });
}
function postCheckOtp(req, res) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            const { email, otp, phone } = req.body;
            const user = yield models_1.User.findOne({ email });
            if (!user) {
                return res.status(404).json({ message: 'user not found' });
            }
            if (user.deactivatedAt) {
                return res.status(403).json({ message: 'Account is currently scheduled for deletion, It will be automatically deleted within 7 days' });
            }
            if (user.terminated) {
                return res.status(403).json({ message: 'Your account has been terminated due to a violation of our Terms and Conditions and in accordance with our Privacy Policy.', terminated: true });
            }
            if (phone && !user.phone) {
                return res.status(404).json({ message: 'user not found' });
            }
            const { status, message, error } = yield services_1.default.checkAndResetOtp(user, otp, phone ? 'phone' : 'email');
            if (error) {
                return res.status(500).json({ message: 'server error' });
            }
            if (status) {
                return res.status(status).json({ message });
            }
            return res.json({ message: `${phone ? 'Phone' : 'Email'} OTP is valid` });
        }
        catch (error) {
            console.log(error);
            return res.status(500).json({ message: 'server error' });
        }
    });
}
function postVerify(req, res) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            const { email, otp, phone, platform, fcmToken } = req.body;
            const user = yield models_1.User.findOne({ email });
            if (!user) {
                return res.status(404).json({ message: 'user not found' });
            }
            if (user.deactivatedAt) {
                return res.status(403).json({ message: 'Account is currently scheduled for deletion, It will be automatically deleted within 7 days' });
            }
            if (user.terminated) {
                return res.status(403).json({ message: 'Your account has been terminated due to a violation of our Terms and Conditions and in accordance with our Privacy Policy.', terminated: true });
            }
            if (phone && !user.phone) {
                return res.status(404).json({ message: 'user not found' });
            }
            if (phone && user.auth.phoneVerified) {
                return res.json({ message: 'phone already verified' });
            }
            if (!phone && user.auth.emailVerified) {
                return res.json({ message: 'email already verified' });
            }
            const { status, message, error } = yield services_1.default.checkAndResetOtp(user, otp, phone ? 'phone' : 'email', true);
            if (error) {
                return res.status(500).json({ message: 'server error' });
            }
            if (status) {
                return res.status(status).json({ message });
            }
            const token = yield services_1.default.createLoggedinDevice(user, platform, fcmToken);
            return res.json({ message: `${phone ? 'Phone' : 'Email'} verified successfully`, token, id: user._id });
        }
        catch (error) {
            console.log(error);
            return res.status(500).json({ message: 'server error' });
        }
    });
}
function postVerify2FA(req, res) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            const { '2faToken': tfaToken, otp, fcmToken } = req.body;
            let payload;
            try {
                payload = jsonwebtoken_1.default.verify(tfaToken, process.env.JWT_SECRET);
            }
            catch (error) {
                return res.status(401).json({ message: 'authentication failed' });
            }
            const { _id, platform, phone, remember } = payload;
            const user = yield models_1.User.findById(_id);
            if (!user) {
                return res.status(404).json({ message: 'user not found' });
            }
            if (user.deactivatedAt) {
                return res.status(403).json({ message: 'Account is currently scheduled for deletion, It will be automatically deleted within 7 days' });
            }
            if (user.terminated) {
                return res.status(403).json({ message: 'Your account has been terminated due to a violation of our Terms and Conditions and in accordance with our Privacy Policy.', terminated: true });
            }
            if (phone && !user.phone) {
                return res.status(404).json({ message: 'user not found' });
            }
            const { status, message, error } = yield services_1.default.checkAndResetOtp(user, otp, phone ? 'phone' : 'email', true);
            if (error) {
                return res.status(500).json({ message: 'server error' });
            }
            if (status) {
                return res.status(status).json({ message });
            }
            const token = yield services_1.default.createLoggedinDevice(user, platform, fcmToken, remember);
            return res.json({ token, id: user._id });
        }
        catch (error) {
            console.log(error);
            return res.status(500).json({ message: 'server error' });
        }
    });
}
function postResetPassword(req, res) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            const { email, otp, password, phone } = req.body;
            const user = yield models_1.User.findOne({ email });
            if (!user) {
                return res.status(404).json({ message: 'user not found' });
            }
            if (user.deactivatedAt) {
                return res.status(403).json({ message: 'Account is currently scheduled for deletion, It will be automatically deleted within 7 days' });
            }
            if (user.terminated) {
                return res.status(403).json({ message: 'Your account has been terminated due to a violation of our Terms and Conditions and in accordance with our Privacy Policy.', terminated: true });
            }
            if (phone && !user.phone) {
                return res.status(404).json({ message: 'user not found' });
            }
            // use services helper function
            const { status, message, error } = yield services_1.default.checkAndResetOtp(user, otp, phone ? 'phone' : 'email', true);
            if (error) {
                return res.status(500).json({ message: 'server error' });
            }
            if (status) {
                return res.status(status).json({ message });
            }
            user.auth.password = helpers_1.default.getHash(password);
            yield user.save();
            return res.json({ message: 'Password updated successfully' });
        }
        catch (error) {
            console.log(error);
            return res.status(500).json({ message: 'server error' });
        }
    });
}
function postLogout(req, res) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            const user = res.locals.user;
            const device = res.locals.device;
            const index = user.auth.loggedinDevices.findIndex(e => e === device);
            user.auth.loggedinDevices.splice(index, 1);
            yield user.save();
            return res.json({ message: 'logged-out successfully' });
        }
        catch (error) {
            console.log(error);
            return res.status(500).json({ message: 'server error' });
        }
    });
}
const controllers = {
    postLogin,
    postGoogleLogin,
    postRegister,
    postSendOtp,
    postCheckOtp,
    postVerify,
    postVerify2FA,
    postResetPassword,
    postLogout
};
exports.default = controllers;
