/*
 * Copyright (c) 2023 codvision.com All Rights Reserved.
 */

package com.codvision.workflow.service.impl;

import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.codvision.commoncore.utils.Preconditions;
import com.codvision.workflow.entity.QuestionnaireModule;
import com.codvision.workflow.entity.WorkFlowData;
import com.codvision.workflow.entity.WorkFlowForm;
import com.codvision.workflow.entity.WorkFlowSubData;
import com.codvision.workflow.entity.vo.WorkFlowFormVO;
import com.codvision.workflow.mapper.QuestionnaireModuleMapper;
import com.codvision.workflow.mapper.WorkFlowDataMapper;
import com.codvision.workflow.mapper.WorkFlowFormMapper;
import com.codvision.workflow.mapper.WorkFlowSubDataMapper;
import com.codvision.workflow.service.WorkFlowFormService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * @author hxl
 */
@Service
@RequiredArgsConstructor
public class WorkFlowFormServiceImpl extends ServiceImpl<WorkFlowFormMapper, WorkFlowForm> implements WorkFlowFormService {

    private final WorkFlowDataMapper dataMapper;
    private final WorkFlowSubDataMapper subDataMapper;
    private final QuestionnaireModuleMapper moduleMapper;

    @Override
    public List<WorkFlowForm> elementFormList(String definitionId) {
        return this.list(Wrappers.<WorkFlowForm>lambdaQuery().eq(WorkFlowForm::getDefinitionId, definitionId));
    }

    @Override
    public void addFormAuth(String definitionId, String definitionKey, String startElementKey, Integer formId, Map<String, Object> params) {
        for (Map.Entry<String, Object> next : params.entrySet()) {
            WorkFlowForm workFlowForm = WorkFlowForm.builder().definitionId(definitionId).definitionKey(definitionKey).formId(formId).build();
            if (startElementKey.equals(next.getKey())) {
                workFlowForm.setIsStartForm(true);
            }

            workFlowForm.setElementKey(next.getKey());
            workFlowForm.setFormAuthJson(JSONUtil.toJsonStr(next.getValue()));
            this.save(workFlowForm);
        }
    }

    @Override
    public WorkFlowFormVO getAllFormInfo(String definitionId, String instanceId) {
        WorkFlowForm workFlowForm = this.getOne(Wrappers.<WorkFlowForm>lambdaQuery().eq(WorkFlowForm::getIsStartForm, true).eq(WorkFlowForm::getDefinitionId, definitionId));
        Preconditions.checkArgument(workFlowForm != null, "获取发起表单权限信息失败");

        WorkFlowFormVO workFlowFormVO = new WorkFlowFormVO();
        workFlowFormVO.setFormJson(initValueIfNecessary(workFlowForm.getFormId(), instanceId, null));
        return workFlowFormVO;
    }

    @Override
    public WorkFlowFormVO getStartFormAuth(String definitionId, String instanceId) {
        WorkFlowForm workFlowForm = this.getOne(Wrappers.<WorkFlowForm>lambdaQuery().eq(WorkFlowForm::getIsStartForm, true).eq(WorkFlowForm::getDefinitionId, definitionId));
        Preconditions.checkArgument(workFlowForm != null, "获取发起表单权限信息失败");

        WorkFlowFormVO workFlowFormVO = new WorkFlowFormVO();
        workFlowFormVO.setFormAuthJson(workFlowForm.getFormAuthJson());

        if (StringUtils.isNotBlank(instanceId)) {
            workFlowFormVO.setFormJson(initValueIfNecessary(workFlowForm.getFormId(), instanceId, null));
            return workFlowFormVO;
        }

        workFlowFormVO.setFormJson(getFormInfo(workFlowForm.getFormId()));
        return workFlowFormVO;
    }

    @Override
    public WorkFlowFormVO getTaskFormAuth(String definitionId, String elementKey, String instanceId, String taskId) {
        WorkFlowForm workFlowForm = this.getOne(Wrappers.<WorkFlowForm>lambdaQuery().eq(WorkFlowForm::getElementKey, elementKey).eq(WorkFlowForm::getDefinitionId, definitionId));
        Preconditions.checkArgument(workFlowForm != null, "获取任务表单权限信息失败");
        return WorkFlowFormVO.builder().formJson(initValueIfNecessary(workFlowForm.getFormId(), instanceId, taskId)).formAuthJson(workFlowForm.getFormAuthJson()).build();
    }

    public WorkFlowForm getTaskFormAuth(String definitionId, String elementKey) {
        return this.getOne(Wrappers.<WorkFlowForm>lambdaQuery().eq(WorkFlowForm::getElementKey, elementKey).eq(WorkFlowForm::getDefinitionId, definitionId));
    }

    private List<QuestionnaireModule> initValueIfNecessary(Integer formId, String instanceId, String taskId) {
        WorkFlowData workFlowData = dataMapper.selectOne(Wrappers.<WorkFlowData>lambdaQuery().eq(WorkFlowData::getInstanceId, instanceId));
        Preconditions.checkArgument(workFlowData != null, "获取表单数据失败");

        Map<String, Object> subDataMap = null;
        if (StringUtils.isNotBlank(taskId)) {
            WorkFlowSubData workFlowSubData = subDataMapper.selectOne(Wrappers.<WorkFlowSubData>lambdaQuery().eq(WorkFlowSubData::getTaskId, taskId));
            if (workFlowSubData != null) {
                subDataMap = JSONUtil.parseObj(workFlowSubData.getFormDataJson());
            }
        }

        Map<String, Object> dataMap = JSONUtil.parseObj(workFlowData.getFormDataJson());
        List<QuestionnaireModule> modules = getFormInfo(formId);
        for (QuestionnaireModule module : modules) {
            if (MapUtil.isNotEmpty(subDataMap)) {
                if (subDataMap.containsKey(module.getAttribute())) {
                    module.setValue(String.valueOf(subDataMap.get(module.getAttribute())));
                }
            } else {
                if (dataMap.containsKey(module.getAttribute())) {
                    module.setValue(String.valueOf(dataMap.get(module.getAttribute())));
                }
            }
        }

        return modules;
    }

    private List<QuestionnaireModule> getFormInfo(Integer formId) {
        List<QuestionnaireModule> modules = moduleMapper.selectList(Wrappers.<QuestionnaireModule>lambdaQuery()
                .eq(QuestionnaireModule::getQuestionnaireId, formId).orderByAsc(QuestionnaireModule::getSort));
        Preconditions.checkArgument(CollectionUtils.isNotEmpty(modules),"获取表单信息失败");
        return modules;
    }

    public void delAllByDefinitionId(String definitionId) {
        this.remove(Wrappers.<WorkFlowForm>lambdaQuery().eq(WorkFlowForm::getDefinitionId, definitionId));
    }

}
