'use strict';

var q = require("q");

var MongoConnection = require('./MongoConnection');
var SharedConstants = require('../../../../shared/constants/SharedConstants');
var logger = require('../../../utils/Logger').loggers.get('db');
var UtilError = require('../../../utils/UtilError');
var ErrorCodes = require("../../../../shared/constants/ErrorCodes");

function getAccountByIdWithCollection (collection, userId) {
    var deferred = q.defer();


    var query = {"documentId": userId,
        "systemHeader.systemType": SharedConstants.SYSTEM_TYPE_ACCOUNT,
        "systemHeader.currentVersion": true,
        "systemHeader.deleted": {$ne: true}
    };

    collection.findOne(query, function (queryErr, user) {
        if (queryErr) {
            var errorMsg = "Error getting user: " + queryErr;
            logger.error(errorMsg);
            deferred.reject(new Error(errorMsg));
        } else {
            if(!user) {
                deferred.reject(new UtilError.AccountNotFoundError("User not found."));
            } else {
                if (user.systemHeader && user.systemHeader.deleted){
                    var deletedMsg = "User is deleted";
                    logger.error(deletedMsg);
                    var error = new Error(deletedMsg);
                    deferred.reject(error);
                } else {
                    deferred.resolve(user);
                }
            }
        }
    });

    // Don't check the permissions on getting the template.
    // The user may not have access to the template but the template needs to be read to check the permissions
    return deferred.promise;
}

var getAccountById = function (userId, connectionName) {
    var deferred = q.defer();

    MongoConnection.getCollection(function (err, collection) {
        if (err) {
            var errorMsg = "Error creating collection in getAccountById: " + err;
            logger.error(errorMsg);
            deferred.reject(new Error(errorMsg));
        } else {
            getAccountByIdWithCollection(collection, userId).then(function successFunc(data) {
                    deferred.resolve(data);
                },
                function errorFunc(err) {
                    logger.error("Error in getAccountById: " + err);
                    deferred.reject(err);
                });
        }
    }, connectionName);

    return deferred.promise;
};

var getPasswordResetDocument = function(hash, connectionName){
    var deferred = q.defer();

    MongoConnection.getCollection(function (err, collection) {
        if (err) {
            var errorMsg = "Error creating collection to get password reset document: " + err;
            logger.error(errorMsg);
            deferred.reject(new Error(errorMsg));
        } else {
            var query = {
                "resetTokenText": hash,
                "systemHeader.systemType" : SharedConstants.SYSTEM_TYPE_PASSWORD_RESET,
                "systemHeader.currentVersion": true,
                "systemHeader.deleted": {$ne: true},
                "isActiveBool" : true,
                "passwordResetExpiryDate": {"$gte": new Date() }

            };

            collection.findOne(query, function (err, resetDoc) {
                if (err) {
                    var errorMsg = "Error getting password reset document: " + err;
                    logger.error(errorMsg);
                    deferred.reject(new Error(errorMsg));
                } else {
                    logger.info('password reset document found');
                    deferred.resolve(resetDoc);
                }
            });
        }

    });

    return deferred.promise;
};

const getAccountByQuery = (email, accountSocialMediaId) => {

    let deferred = q.defer();

    MongoConnection.getCollection(function (err, collection) {
        if (err) {
            const errorMsg = "Error creating collection to get account by query: " + err;
            let error = new Error(errorMsg);
            deferred.reject(error);
        } else {
            let regexEmail = '^' + email + '$';
            let query = {
                "email": { $regex: regexEmail, '$options' : 'i' }
            };
            if(accountSocialMediaId){
                query.userId = accountSocialMediaId;
            }
            query["systemHeader.systemType"] = SharedConstants.SYSTEM_TYPE_ACCOUNT;
            query["systemHeader.deleted"] = { "$ne": true };
            query["systemHeader.currentVersion"] = true;

            collection.find(query).toArray(
                function (queryErr, results) {
                    if (queryErr) {
                        deferred.reject(err);
                    }else {
                        if(results.length > 1){

                            let message = "Error on login - " + ErrorCodes.ERROR_DUPLICATE_ACCOUNT_EMAIL
                                + ": There is more than one account with the same email. " +
                              "There cannot be two accounts with the same email and a different case.";

                            let error = new Error(message);
                            error.errorCode = ErrorCodes.ERROR_DUPLICATE_ACCOUNT_EMAIL;

                            deferred.reject(error);
                        }
                        deferred.resolve(results[0]);
                    }
                });
        }

    });

    return deferred.promise;
};

