const _ = require('underscore');

const { getCollection } = require('../utils/collection');
const { excuteTriggers } = require('../utils/trigger')
const WorkflowManager = require('./workflow_manager');
// const UUFlowManager = require('./uuflow_manager'); // Moved inside function to avoid circular dependency

const getHandlersManager = {};

getHandlersManager.getHandlersByUsersAndRoles = async function (user_ids, role_ids, space_id) {
    let approve_users = [];
    
    for (const user_id of user_ids) {
        const usersCollection = await getCollection('users');
        const userCount = await usersCollection.find({ _id: user_id }).count();
        
        if (userCount > 0) {
            const users = await getHandlersManager.getHandlersByUserAndRoles(user_id, role_ids, space_id);
            if (users.length > 0) {
                approve_users = approve_users.concat(users);
            }
        } else {
            throw new Error('error! user_id不合法');
        }
    }
    
    return _.uniq(approve_users);
};

getHandlersManager.getHandlersByUserAndRoles = async function (user_id, role_ids, space_id) {
    let user_ids = [];
    
    for (const role_id of role_ids) {
        const flowRolesCollection = await getCollection('flow_roles');
        const roleCount = await flowRolesCollection.find({ _id: role_id }).count();
        
        if (roleCount > 0) {
            const users = await getHandlersManager.getHandlersByUserAndRole(user_id, role_id, space_id);
            if (users.length > 0) {
                user_ids = user_ids.concat(users);
            }
        } else {
            throw new Error('error! role_id已经被删除');
        }
    }
    
    if (user_ids.length > 0) {
        return _.uniq(user_ids);
    } else {
        throw new Error('error! 根据user_id和role_ids没查到对应的处理人');
    }
};

getHandlersManager.getHandlersByUserAndRole = async function (user_id, role_id, space_id) {
    const organizationsCollection = await getCollection('organizations');
    const orgs = await organizationsCollection.find({
        space: space_id,
        users: user_id
    }, {
        projection: { _id: 1 }
    }).toArray();
    
    let user_ids = [];
    
    for (const org of orgs) {
        const users = await getHandlersManager.getHandlersByOrgAndRole(org._id, role_id, space_id);
        if (users.length > 0) {
            user_ids = user_ids.concat(users);
        }
    }
    
    return _.uniq(user_ids);
};

getHandlersManager.getHandlersByOrgsAndRoles = async function (org_ids, role_ids, space_id) {
    let user_ids = [];
    
    for (const org_id of org_ids) {
        const users = await getHandlersManager.getHandlersByOrgAndRoles(org_id, role_ids, space_id);
        if (users.length > 0) {
            user_ids = user_ids.concat(users);
        }
    }
    
    return _.uniq(user_ids);
};

getHandlersManager.getHandlersByOrgAndRoles = async function (org_id, role_ids, space_id) {
    let user_ids = [];
    
    for (const role_id of role_ids) {
        const users = await getHandlersManager.getHandlersByOrgAndRole(org_id, role_id, space_id);
        if (users.length > 0) {
            user_ids = user_ids.concat(users);
        }
    }
    
    if (user_ids.length > 0) {
        return _.uniq(user_ids);
    } else {
        throw new Error('error! 根据org_id和role_ids没查到对应的处理人');
    }
};

getHandlersManager.getHandlersByOrgAndRole = async function (org_id, role_id, space_id) {
    const organizationsCollection = await getCollection('organizations');
    const flowPositionsCollection = await getCollection('flow_positions');
    
    const org = await organizationsCollection.findOne({
        _id: org_id
    }, {
        projection: { parents: 1 }
    });
    
    let user_ids = [];
    let positions = await flowPositionsCollection.find({
        space: space_id,
        org: org_id,
        role: role_id
    }, {
        projection: { users: 1 }
    }).toArray();
    
    for (const position of positions) {
        user_ids = user_ids.concat(position.users);
    }
    
    if (user_ids.length === 0 && org && org.parents) {
        for (const parent_id of org.parents) {
            positions = await flowPositionsCollection.find({
                space: space_id,
                org: parent_id,
                role: role_id
            }, {
                projection: { users: 1 }
            }).toArray();
            
            if (positions.length > 0) {
                for (const position of positions) {
                    user_ids = user_ids.concat(position.users);
                }
            }
        }
    }
    
    return _.uniq(user_ids);
};

