'use strict';

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

const getSelect = (options) => {
    let connectionName = options ? options.connectionName : null;
    const bucketName = cbConnection.getConfig(connectionName).bucket;

    return "SELECT `" + bucketName + "`.* FROM `" + bucketName + "` " ;

};

function markSystemActionDone(systemAction, statusDescription) {
    logger.info('Marking System Action Document... ');

    var deferred = q.defer();

    if (systemAction) {
        var bucketName = cbConnection.getConfig().bucket;

        var statement = "UPDATE `" + bucketName + "` " +
            "SET actionedDate = $1, statusDescription = $2 " +
            "WHERE documentId = $3 AND systemHeader.currentVersion = true;";

        var query = cbUtil.getN1QlQuery(statement);
        cbBucket = cbConnection.getBucket();
        cbBucket.query(query, [new Date(), statusDescription, systemAction.documentId], function(err, results) {
            if(err) {
                logger.error(err);
                deferred.reject(new Error(err));
            } else {
                logger.info(`System Action: ${systemAction.documentId} marked done with statusDescription: ${statusDescription}`);
                deferred.resolve();
            }
        });
    } else {
        deferred.reject(new Error('No system action document provided.'));
    }

    return deferred.promise;
}

function getUnactionedSystemActions() {
    var deferred = q.defer();

    var bucketName = cbConnection.getConfig().bucket;

    var statement = "SELECT `" + bucketName + "`.* FROM `" + bucketName + "` " +
        "WHERE userId IS NOT NULL AND systemHeader.systemType = $1 " +
        "AND systemHeader.currentVersion = true " +
        "AND (systemHeader.deleted IS MISSING OR systemHeader.deleted IS NULL OR systemHeader.deleted = false) " +
        "AND (cancelledBool IS MISSING OR cancelledBool IS NULL OR cancelledBool = false) " +
        "AND actionedDate IS NULL AND dueDate <= $2;";

    var query = cbUtil.getN1QlQuery(statement);
    cbBucket = cbConnection.getBucket();
    cbBucket.query(query, [SharedConstants.SYSTEM_TYPE_SYSTEM_ACTION, new Date()], function(err, results) {
        if(err) {
            logger.error(err);
            deferred.reject(err);
        } else {
            deferred.resolve(results.rows);
        }
    });

    return deferred.promise;
}

const processUnactionedSystemActions = async (systemActionProcessingFunc) => {
    try {
        const results = getUnactionedSystemActions();
        for (const item of results) {
            return await systemActionProcessingFunc(item);
        }
    } catch(err) {
        throw err;
    }
};

function getCurrentScheduledDocuments() {
    var deferred = q.defer();

    var bucketName = cbConnection.getConfig().bucket;

    var currentDate = new Date();

    var statement = "SELECT `" + bucketName + "`.* FROM `" + bucketName + "` " +
        "WHERE systemHeader.systemType = $1 " +
        "AND nextRunDate > $2 " +
        "AND systemHeader.currentVersion = true AND scheduleActive = true;";

    var query = cbUtil.getN1QlQuery(statement);
    cbBucket = cbConnection.getBucket();
    cbBucket.query(query, [SharedConstants.SYSTEM_TYPE_SCHEDULE, currentDate], function(err, results) {
        if(err) {
            logger.error(err);
            deferred.reject(err);
        } else {
            for (var i = 0; i < results.length; i++) {
                delete results[0]._id;
            }

            deferred.resolve(results);
        }
    });

    return deferred.promise;
}

const getIncludeDocsQuery = (includeNames) =>{

    let statement = getSelect() +
      ' WHERE (systemHeader.systemType="' + SharedConstants.SYSTEM_TYPE_RULESET_INCLUDE + '"' ;

    if (includeNames && includeNames.length > 0) {
        statement += ' AND name IN ' + JSON.stringify(includeNames) ;
    }
    statement += ' )' ;

    return statement;

};

const getRuleSetIdQuery = (event, templateId) =>{

    let statement = getSelect() +
      ' WHERE systemHeader.systemType="' + SharedConstants.SYSTEM_TYPE_RULESET + '"' +
      ' AND event="' + event + '"' +
      ' AND template.documentId="' + templateId + '"' ;

    return statement;

};

const getRuleSetIdByNameQuery = (name) => {

    let statement = getSelect() +
        ` WHERE  name="${name}` +
        ` AND systemHeader.systemType="${SharedConstants.SYSTEM_TYPE_RULESET}"`;

    return statement;

};

////////////////////////////////////
// public api
module.exports = {
    getUnactionedSystemActions: getUnactionedSystemActions,

    processUnactionedSystemActions,

    getCurrentScheduledDocuments: getCurrentScheduledDocuments,

    getIncludeDocsQuery: getIncludeDocsQuery,

    getRuleSetIdQuery: getRuleSetIdQuery,

    markSystemActionDone,

    getRuleSetIdByNameQuery
};