const getAccountByApiKey = (apiKey, apiHosts) => {

    let deferred = q.defer();

    MongoConnection.getCollection(function (err, collection) {
        if (err) {
            const errorMsg = "Error creating collection to get account by ApiKey: " + err;

            let error = new Error(errorMsg);
            error.errorCode = ErrorCodes.ERROR_DUPLICATE_ACCOUNT_EMAIL;
            deferred.reject(error);
        } else {
            let query = {};
            query["apiKey"] = apiKey;
            query["apiHosts"] = { $in: apiHosts};
            query["systemHeader.systemType"] = SharedConstants.SYSTEM_TYPE_ACCOUNT_SECURITY;
            query["systemHeader.deleted"] = { "$ne": true };
            query["systemHeader.currentVersion"] = true;

            collection.find(query).toArray(
                function (queryErr, results) {
                    if (queryErr) {
                        deferred.reject(err);
                    }else {
                        deferred.resolve(results);
                    }
                });
        }

    });

    return deferred.promise;
};

module.exports = {

    getAccountById: getAccountById,

    // the insertWithCollection function should be preferred if a collection has already been opened. This allows the same
    // collection to be used
    getAccountByIdWithCollection: getAccountByIdWithCollection,

    /*
     getAccount
     parameters:
     email - account email
     verified - get results whether verified or not
     provider - social login provider, default local
     userId - social id of the user
     */
    getAccount: function(email, provider, accountSocialMediaId) {

        if(true){
            var msg = 'MongoAccountDataService.getAccount is longer supported. ' +
                'Use AccountService.getAccount instead. See issue 12225 for more info. ';
            logger.error(msg);
            return Promise.reject(new Error(msg));
        }

        var deferred = q.defer();

        logger.debug("Getting Account: " + email);
        MongoConnection.getCollection(function (err, collection) {
            if (err) {
                var errorMsg = "Error creating collection to get account: " + err;
                logger.error(errorMsg);
                deferred.reject(new Error(errorMsg));
            } else {
                var query = {
                    "provider": "local",
                    "systemHeader.systemType" : SharedConstants.SYSTEM_TYPE_ACCOUNT,
                    "systemHeader.currentVersion": true,
                    "systemHeader.deleted": {$ne: true}
                };

                if (email) {
                    query.email = {
                        $regex: new RegExp(email, "i")
                    };
                }

                if (provider) {
                    query.provider = provider;
                }

                if (accountSocialMediaId) {
                    query.userId = accountSocialMediaId;
                }

                collection.findOne(query, function (err, account) {
                    if (err) {
                        var errorMsg = "Error getting account: " + err;
                        logger.error(errorMsg);
                        deferred.reject(new Error(errorMsg));
                    } else {
                        logger.info('account found');
                        deferred.resolve(account);
                    }
                });
            }

        });

        return deferred.promise;
    },

    getPasswordResetDocument: getPasswordResetDocument,

    getAccountByQuery: getAccountByQuery,

    getAccountByApiKey: getAccountByApiKey,

    getAccountUtilityDocumentsQuery: function(accountId, type){

        var query = {};
        query["accountRel.documentId"] = accountId;
        query["systemHeader.systemType"] = type;

        return query;
    },

    getCheckExistedAccountQuery: function(email){

      let regexEmail = '^' + email + '$';
      let query = {
        "email": { $regex: regexEmail, '$options' : 'i' }
      };

      return query;
    }
};

