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

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.google.gson.reflect.TypeToken;
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.*;
import com.qmth.sop.business.entity.*;
import com.qmth.sop.business.mapper.TBProjectExchangeMapper;
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;

/**
 * <p>
 * 项目变更计划表 服务实现类
 * </p>
 *
 * @author wangliang
 * @since 2023-08-01
 */
@Service
public class TBProjectExchangeServiceImpl extends ServiceImpl<TBProjectExchangeMapper, TBProjectExchange> implements TBProjectExchangeService {

    @Resource
    ActivitiService activitiService;

    @Resource
    TFCustomFlowEntityService tfCustomFlowEntityService;

    @Resource
    TaskService taskService;

    @Resource
    TBProjectExchangeService tbProjectExchangeService;

    @Resource
    SysUserRoleService sysUserRoleService;

    @Resource
    TBCrmService tbCrmService;

    @Resource
    SysUserService sysUserService;

    @Resource
    TFFlowLogService tfFlowLogService;

    @Resource
    TFFlowApproveService tfFlowApproveService;

    @Resource
    TFCustomFlowAllocationService tfCustomFlowAllocationService;

    /**
     * 新增项目变更计划申请
     *
     * @param tbProjectExchange
     * @return
     * @throws InterruptedException
     */
    @Override
    @Transactional
    public Boolean saveProjectExchange(TBProjectExchange tbProjectExchange) throws InterruptedException {
        if (tbProjectExchange.getFlowApprove() != FlowApprovePassEnum.START && tbProjectExchange.getFlowApprove() != FlowApprovePassEnum.DRAFT) {
            throw ExceptionResultEnum.PARAMS_ERROR.exception("项目计划变更申请只能为提交或草稿");
        }
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();

        TFCustomFlowAllocation tfCustomFlowAllocation = tfCustomFlowAllocationService.getOne(new QueryWrapper<TFCustomFlowAllocation>().lambda().eq(TFCustomFlowAllocation::getType, TFCustomTypeEnum.PROJECT_EXCHANGE_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(tbProjectExchange.getFlowDeploymentId(), tbProjectExchange.getFlowApprove(), approveUserIds, tbProjectExchange.getCrmNo());
        flowApproveParam.setApproveRemark(tbProjectExchange.getFlowApprove().getTitle());
        Map<String, Object> map = activitiService.taskApprove(flowApproveParam);
        TFCustomFlowEntity tfCustomFlowEntity = (TFCustomFlowEntity) map.get(SystemConstant.FLOW_ENTITY);
        tbProjectExchange.setCode(tfCustomFlowEntity.getCode(), sysUser.getId());
        tfCustomFlowEntity.setObjId(tbProjectExchange.getId());
        tfCustomFlowEntityService.updateById(tfCustomFlowEntity);
        return tbProjectExchangeService.save(tbProjectExchange);
    }

    /**
     * 项目变更计划申请列表
     *
     * @param iPage
     * @param serviceId
     * @param createUserId
     * @param type
     * @param customType
     * @param flowStatus
     * @param customName
     * @param exchangeNo
     * @param startTime
     * @param endTime
     * @return
     */
    @Override
    public IPage<ProjectExchangeResult> list(IPage<Map> iPage, Long serviceId, Long createUserId, DelayWarnTypeEnum type, ProductTypeEnum customType, ProjectExchangeFlowStatusEnum flowStatus, String customName, String exchangeNo, Long startTime, Long endTime) {
        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
        DataPermissionDto dpr = sysUserService.buildUserDataPermission(requestUser.getId());
        IPage<ProjectExchangeResult> list = this.baseMapper.list(iPage, serviceId, createUserId, Objects.nonNull(type) ? type.name() : null, Objects.nonNull(customType) ? customType.name() : null, Objects.nonNull(flowStatus) ? flowStatus.name() : null, customName, exchangeNo, startTime, endTime, dpr);
        for (ProjectExchangeResult p : list.getRecords()) {
            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.setApproveUsersName(StringUtils.join(userName, SystemConstant.LIST_JOIN_SPLIT));
            }
            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);
                            }
                        }
                    }
                }
            }
        }
        return list;
    }

    /**
     * 项目计划变更审核接口
     *
     * @param taskId
     * @param flowApprove
     * @param projectExchangeApprove
     * @param remark
     * @param userId
     * @return
     * @throws InterruptedException
     */
    @Override
    @Transactional
    public Boolean flowApprove(Long taskId, FlowApprovePassEnum flowApprove, ProjectExchangeApproveEnum projectExchangeApprove, String remark, Long userId) throws InterruptedException {
        Optional.ofNullable(taskId).orElseThrow(() -> ExceptionResultEnum.FLOW_TASK_ID_IS_NULL.exception());
        if (flowApprove != FlowApprovePassEnum.START && flowApprove != FlowApprovePassEnum.PASS && flowApprove != FlowApprovePassEnum.DRAFT) {
            throw ExceptionResultEnum.PARAMS_ERROR.exception("项目计划变更审批只能为通过或草稿");
        }
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        userId = Objects.nonNull(sysUser) ? sysUser.getId() : userId;
        Task task = taskService.createTaskQuery().taskId(String.valueOf(taskId)).singleResult();
        Optional.ofNullable(task).orElseThrow(() -> ExceptionResultEnum.FLOW_TASK_NO_DATA.exception());

        List<String> taskApproveUserList = activitiService.getTaskApprove(task);
        if (!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())));
        activitiService.taskApprove(new FlowApproveParam(taskId, flowApprove, Arrays.asList(String.valueOf(userId)), tfCustomFlowEntity.getCrmNo(), projectExchangeApprove.getTitle() + ";" + remark));

        TBProjectExchange tbProjectExchange = this.getOne(new QueryWrapper<TBProjectExchange>().lambda().eq(TBProjectExchange::getExchangeNo, tfCustomFlowEntity.getCode()));
        Optional.ofNullable(tbProjectExchange).orElseThrow(() -> ExceptionResultEnum.PROJECT_EXCHANGE_NO_DATA.exception());

        tbProjectExchange.setResult(projectExchangeApprove);
        tbProjectExchange.setRemark(remark);
        return tbProjectExchangeService.updateById(tbProjectExchange);
    }

    /**
     * 项目计划变更详情接口
     *
     * @param id
     * @return
     */
    @Override
    public TBProjectExchangeViewResult view(Long id) {
        TBProjectExchange tbProjectExchange = this.getById(id);
        Optional.ofNullable(tbProjectExchange).orElseThrow(() -> ExceptionResultEnum.PROJECT_EXCHANGE_NO_DATA.exception());

        CrmProjectResult crmProjectResult = tbCrmService.findCrmProjectBySopNoOrCrmNo(tbProjectExchange.getSopNo(), tbProjectExchange.getCrmNo());
        Optional.ofNullable(crmProjectResult).orElseThrow(() -> ExceptionResultEnum.CRM_NO_NO_DATA.exception());

        TFCustomFlowEntity tfCustomFlowEntity = tfCustomFlowEntityService.getOne(new QueryWrapper<TFCustomFlowEntity>().lambda().eq(TFCustomFlowEntity::getCode, tbProjectExchange.getExchangeNo()));
        Optional.ofNullable(tfCustomFlowEntity).orElseThrow(() -> ExceptionResultEnum.FLOW_ENTITY_NO_DATA.exception());

        //获取当前流程节点
        TFFlowApprove tfFlowApprove = tfFlowApproveService.getOne(new QueryWrapper<TFFlowApprove>().lambda().eq(TFFlowApprove::getFlowId, tfCustomFlowEntity.getFlowId()));
        Optional.ofNullable(tfFlowApprove).orElseThrow(() -> ExceptionResultEnum.FLOW_APPROVE_NO_DATA.exception());

        FlowResult flowResult = JSONObject.parseObject(tfCustomFlowEntity.getFlowProcessVar(), FlowResult.class);
        LinkedHashMap<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
        FlowTaskResult currFlowTaskResult = null;
        List<FlowTaskResult> flowTaskHistoryList = null;
        List<Long> taskIdList = null;

        //获取流程审批历史
        List<TFFlowViewLogResult> flowApproveHistoryList = null;
        Map<Integer, Integer> approveSetupMap = new HashMap<>();
        List<TFFlowLogResult> tfFlowLogResultList = tfFlowLogService.findByObjectId(tfCustomFlowEntity.getId());
        if (!CollectionUtils.isEmpty(tfFlowLogResultList)) {
            flowApproveHistoryList = GsonUtil.fromJson(GsonUtil.toJson(tfFlowLogResultList), new TypeToken<List<TFFlowViewLogResult>>() {
            }.getType());
            for (TFFlowViewLogResult t : flowApproveHistoryList) {
                t.setMessageType(FlowMsgTypeEnum.STANDARD);
                approveSetupMap.put(t.getApproveSetup(), t.getApproveSetup());
                if (Objects.nonNull(t.getApproveOperation())) {
                    t.setApproveRemark(t.getApproveOperation().getTitle());
                }
            }
        }
        for (Map.Entry<String, FlowTaskResult> entry : setupMap.entrySet()) {
            FlowTaskResult flowTaskResult = GsonUtil.fromJson(GsonUtil.toJson(entry.getValue()), FlowTaskResult.class);
            if (flowTaskResult.getSetup() > 0) {
                //正在审批的表单
                if (Objects.nonNull(tfFlowApprove.getSetup()) && flowTaskResult.getSetup().intValue() == tfFlowApprove.getSetup().intValue()) {
                    currFlowTaskResult = flowTaskResult;
                    List<Task> taskList = taskService.createTaskQuery().processInstanceId(String.valueOf(tfCustomFlowEntity.getFlowId())).list();
                    if (!CollectionUtils.isEmpty(taskList)) {
                        taskIdList = taskList.stream().map(s -> Long.parseLong(s.getId())).collect(Collectors.toList());
                    }
                } else if (approveSetupMap.containsKey(flowTaskResult.getSetup())) {//已经审批过的表单
                    flowTaskHistoryList = CollectionUtils.isEmpty(flowTaskHistoryList) ? new ArrayList<>(approveSetupMap.size()) : flowTaskHistoryList;
                    flowTaskHistoryList.add(flowTaskResult);
                }
            }
        }
        return new TBProjectExchangeViewResult(crmProjectResult, tbProjectExchange, taskIdList, flowTaskHistoryList, currFlowTaskResult, flowApproveHistoryList);
    }
}