getHandlersManager.getHandlers = async function (instance_id, step_id, login_user_id) {
    const UUFlowManager = require('./uuflow_manager');
    const instancesCollection = await getCollection('instances');
    const flowsCollection = await getCollection('flows');
    const formsCollection = await getCollection('forms');
    const spaceUsersCollection = await getCollection('space_users');
    const flowRolesCollection = await getCollection('flow_roles');
    const organizationsCollection = await getCollection('organizations');
    
    const instance = await instancesCollection.findOne({_id: instance_id});
    
    // 拟稿时, 可以设定后续每个步骤的处理人 #1926
    if (instance.step_approve && !_.isEmpty(instance.step_approve[`${step_id}_options`])) {
        return instance.step_approve[`${step_id}_options`];
    }
    
    let approve_users = [];
    const space_id = instance.space;
    const flow_id = instance.flow;
    const flow_rev = instance.flow_version;
    
    const current_flow = await flowsCollection.findOne({_id: flow_id}, { 
        projection: { 
            _id: 1, 
            form: 1, 
            'current._id': 1, 
            'current.steps': 1, 
            'current.form_version': 1, 
            'historys._id': 1, 
            'historys.steps': 1, 
            'historys.form_version': 1 
        }
    });
    
    let current_step = null;
    let current_steps = [];
    
    if (current_flow.current._id === flow_rev) {
        current_steps = current_flow.current.steps;
    } else {
        const current = _.find(current_flow.historys, function (history) {
            return history._id === flow_rev;
        });
        current_steps = current.steps;
    }
    
    current_step = _.find(current_steps, function (step) {
        return step._id === step_id;
    });
    
    if (current_step.step_type === "condition") {
        const unfinished_trace = _.find(instance.traces, function (trace) {
            return trace.is_finished === false;
        });
        return [unfinished_trace.approves[0].user];
    }
    
    if (current_step.step_type === "start") {
        const handlers = [instance.applicant, instance.submitter];
        return _.uniq(handlers);
    }
    
    const deal_type = current_step.deal_type;
    let users = [];
    
    if (deal_type === "applicantRole") {
        const applicant = instance.applicant;
        if (applicant) {
            const space_user_count = await spaceUsersCollection.find({
                space: space_id,
                user: applicant
            }).count();
            
            if (space_user_count === 0) {
                throw new Error('error! 提交人已经被删除或不属于当前space');
            }
            
            if (current_step.approver_roles && current_step.approver_roles.length > 0) {
                for (const approver_role of current_step.approver_roles) {
                    const role_count = await flowRolesCollection.find({
                        _id: approver_role
                    }).count();
                    
                    if (role_count === 0) {
                        throw new Error('error! 角色已经被删除');
                    }
                }
                
                users = await getHandlersManager.getHandlersByUserAndRoles(applicant, current_step.approver_roles, space_id);
            } else {
                throw new Error('error! 审批岗位未指定');
            }
        } else {
            throw new Error('error! Instance的提交人为空');
        }
    } else if (deal_type === "hrRole") {
        const approveHrRoleIds = current_step.approver_hr_roles;
        if (approveHrRoleIds) {
            const hrRolesUsers = await WorkflowManager.getHrRolesUsers(space_id, approveHrRoleIds);
            users = _.pluck(hrRolesUsers, 'user');
        } else {
            throw new Error('error! 角色未指定');
        }
    } else if (deal_type === "applicant") {
        users = [instance.applicant];
    } else if (deal_type === "orgFieldRole") {
        const form_id = current_flow.form;
        let form_rev = null;
        
        if (flow_rev === current_flow.current._id) {
            form_rev = current_flow.current.form_version;
        } else {
            const current_flow_version = _.find(current_flow.historys, function (current_flow_history) {
                return current_flow_history._id === flow_rev;
            });
            if (current_flow_version) {
                form_rev = current_flow_version.form_version;
            }
        }
        
        const form = await formsCollection.findOne({_id: form_id});
        let current_form = null;
        
        if (form_rev === form.current._id) {
            current_form = form.current;
        } else {
            current_form = _.find(form.historys, function (form_history) {
                return form_history._id === form_rev;
            });
        }
        
        const approver_org_field = current_step.approver_org_field;
        const form_fields = current_form.fields;
        let field_code = null;
        
        for (const form_field of form_fields) {
            if (form_field._id === approver_org_field) {
                field_code = form_field.code;
                break;
            }
        }
        
        const newest_values = await UUFlowManager.getUpdatedValues(instance);
        let org_ids = [];
        let org_ids_names = [];
        
        if (newest_values[field_code]) {
            if (newest_values[field_code] instanceof Array) {
                org_ids_names = newest_values[field_code];
            } else {
                org_ids_names.push(newest_values[field_code]);
            }
        }
        
        for (const org of org_ids_names) {
            const check_org_count = await organizationsCollection.find({
                _id: org["id"]
            }).count();
            
            if (check_org_count === 0) {
                throw new Error('error! 组织ID不合法');
            }
            
            org_ids.push(org["id"]);
        }
        
        if (current_step.approver_roles && current_step.approver_roles.length > 0) {
            for (const approver_role of current_step.approver_roles) {
                const role_count = await flowRolesCollection.find({
                    _id: approver_role
                }).count();
                
                if (role_count === 0) {
                    throw new Error(`error! ${approver_role}已经被删除`);
                }
            }
            
            users = await getHandlersManager.getHandlersByOrgsAndRoles(org_ids, current_step.approver_roles, instance.space);
        } else {
            throw new Error(`error! 流程步骤${current_step.name}审批岗位未指定`);
        }
    } else if (deal_type === "orgField") {
        const form_id = current_flow.form;
        let form_rev = null;
        
        if (flow_rev === current_flow.current._id) {
            form_rev = current_flow.current.form_version;
        } else {
            const current_flow_version = _.find(current_flow.historys, function (current_flow_history) {
                return current_flow_history._id === flow_rev;
            });
            if (current_flow_version) {
                form_rev = current_flow_version.form_version;
            }
        }
        
        const form = await formsCollection.findOne({_id: form_id});
        let current_form = null;
        
        if (form_rev === form.current._id) {
            current_form = form.current;
        } else {
            current_form = _.find(form.historys, function (form_history) {
                return form_history._id === form_rev;
            });
        }
        
        const approver_org_field = current_step.approver_org_field;
        const form_fields = current_form.fields;
        let field_code = null;
        
        for (const form_field of form_fields) {
            if (form_field._id === approver_org_field) {
                field_code = form_field.code;
                break;
            }
        }
        
        const newest_values = await UUFlowManager.getUpdatedValues(instance);
        let org_ids = [];
        let org_ids_names = [];
        
        if (newest_values[field_code]) {
            if (newest_values[field_code] instanceof Array) {
                org_ids_names = newest_values[field_code];
            } else {
                org_ids_names.push(newest_values[field_code]);
            }
        }
        
        for (const org of org_ids_names) {
            const check_org_count = await organizationsCollection.find({
                _id: org["id"]
            }).count();
            
            if (check_org_count === 0) {
                throw new Error('error! 组织ID不合法');
            }
            
            org_ids.push(org["id"]);
        }
        
        let user_ids = [];
        
        for (const org_id of org_ids) {
            const org = await organizationsCollection.findOne({
                _id: org_id
            }, {
                projection: { users: 1 }
            });
            
            const org_children = await organizationsCollection.find({
                space: space_id,
                parents: org_id
            }, {
                projection: { users: 1 }
            }).toArray();
            
            org_children.unshift(org);
            const check_orgs = org_children;
            let org_users = [];
            
            for (const check_org_user of check_orgs) {
                if (check_org_user.users) {
                    for (const org_user of check_org_user.users) {
                        const spaceUserCount = await spaceUsersCollection.find({
                            space: space_id,
                            user: org_user
                        }).count();
                        
                        if (spaceUserCount === 0) {
                            throw new Error('error! space下不存在此user');
                        }
                    }
                }
                
                user_ids = user_ids.concat(check_org_user.users);
                org_users = org_users.concat(check_org_user.users);
            }
            
            if (org_users.length === 0) {
                throw new Error(`error! 组织${org_id}不存在处理人`);
            }
        }
        
        users = _.uniq(user_ids);
    } else if (deal_type === "userFieldRole") {
        const form_id = current_flow.form;
        let form_rev = null;
        
        if (flow_rev === current_flow.current._id) {
            form_rev = current_flow.current.form_version;
        } else {
            const current_flow_version = _.find(current_flow.historys, function (current_flow_history) {
                return current_flow_history._id === flow_rev;
            });
            if (current_flow_version) {
                form_rev = current_flow_version.form_version;
            }
        }
        
        const form = await formsCollection.findOne({_id: form_id});
        let current_form = null;
        
        if (form_rev === form.current._id) {
            current_form = form.current;
        } else {
            current_form = _.find(form.historys, function (form_history) {
                return form_history._id === form_rev;
            });
        }
        
        const approver_user_field = current_step.approver_user_field;
        const form_fields = current_form.fields;
        let field_code = null;
        
        for (const form_field of form_fields) {
            if (form_field._id === approver_user_field) {
                field_code = form_field.code;
                break;
            }
        }
        
        const newest_values = await UUFlowManager.getUpdatedValues(instance);
        let user_ids_names = [];
        
        if (newest_values[field_code]) {
            if (newest_values[field_code] instanceof Array) {
                user_ids_names = newest_values[field_code];
            } else {
                user_ids_names.push(newest_values[field_code]);
            }
        }
        
        let user_ids = [];
        
        for (const user of user_ids_names) {
            const check_user_count = await spaceUsersCollection.find({
                space: space_id,
                user: _.isString(user) ? user : user["id"]
            }).count();
            
            if (check_user_count === 0) {
                throw new Error('error! 人员ID不合法');
            }
            
            user_ids.push(_.isString(user) ? user : user["id"]);
        }
        
        user_ids = _.uniq(user_ids);
        
        if (current_step.approver_roles && current_step.approver_roles.length > 0) {
            for (const approver_role of current_step.approver_roles) {
                const role_count = await flowRolesCollection.find({
                    _id: approver_role
                }).count();
                
                if (role_count === 0) {
                    throw new Error(`error! ${approver_role}已经被删除`);
                }
            }
            
            users = await getHandlersManager.getHandlersByUsersAndRoles(user_ids, current_step.approver_roles, instance.space);
        } else {
            throw new Error(`error! 流程步骤${current_step.name}审批岗位未指定`);
        }
    } else if (deal_type === "userField") {
        const form_id = current_flow.form;
        let form_rev = null;
        
        if (flow_rev === current_flow.current._id) {
            form_rev = current_flow.current.form_version;
        } else {
            const current_flow_version = _.find(current_flow.historys, function (current_flow_history) {
                return current_flow_history._id === flow_rev;
            });
            if (current_flow_version) {
                form_rev = current_flow_version.form_version;
            }
        }
        
        const form = await formsCollection.findOne({_id: form_id});
        let current_form = null;
        
        if (form_rev === form.current._id) {
            current_form = form.current;
        } else {
            current_form = _.find(form.historys, function (form_history) {
                return form_history._id === form_rev;
            });
        }
        
        const approver_user_field = current_step.approver_user_field;
        const form_fields = current_form.fields;
        let field_code = null;
        
        for (const form_field of form_fields) {
            if (form_field._id === approver_user_field) {
                field_code = form_field.code;
                break;
            }
        }
        
        const newest_values = await UUFlowManager.getUpdatedValues(instance);
        let user_ids_names = [];
        
        if (newest_values[field_code]) {
            if (newest_values[field_code] instanceof Array) {
                user_ids_names = newest_values[field_code];
            } else {
                user_ids_names.push(newest_values[field_code]);
            }
        }
        
        let user_ids = [];
        for (const user of user_ids_names) {
            const check_user_count = await spaceUsersCollection.find({
                space: space_id,
                user: _.isString(user) ? user : user["id"]
            }).count();
            if (check_user_count === 0) {
                throw new Error('error! 人员ID不合法');
            }
            
            user_ids.push(_.isString(user) ? user : user["id"]);
        }
        
        users = _.uniq(user_ids);
    } else if (deal_type === "specifyStepRole") {
        const approver_step = current_step.approver_step;
        const finished_traces = _.filter(instance.traces, function (trace) {
            return trace.step === approver_step;
        });
        
        const max_startDate_trace = _.max(finished_traces, function (t) {
            return t.start_date;
        });
        
        approve_users = _.pluck(max_startDate_trace.approves, "user");
        
        if (current_step.approver_roles) {
            for (const approver_role of current_step.approver_roles) {
                const role_count = await flowRolesCollection.find({
                    _id: approver_role
                }).count();
                
                if (role_count === 0) {
                    throw new Error('error! 角色已经被删除');
                }
            }
        }
        
        for (const approve_user of approve_users) {
            const spaceUserCount = await spaceUsersCollection.find({
                space: space_id,
                user: approve_user
            }).count();
            
            if (spaceUserCount === 0) {
                throw new Error('error! 指定步骤的处理人已经变更');
            }
        }
        
        users = await getHandlersManager.getHandlersByUsersAndRoles(approve_users, current_step.approver_roles, space_id);
    } else if (deal_type === "specifyStepUser") {
        const approver_step = current_step.approver_step;
        const finished_traces = _.filter(instance.traces, function (trace) {
            return trace.step === approver_step;
        });
        
        const max_startDate_trace = _.max(finished_traces, function (t) {
            return t.start_date;
        });
        
        approve_users = _.pluck(max_startDate_trace.approves, "user");
        
        for (const approve_user of approve_users) {
            const check_approve_user_count = await spaceUsersCollection.find({
                space: space_id,
                user: approve_user
            }).count();
            
            if (check_approve_user_count === 0) {
                throw new Error('error! 指定步骤的处理人已经变更');
            }
        }
        
        users = _.uniq(approve_users);
    } else if (deal_type === "submitterRole") {
        const submitter = instance.submitter;
        if (!submitter) {
            const submitter_user_count = await spaceUsersCollection.find({
                space: space_id,
                user: submitter
            }).count();
            
            if (submitter_user_count === 0) {
                throw new Error('error! 提交人已经被删除或不属于当前工作区');
            } else {
                if (current_step.approver_roles && current_step.approver_roles.length > 0) {
                    for (const approver_role of current_step.approver_roles) {
                        const role_count = await flowRolesCollection.find({
                            _id: approver_role
                        }).count();
                        
                        if (role_count === 0) {
                            throw new Error(`error! ${approver_role}已经被删除`);
                        }
                    }
                    
                    users = await getHandlersManager.getHandlersByUserAndRoles(submitter, current_step.approver_roles, space_id);
                } else {
                    throw new Error(`error! 流程步骤${current_step.name}审批岗位未指定`);
                }
            }
        } else {
            throw new Error('error! 申请单的提交人为空');
        }
    } else if (deal_type === "submitter") {
        const submitter = instance.submitter;
        const submitter_user_count = await spaceUsersCollection.find({
            space: space_id,
            user: submitter
        }).count();
        
        if (submitter_user_count === 0) {
            throw new Error('error! 提交人已经被删除或不属于当前工作区');
        } else {
            users = [submitter];
        }
    } else if (deal_type === "specifyOrg") {
        const approver_org_ids = current_step.approver_orgs;
        if (!approver_org_ids || approver_org_ids.length === 0) {
            throw new Error('error! 未定义用于查找下一步处理人的部门，请联系管理员调查流程图的配置是否正确');
        }
        
        const valid_approver_org_ids = [];
        
        for (const approver_org_id of approver_org_ids) {
            const orgCount = await organizationsCollection.find({
                _id: approver_org_id
            }).count();
            
            if (orgCount > 0) {
                valid_approver_org_ids.unshift(approver_org_id);
            }
        }
        
        let org_user_ids = [];
        
        for (const valid_approver_org_id of valid_approver_org_ids) {
            const valid_approver_org = await organizationsCollection.findOne({
                _id: valid_approver_org_id
            }, {
                projection: { users: 1 }
            });
            
            if (valid_approver_org.users) {
                org_user_ids = org_user_ids.concat(valid_approver_org.users);
            }
            
            const child_orgs = await organizationsCollection.find({
                space: space_id,
                parents: valid_approver_org_id
            }, {
                projection: { users: 1 }
            }).toArray();
            
            for (const child_org of child_orgs) {
                if (child_org.users) {
                    org_user_ids = org_user_ids.concat(child_org.users);
                }
            }
        }
        
        org_user_ids = _.uniq(org_user_ids);
        const new_org_user_ids = [];
        
        for (const org_user_id of org_user_ids) {
            const space_user_info_count = await spaceUsersCollection.find({
                space: space_id,
                user: org_user_id
            }).count();
            
            if (space_user_info_count > 0) {
                new_org_user_ids.push(org_user_id);
            }
        }
        
        users = new_org_user_ids;
    } else if (deal_type === "specifyUser") {
        let approver_user_ids = current_step.approver_users;
        approver_user_ids = _.uniq(approver_user_ids);
        const new_approver_user_ids = [];
        
        for (const approver_user_id of approver_user_ids) {
            const space_user_info_count = await spaceUsersCollection.find({
                space: space_id,
                user: approver_user_id
            }).count();
            
            if (space_user_info_count > 0) {
                new_approver_user_ids.push(approver_user_id);
            }
        }
        
        users = new_approver_user_ids;
    } else if (deal_type === "pickupAtRuntime") {
        let next_step_users = [];
        const _trace = _.find(instance.traces, function (_tr) {
            return _tr.is_finished === false;
        });
        
        const _approve = _.find(_trace.approves, function (_app) {
            return _app.is_finished === false && _app.type !== 'cc';
        });
        
        if (_approve.next_steps) {
            if (_approve.next_steps[0]["users"]) {
                next_step_users = _approve.next_steps[0]["users"];
            }
        }
        
        users = next_step_users;
    } else if (deal_type === "applicantSuperior") {
        const applicantSuperiors = [];
        const _space_user = await spaceUsersCollection.findOne({
            space: space_id,
            user: instance.applicant
        }, {
            projection: { manager: 1 }
        });
        
        if (_space_user.manager) {
            applicantSuperiors.push(_space_user.manager);
        }
        
        users = applicantSuperiors;
    }

    await excuteTriggers({ when: 'cacluateNextStepUsers', userId: login_user_id, flowId: flow_id, insId: instance_id, nextStep: current_step, nextUserIds: users });
    return users;
};



module.exports = getHandlersManager;