package com.qmth.sop.business.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.sop.business.activiti.service.ActivitiService;
import com.qmth.sop.business.bean.dto.DataPermissionDto;
import com.qmth.sop.business.bean.dto.OrgUserNameDto;
import com.qmth.sop.business.bean.dto.UserDto;
import com.qmth.sop.business.bean.params.FlowApproveParam;
import com.qmth.sop.business.bean.result.FlowFormWidgetResult;
import com.qmth.sop.business.bean.result.FlowResult;
import com.qmth.sop.business.bean.result.FlowTaskResult;
import com.qmth.sop.business.bean.result.TBQualityProblemApplyResult;
import com.qmth.sop.business.entity.*;
import com.qmth.sop.business.mapper.TBQualityProblemApplyMapper;
import com.qmth.sop.business.service.*;
import com.qmth.sop.common.contant.SystemConstant;
import com.qmth.sop.common.enums.*;
import com.qmth.sop.common.util.GsonUtil;
import com.qmth.sop.common.util.ServletUtil;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 质量问题反馈表 服务实现.
 *
 * @author: shudonghui
 * @date: 2023-08-14 14:00:01
 * @version: 1.0
 * @email: shudonghui@qmth.com.cn
 * @Company: www.qmth.com.cn
 */
@Service
public class TBQualityProblemApplyServiceImpl extends ServiceImpl<TBQualityProblemApplyMapper, TBQualityProblemApply> implements TBQualityProblemApplyService {

    @Resource
    TFCustomFlowEntityService tfCustomFlowEntityService;

    @Resource
    ActivitiService activitiService;

    @Resource
    TBQualityProblemApplyService tbQualityProblemApplyService;

    @Resource
    TaskService taskService;

    @Resource
    SysUserRoleService sysUserRoleService;

    @Resource
    SysUserService sysUserService;

    @Resource
    TFCustomFlowAllocationService tfCustomFlowAllocationService;

    @Resource
    TFFlowLogService tfFlowLogService;

    /**
     * 查询列表
     *
     * @param iPage
     * @return
     */
    @Override
    public IPage<TBQualityProblemApplyResult> query(IPage<Map> iPage, Long serviceId, Long userId, QualityProblemTypeEnum type, QualityProblemReasonEnum reason, InfluenceDegreeEnum degree, String custom, String problemNo, Long startTime, Long endTime) {
        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
        DataPermissionDto dpr = sysUserService.buildUserDataPermission(requestUser.getId());
        IPage<TBQualityProblemApplyResult> resultIPage = this.baseMapper.query(iPage, serviceId, userId, Objects.nonNull(type) ? type.name() : null, Objects.nonNull(reason) ? reason.name() : null, Objects.nonNull(degree) ? degree.name() : null, custom, problemNo, startTime, endTime, dpr);
        for (TBQualityProblemApplyResult p : resultIPage.getRecords()) {
            if (Objects.nonNull(p.getTaskId())) {
                Task task = taskService.createTaskQuery().taskId(String.valueOf(p.getTaskId())).singleResult();
                if (Objects.nonNull(task.getAssignee()) && task.getAssignee().equals(requestUser.getId().toString())) {
                    p.setMyself(true);
                } else {
                    List<IdentityLink> identityLinkList = taskService.getIdentityLinksForTask(task.getId());
                    if (!CollectionUtils.isEmpty(identityLinkList)) {
                        for (IdentityLink i : identityLinkList) {
                            if (Objects.nonNull(i.getUserId()) && i.getUserId().equals(requestUser.getId().toString())) {
                                p.setMyself(true);
                            }
                        }
                    }
                }
            }
            TFFlowLog tfFlowLog = tfFlowLogService.findByLastFlowLog(p.getFlowId());
            if (Objects.nonNull(tfFlowLog) && Objects.nonNull(tfFlowLog.getPendApproveId())) {
                List<String> userList = Arrays.asList(tfFlowLog.getPendApproveId().split(SystemConstant.LIST_JOIN_SPLIT));
                List<OrgUserNameDto> orgUserNameDtoList = sysUserService.findOrgUserName(userList.stream().map(s -> Long.parseLong(s)).collect(Collectors.toList()));
                List<String> userName = orgUserNameDtoList.stream().map(s -> s.getOrgUserName()).collect(Collectors.toList());
                p.setPendApproveUsers(StringUtils.join(userName, SystemConstant.LIST_JOIN_SPLIT));
            }
        }
        return resultIPage;
    }

