'use strict';

var q = require('q');
var cbConnection = require('./CouchbaseConnection');
var SharedConstants = require('../../../../shared/constants/SharedConstants');
var logger = require('../../../utils/Logger').loggers.get('db');
var lodashLang = require('lodash/lang');
var cbUtil = require('./CouchbaseUtil');
var cbBucket;
var ErrorCodes = require("../../../../shared/constants/ErrorCodes");

var getAccountById = function(userId, connectionName, isPublicAccount) {
    logger.info('Invoke getAccountById function in CouchbaseDataService');
    var deferred = q.defer();

    var bucketName = cbConnection.getConfig(connectionName).bucket;

    var statement = "SELECT `" + bucketName + "`.* FROM `" + bucketName + "` " +
        "WHERE documentId = $1 AND systemHeader.systemType = $2 " +
        "AND systemHeader.currentVersion = true AND (systemHeader.deleted IS MISSING OR systemHeader.deleted != true);";

    var query = cbUtil.getN1QlQuery(statement);
    cbBucket = cbConnection.getBucket(connectionName);
    cbBucket.query(query, [userId, SharedConstants.SYSTEM_TYPE_ACCOUNT], function(err, results) {
        if(err) {
            deferred.reject(err);
        } else {
            //deleting _id, migrated accounts can still have _id
            var account = results[0];
            if (account) {
                delete account._id;
            }

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

    return deferred.promise;
};

var getPasswordResetDocument = function(hash, connectionName) {
    logger.info('Invoke getPasswordResetDocument function in CouchbaseDataService');
    var deferred = q.defer();

    var bucketName = cbConnection.getConfig(connectionName).bucket;

    var statement = "SELECT `" + bucketName + "`.* FROM `" + bucketName + "` " +
        "WHERE resetTokenText = $1 AND systemHeader.systemType = $2 " +
        "AND systemHeader.currentVersion = true AND " +
		"(systemHeader.deleted IS MISSING OR systemHeader.deleted != true) " +
		"AND isActiveBool = true AND passwordResetExpiryDate >= $3;";

    var query = cbUtil.getN1QlQuery(statement);
    cbBucket = cbConnection.getBucket(connectionName);
    cbBucket.query(query, [hash, SharedConstants.SYSTEM_TYPE_PASSWORD_RESET, new Date()], function(err, results) {
        if(err) {
            deferred.reject(err);
        } else {
            //deleting _id, migrated accounts can still have _id
            var resetDoc = results[0];
            if (resetDoc) {
                delete resetDoc._id;
            }

            deferred.resolve(resetDoc);
        }
    });

    return deferred.promise;
};

const getAccountByQuery = (email, accountSocialMediaId, connectionName) => {

    let deferred = q.defer();

    let bucketName = cbConnection.getConfig(connectionName).bucket;

    let statement = "SELECT `" + bucketName + "`.* FROM `" + bucketName + "` " +
        "WHERE lower(email) = $1 AND systemHeader.systemType = $2 " +
        "AND systemHeader.currentVersion = true AND " +
        "(systemHeader.deleted IS MISSING OR systemHeader.deleted != true) " ;

    let value = [email.toLowerCase(), SharedConstants.SYSTEM_TYPE_ACCOUNT];

    if(accountSocialMediaId){
        statement +=  "AND userId = $3";
        value.push(accountSocialMediaId);
    }

    let query = cbUtil.getN1QlQuery(statement);
    cbBucket = cbConnection.getBucket(connectionName);
    cbBucket.query(query, value, function(err, results) {
        if(err) {
            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, connectionName) => {

    let deferred = q.defer();

    let bucketName = cbConnection.getConfig(connectionName).bucket;

    let statement = "SELECT `" + bucketName + "`.* FROM `" + bucketName + "` " +
        "WHERE  apiKey = $1 AND  ANY hosts IN apiHosts SATISFIES hosts IN $2 END AND systemHeader.systemType = $3 " +
        "AND systemHeader.currentVersion = true AND " +
        "(systemHeader.deleted IS MISSING OR systemHeader.deleted != true) " ;

    let values = [apiKey, apiHosts, SharedConstants.SYSTEM_TYPE_ACCOUNT_SECURITY];

    let query = cbUtil.getN1QlQuery(statement);
    cbBucket = cbConnection.getBucket(connectionName);
    cbBucket.query(query, values, function(err, results) {
        if(err) {
            deferred.reject(err);
        } else {
            deferred.resolve(results);
        }
    });

    return deferred.promise;
};


module.exports = {

	getAccountById: getAccountById,

	/*
	 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, verified, provider, accountSocialMediaId) {

        if(true){
            var msg = 'CouchbaseAccountDataService.getAccount is no 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);

		var bucketName = cbConnection.getConfig().bucket;

		var params = [SharedConstants.SYSTEM_TYPE_ACCOUNT];

		var whereCondition = "systemHeader.systemType = $1 " +
			"AND systemHeader.currentVersion = true AND (systemHeader.deleted IS MISSING OR systemHeader.deleted != true) ";
		if (email) {
			//query.email = email;
			params.push(email);
			whereCondition += "AND email = $" + params.length + " ";
		}

		if (provider) {
			//query.provider = provider;
			params.push(provider);
			whereCondition += "AND provider = $" + params.length + " ";
		} else {
			whereCondition += "AND provider = 'local' ";
		}

		if (accountSocialMediaId) {
			//query.userId = accountSocialMediaId;
			params.push(accountSocialMediaId);
			whereCondition += "AND userId = $" + params.length + " ";
		}

		if (verified) {
			//query.verified = verified;
			params.push(verified);
			whereCondition += "AND verified = $" + params.length + " ";
		}
		whereCondition += ";";

		var statement = "SELECT `" + bucketName + "`.* FROM `" + bucketName + "` " +
			"WHERE " + whereCondition;
		var query = cbUtil.getN1QlQuery(statement);
		cbBucket = cbConnection.getBucket();
		cbBucket.query(query, params, function(err, results) {
			if(err) {
				var errorMsg = "Error getting account: " + err;
				logger.error(errorMsg);
				deferred.reject(new Error(errorMsg));
			} else {
				if (lodashLang.isEmpty(results[0])){
					errorMsg = "Username or password is not valid";
					logger.info(errorMsg);
					deferred.reject(new Error(errorMsg));
				}
				else{
					logger.info('account found');
					//deleting _id, migrated accounts can still have _id
					var account = results[0];
					if (account) {
						delete account._id;
					}

					deferred.resolve(account);
				}

			}
		});

		return deferred.promise;
	},

    getPasswordResetDocument: getPasswordResetDocument,

    getAccountByQuery: getAccountByQuery,

    getAccountByApiKey: getAccountByApiKey,

    getAccountUtilityDocumentsQuery: function(accountId, type){

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

        return query;
    },

    getCheckExistedAccountQuery: function(email){

      let query = {
        "lower(email)": email.toLowerCase()
      };

      return query;
    }
};
