package cn.stylefeng.workflow.instance.core.condition;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.stylefeng.roses.kernel.rule.pojo.dict.SimpleDict;
import cn.stylefeng.roses.kernel.sys.api.OrgApproverServiceApi;
import cn.stylefeng.roses.kernel.sys.api.enums.org.DetectModeEnum;
import cn.stylefeng.team.form.api.enums.FormTypeEnum;
import cn.stylefeng.workflow.api.enums.ApproverTypeEnum;
import cn.stylefeng.workflow.api.enums.FormFieldTypeEnum;
import cn.stylefeng.workflow.api.pojo.InstanceContext;
import cn.stylefeng.workflow.api.pojo.InstanceVariable;
import cn.stylefeng.workflow.api.pojo.config.SixGraphDesign;
import cn.stylefeng.workflow.api.pojo.config.model.FlowGlobalConfig;
import cn.stylefeng.workflow.api.pojo.config.model.ModelForm;
import cn.stylefeng.workflow.api.pojo.config.node.approver.ApproverConfig;
import cn.stylefeng.workflow.api.pojo.config.node.approver.ApproverSummary;
import cn.stylefeng.workflow.api.pojo.config.node.approver.detail.NodeApproverForm;
import cn.stylefeng.workflow.instance.core.condition.base.BaseApproverRule;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class FormApproverRule extends BaseApproverRule {

    @Override
    public boolean approverEvaluate(InstanceContext instanceContext, ApproverConfig approverConfig) {

        ApproverSummary mainApprover = approverConfig.getMainApprover();
        if (ObjectUtil.isEmpty(mainApprover)) {
            return false;
        }

        if (!ApproverTypeEnum.FORM_SELECT.getValue().equals(mainApprover.getApproverType())) {
            return false;
        }

        List<NodeApproverForm> nodeApproverFormList = mainApprover.getNodeApproverFormList();
        if (ObjectUtil.isEmpty(nodeApproverFormList)) {
            return false;
        }

        return true;
    }

    @Override
    public void approverExecute(InstanceContext instanceContext, ApproverConfig approverConfig) {

        List<Long> finalResultUserIdList = new ArrayList<>();

        List<NodeApproverForm> nodeApproverFormList = approverConfig.getMainApprover().getNodeApproverFormList();
        for (NodeApproverForm nodeApproverForm : nodeApproverFormList) {

            List<Long> userIdList;

            Integer formType = nodeApproverForm.getFormType();
            if (FormTypeEnum.APP_DESIGN.getValueType().equals(formType)) {
                userIdList = this.getFormApproverList(nodeApproverForm, instanceContext);
            }

            else {
                userIdList = this.getCustomFormFieldInfo(nodeApproverForm, instanceContext);
            }

            if (userIdList != null && !userIdList.isEmpty()) {
                finalResultUserIdList.addAll(userIdList);
            }
        }

        if (ObjectUtil.isNotEmpty(finalResultUserIdList)) {
            setResult(finalResultUserIdList);
        }
    }

    @Override
    public String getBaseRuleName() {
        return FormApproverRule.class.getName();
    }

    @Override
    public int getBaseRulePriority() {
        return 500;
    }

    private List<Long> getFormApproverList(NodeApproverForm nodeApproverForm, InstanceContext instanceContext) {

        SixGraphDesign xSixGraphJson = instanceContext.getDefinition().getXSixGraphJson();
        if (ObjectUtil.isEmpty(xSixGraphJson)) {
            return null;
        }

        FlowGlobalConfig flowGlobalConfig = xSixGraphJson.getFlowGlobalConfig();
        if (ObjectUtil.isEmpty(flowGlobalConfig)) {
            return null;
        }

        List<ModelForm> formDefinitionList = flowGlobalConfig.getFormDefinitionList();
        if (ObjectUtil.isEmpty(formDefinitionList)) {
            return null;
        }

        InstanceVariable instanceVariable = instanceContext.getInstanceVariable();
        if (ObjectUtil.isEmpty(instanceVariable)) {
            return null;
        }

        List<ModelForm> modelFormList = formDefinitionList.stream()
                .filter(modelForm -> modelForm.getFormCode().equals(nodeApproverForm.getFormCode())).collect(Collectors.toList());
        if (ObjectUtil.isNotEmpty(modelFormList)) {
            ModelForm modelForm = modelFormList.get(0);
            Long formDefinitionId = modelForm.getFormDefinitionId();
            if (formDefinitionId == null) {
                return null;
            }

            Map<String, Map<String, Object>> formData = instanceVariable.getFormData();
            if (ObjectUtil.isEmpty(formData)) {
                return null;
            }

            Map<String, Object> definitionFields = formData.get(formDefinitionId.toString());
            if (ObjectUtil.isEmpty(definitionFields)) {
                return null;
            }

            Object fieldValue = definitionFields.get(nodeApproverForm.getFieldCode());
            if (ObjectUtil.isEmpty(fieldValue)) {
                return null;
            }

            List<Long> finalIdArrayList;


            String valueString = fieldValue.toString();
            Object jsonObj = JSON.parse(valueString);

            if (jsonObj instanceof JSONArray) {
                List<SimpleDict> userOrOrgList = JSON.parseArray(valueString, SimpleDict.class);
                finalIdArrayList = userOrOrgList.stream().map(SimpleDict::getId).collect(Collectors.toList());
            } else {
                finalIdArrayList = ListUtil.list(false, Convert.toLong(valueString));
            }

            return getUserIdList(nodeApproverForm, finalIdArrayList);
        }

        return null;
    }

    private List<Long> getCustomFormFieldInfo(NodeApproverForm nodeApproverForm, InstanceContext instanceContext) {

        InstanceVariable instanceVariable = instanceContext.getInstanceVariable();
        if (ObjectUtil.isEmpty(instanceVariable)) {
            return null;
        }

        Map<String, Object> customVueFormData = instanceVariable.getCustomVueFormData();
        if (ObjectUtil.isEmpty(customVueFormData)) {
            return null;
        }

        String fieldCode = nodeApproverForm.getFieldCode();
        Object selectIdJson = customVueFormData.get(fieldCode);
        if (ObjectUtil.isEmpty(selectIdJson)) {
            return null;
        }

        List<SimpleDict> userOrOrgList = JSON.parseArray(selectIdJson.toString(), SimpleDict.class);

        List<Long> bizIdList = userOrOrgList.stream().map(SimpleDict::getId).collect(Collectors.toList());
        return getUserIdList(nodeApproverForm, bizIdList);
    }

    private static List<Long> getUserIdList(NodeApproverForm nodeApproverForm, List<Long> bizIdList) {
        List<Long> userIdList = new ArrayList<>();

        if (FormFieldTypeEnum.PERSONAL.getValue().equals(nodeApproverForm.getFormFieldType())) {
            userIdList.addAll(bizIdList);
        }

        else if (FormFieldTypeEnum.DEPT.getValue().equals(nodeApproverForm.getFormFieldType())) {
            OrgApproverServiceApi orgApproverServiceApi = SpringUtil.getBean(OrgApproverServiceApi.class);
            for (Long orgId : bizIdList) {
                List<Long> tempUserIdList = orgApproverServiceApi.getDeptOrgApprover(orgId,
                        Convert.toInt(nodeApproverForm.getApproveGroupType()), 0, DetectModeEnum.TO_TOP);
                if (ObjectUtil.isNotEmpty(tempUserIdList)) {
                    userIdList.addAll(tempUserIdList);
                }
            }
        }

        return userIdList;
    }

}