    /**
     * 新增修改质量问题反馈表
     *
     * @param tbQualityProblemApply
     */
    @Override
    @Transactional
    public Boolean saveTBQualityProblemApply(TBQualityProblemApply tbQualityProblemApply) throws InterruptedException {
        if (tbQualityProblemApply.getFlowApprove() != FlowApprovePassEnum.START && tbQualityProblemApply.getFlowApprove() != FlowApprovePassEnum.DRAFT) {
            throw ExceptionResultEnum.PARAMS_ERROR.exception("质量问题反馈申请只能为提交或草稿");
        }
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();

        FlowTaskResult currFlowTaskResult = JSONObject.parseObject(tbQualityProblemApply.getFormProperties(), FlowTaskResult.class);
        tbQualityProblemApply = this.updateFieldValue(currFlowTaskResult, tbQualityProblemApply);

        TFCustomFlowAllocation tfCustomFlowAllocation = tfCustomFlowAllocationService.getOne(new QueryWrapper<TFCustomFlowAllocation>().lambda().eq(TFCustomFlowAllocation::getType, TFCustomTypeEnum.QUALITY_PROBLEM_FLOW));
        Optional.ofNullable(tfCustomFlowAllocation).orElseThrow(() -> ExceptionResultEnum.FLOW_ALLOCATION_NO_DATA.exception());
        Optional.ofNullable(tfCustomFlowAllocation.getRoleAllocation()).orElseThrow(() -> ExceptionResultEnum.FLOW_ALLOCATION_NO_DATA.exception());

        List<RoleTypeEnum> roleTypeEnumList = tfCustomFlowAllocationService.getRoleTypes(tfCustomFlowAllocation.getRoleAllocation(), 2);
        //查询所有审核角色
        List<UserDto> userDtoList = sysUserRoleService.userListByRoleType(roleTypeEnumList);
        if (CollectionUtils.isEmpty(userDtoList)) {
            throw ExceptionResultEnum.ERROR.exception("系统中没有" + roleTypeEnumList + "角色的用户");
        }
        List<String> approveUserIds = userDtoList.stream().map(s -> String.valueOf(s.getId())).collect(Collectors.toList());
        FlowApproveParam flowApproveParam = new FlowApproveParam(tbQualityProblemApply.getFlowDeploymentId(), tbQualityProblemApply.getFlowApprove(), tbQualityProblemApply.getFormProperties(), approveUserIds, tbQualityProblemApply.getCrmNo());
        flowApproveParam.setApproveRemark(tbQualityProblemApply.getFlowApprove().getTitle());
        Map<String, Object> map = activitiService.taskApprove(flowApproveParam);
        TFCustomFlowEntity tfCustomFlowEntity = (TFCustomFlowEntity) map.get(SystemConstant.FLOW_ENTITY);
        tbQualityProblemApply.setCode(tfCustomFlowEntity.getCode(), sysUser.getId());
        tfCustomFlowEntity.setObjId(tbQualityProblemApply.getId());
        tfCustomFlowEntityService.updateById(tfCustomFlowEntity);
        return tbQualityProblemApplyService.save(tbQualityProblemApply);
    }

    /**
     * 质量问题反馈审核
     *
     * @param flowApproveParam
     * @return
     */
    @Override
    public Boolean flowApprove(FlowApproveParam flowApproveParam) throws InterruptedException {
        Optional.ofNullable(flowApproveParam.getTaskId()).orElseThrow(() -> ExceptionResultEnum.FLOW_TASK_ID_IS_NULL.exception());
        if (flowApproveParam.getApprove() != FlowApprovePassEnum.START && flowApproveParam.getApprove() != FlowApprovePassEnum.PASS && flowApproveParam.getApprove() != FlowApprovePassEnum.REJECT && flowApproveParam.getApprove() != FlowApprovePassEnum.DRAFT) {
            throw ExceptionResultEnum.PARAMS_ERROR.exception("质量问题反馈审核只能为通过或驳回或草稿");
        }
        Optional.ofNullable(flowApproveParam.getFormProperties()).orElseThrow(() -> ExceptionResultEnum.FLOW_FORM_PROPERTIES_IS_NULL.exception());
        if (flowApproveParam.getApprove() == FlowApprovePassEnum.REJECT && Objects.isNull(flowApproveParam.getSetup())) {
            throw ExceptionResultEnum.FLOW_REJECT_SETUP_IS_NULL.exception();
        }
        FlowTaskResult formDataFlowTaskResult = JSONObject.parseObject(flowApproveParam.getFormProperties(), FlowTaskResult.class);
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        Task task = taskService.createTaskQuery().taskId(String.valueOf(flowApproveParam.getTaskId())).singleResult();
        Optional.ofNullable(task).orElseThrow(() -> ExceptionResultEnum.FLOW_TASK_NO_DATA.exception());

        List<String> taskApproveUserList = activitiService.getTaskApprove(task);
        if (flowApproveParam.getApprove() != FlowApprovePassEnum.DRAFT && !CollectionUtils.isEmpty(taskApproveUserList) && !taskApproveUserList.contains(sysUser.getId().toString())) {
            throw ExceptionResultEnum.FLOW_DATA_NOT_ME.exception();
        }

        TFCustomFlowEntity tfCustomFlowEntity = tfCustomFlowEntityService.getOne(new QueryWrapper<TFCustomFlowEntity>().lambda().eq(TFCustomFlowEntity::getFlowId, Long.parseLong(task.getProcessInstanceId())));
        Optional.ofNullable(tfCustomFlowEntity).orElseThrow(() -> ExceptionResultEnum.FLOW_ENTITY_NO_DATA.exception());

        FlowResult flowResult = JSONObject.parseObject(tfCustomFlowEntity.getFlowProcessVar(), FlowResult.class);
        LinkedHashMap<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
        FlowTaskResult currFlowTaskResult = GsonUtil.fromJson(GsonUtil.toJson(setupMap.get(task.getTaskDefinitionKey())), FlowTaskResult.class);
        currFlowTaskResult.setFormProperty(formDataFlowTaskResult.getFormProperty());

        List<String> approveUserIds = new ArrayList<>();
        if (Objects.nonNull(currFlowTaskResult) && currFlowTaskResult.getSetup().intValue() > 1) {
            FlowTaskResult flowTaskResultTemp = null;
            for (Map.Entry<String, FlowTaskResult> entry : setupMap.entrySet()) {
                flowTaskResultTemp = GsonUtil.fromJson(GsonUtil.toJson(entry.getValue()), FlowTaskResult.class);
                if (flowTaskResultTemp.getSetup().intValue() == 2) {
                    break;
                }
            }
            if (currFlowTaskResult.getSetup().intValue() == flowTaskResultTemp.getSetup().intValue()) {
                flowTaskResultTemp.setFormProperty(formDataFlowTaskResult.getFormProperty());
            }
            approveUserIds = this.getApproveUserIds(flowTaskResultTemp, currFlowTaskResult.getSetup(), approveUserIds);
        } else {
            approveUserIds.addAll(taskApproveUserList);
        }
        TBQualityProblemApply tbQualityProblemApply = this.getOne(new QueryWrapper<TBQualityProblemApply>().lambda().eq(TBQualityProblemApply::getProblemNo, tfCustomFlowEntity.getCode()));
        Optional.ofNullable(tbQualityProblemApply).orElseThrow(() -> ExceptionResultEnum.QUALITY_PROBLEM_APPLY_NO_DATA.exception());

        tbQualityProblemApply = this.updateFieldValue(currFlowTaskResult, tbQualityProblemApply);
        approveUserIds = !CollectionUtils.isEmpty(approveUserIds) ? approveUserIds : Arrays.asList(String.valueOf(sysUser.getId()));
        flowApproveParam.setApproveUserIds(approveUserIds);

        if (currFlowTaskResult.getSetup().intValue() == 3 || currFlowTaskResult.getSetup().intValue() == 4) {
            flowApproveParam.setApproveRemark("无");
            List<FlowFormWidgetResult> flowFormWidgetResultList = currFlowTaskResult.getFormProperty();
            StringJoiner stringJoiner = new StringJoiner(";");
            for (FlowFormWidgetResult f : flowFormWidgetResultList) {
                if (f.getFormId().contains(SystemConstant.SIGN)) {
                    JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                    if (Objects.nonNull(jsonObject.get(SystemConstant.VALUE))) {
                        String value = jsonObject.getString(SystemConstant.VALUE);
                        stringJoiner.add(value);
                    }
                } else if (f.getFormId().contains("approve_remark")) {
                    JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                    if (Objects.nonNull(jsonObject.get(SystemConstant.VALUE))) {
                        String value = jsonObject.getString(SystemConstant.VALUE);
                        stringJoiner.add(value);
                    }
                }
            }
            if (stringJoiner.toString().length() > 1) {
                flowApproveParam.setApproveRemark(stringJoiner.toString());
            }
        }
        activitiService.taskApprove(flowApproveParam);
        tbQualityProblemApply.updateInfo(sysUser.getId());
        return this.updateById(tbQualityProblemApply);
    }

    /**
     * 删除质量问题反馈表
     *
     * @param ids
     */
    @Override
    @Transactional
    public Boolean delete(long[] ids) {
        List<Long> idList = Arrays.stream(ids).boxed().collect(Collectors.toList());
        return this.removeByIds(idList);
    }

    @Override
    public List<SysUser> userList() {
        return this.baseMapper.userList();
    }

    /**
     * 获取审批人
     *
     * @param flowTaskResult
     * @param setup
     * @param approveUserIds
     * @return
     */
    public List<String> getApproveUserIds(FlowTaskResult flowTaskResult, Integer setup, List<String> approveUserIds) {
        List<FlowFormWidgetResult> formProperty = flowTaskResult.getFormProperty();
        for (FlowFormWidgetResult f : formProperty) {
            if (setup.intValue() == 2 && f.getFormId().contains(SystemConstant.APPROVE_CHECK_USERS) && Objects.nonNull(f.getValue()) && !f.getValue().contains("null")) {//获取甲方复核人员
//                String string = f.getValue().replaceAll("\\[", "").replaceAll("\\]", "");
//                approveUserIds = Arrays.asList(StringUtils.split(string, ","));
                JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                JSONArray jsonArray = jsonObject.getJSONArray(SystemConstant.VALUE);
                StringJoiner stringJoiner = new StringJoiner(",");
                for (int i = 0; i < jsonArray.size(); i++) {
                    approveUserIds.add(jsonArray.getString(i));
                }
                break;
            } else if (setup.intValue() == 3 && f.getFormId().contains(SystemConstant.APPROVE_CHECK_THIRD_USERS) && Objects.nonNull(f.getValue()) && !f.getValue().contains("null")) {//获取已方复核人员
//                String string = f.getValue().replaceAll("\\[", "").replaceAll("\\]", "");
//                approveUserIds = Arrays.asList(StringUtils.split(string, ","));
                JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                JSONArray jsonArray = jsonObject.getJSONArray(SystemConstant.VALUE);
                StringJoiner stringJoiner = new StringJoiner(",");
                for (int i = 0; i < jsonArray.size(); i++) {
                    approveUserIds.add(jsonArray.getString(i));
                }
                break;
            }
        }
        if (setup.intValue() == 2 && CollectionUtils.isEmpty(approveUserIds)) {
            throw ExceptionResultEnum.ERROR.exception("甲方复核人不能为空");
        } else if (setup.intValue() == 3 && CollectionUtils.isEmpty(approveUserIds)) {
            throw ExceptionResultEnum.ERROR.exception("已方复核人不能为空");
        }
        return approveUserIds;
    }

    /**
     * 更新字段
     *
     * @param currFlowTaskResult
     * @param tbQualityProblemApply
     * @return
     */
    public TBQualityProblemApply updateFieldValue(FlowTaskResult currFlowTaskResult, TBQualityProblemApply tbQualityProblemApply) {
        List<FlowFormWidgetResult> formWidgetResultList = currFlowTaskResult.getFormProperty();
        if (!CollectionUtils.isEmpty(formWidgetResultList)) {//更新字段
            for (FlowFormWidgetResult f : formWidgetResultList) {
                if (f.getFormId().contains(SystemConstant.PROBLEM_POINT) && Objects.nonNull(f.getValue()) && !f.getValue().contains("null")) {//问题简要
                    JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                    String value = jsonObject.getString(SystemConstant.VALUE);
                    tbQualityProblemApply.setSummary(value);
                }
                if (f.getFormId().contains(SystemConstant.PROBLEM_REMARK) && Objects.nonNull(f.getValue()) && !f.getValue().contains("null")) {//问题情况说明
                    JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                    String value = jsonObject.getString(SystemConstant.VALUE);
                    tbQualityProblemApply.setRemark(value);
                }
                if (f.getFormId().contains(SystemConstant.ATTACHMENT_INFO) && Objects.nonNull(f.getValue()) && !f.getValue().contains("null")) {//附件id数组
                    JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                    JSONArray jsonArray = jsonObject.getJSONArray(SystemConstant.VALUE);
                    StringJoiner stringJoiner = new StringJoiner(",");
                    for (int i = 0; i < jsonArray.size(); i++) {
                        stringJoiner.add(jsonArray.getString(i));
                    }
                    tbQualityProblemApply.setAttachmentIds(stringJoiner.toString());
                }
                if (f.getFormId().contains(SystemConstant.PROBLEM_TYPE) && Objects.nonNull(f.getValue()) && !f.getValue().contains("null")) {//质量问题类型
                    JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                    String value = jsonObject.getString(SystemConstant.VALUE);
                    tbQualityProblemApply.setType(QualityProblemTypeEnum.valueOf(value));
                }
                if (f.getFormId().contains(SystemConstant.PROBLEM_REASON_RADIO) && Objects.nonNull(f.getValue()) && !f.getValue().contains("null")) {//问题归因
                    JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                    String value = jsonObject.getString(SystemConstant.VALUE);
                    tbQualityProblemApply.setReason(QualityProblemReasonEnum.valueOf(value));
                }
                if (f.getFormId().contains(SystemConstant.PROBLEM_DEGREE_RADIO) && Objects.nonNull(f.getValue()) && !f.getValue().contains("null")) {//问题影响度
                    JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                    String value = jsonObject.getString(SystemConstant.VALUE);
                    tbQualityProblemApply.setInfluenceDegree(InfluenceDegreeEnum.valueOf(value));
                }
                if (f.getFormId().contains(SystemConstant.PROBLEM_USERS) && Objects.nonNull(f.getValue()) && !f.getValue().contains("null")) {//责任人
                    JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                    JSONArray jsonArray = jsonObject.getJSONArray(SystemConstant.VALUE);
                    StringJoiner stringJoiner = new StringJoiner(",");
                    for (int i = 0; i < jsonArray.size(); i++) {
                        stringJoiner.add(jsonArray.getString(i));
                    }
                    tbQualityProblemApply.setUserIds(stringJoiner.toString());
                }
            }
        }
        return tbQualityProblemApply;
    }
}