package com.yeejoin.amos.boot.module.hygf.biz.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.entity.BaseEntity;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.module.hygf.api.Enum.BusinessTypeEnum;
import com.yeejoin.amos.boot.module.hygf.api.Enum.FinancingAuditEnum;
import com.yeejoin.amos.boot.module.hygf.api.Enum.FlowStatusEnum;
import com.yeejoin.amos.boot.module.hygf.api.Enum.TaskStatusEnum;
import com.yeejoin.amos.boot.module.hygf.api.config.UserLimits;
import com.yeejoin.amos.boot.module.hygf.api.dto.FinancingAuditingDto;
import com.yeejoin.amos.boot.module.hygf.api.dto.FinancingInfoDto;
import com.yeejoin.amos.boot.module.hygf.api.dto.TaskModelDto;
import com.yeejoin.amos.boot.module.hygf.api.dto.WorkflowResultDto;
import com.yeejoin.amos.boot.module.hygf.api.entity.FinancingAuditing;
import com.yeejoin.amos.boot.module.hygf.api.entity.FinancingInfo;
import com.yeejoin.amos.boot.module.hygf.api.entity.FinancingRectificationOrder;
import com.yeejoin.amos.boot.module.hygf.api.entity.StdUserEmpower;
import com.yeejoin.amos.boot.module.hygf.api.mapper.FinancingInfoMapper;
import com.yeejoin.amos.boot.module.hygf.api.service.IFinancingInfoService;
import com.yeejoin.amos.boot.module.hygf.api.util.RedisLockUtil;
import com.yeejoin.amos.feign.workflow.model.ActWorkflowBatchDTO;
import com.yeejoin.amos.feign.workflow.model.ActWorkflowStartDTO;
import com.yeejoin.amos.feign.workflow.model.ProcessTaskDTO;
import com.yeejoin.amos.feign.workflow.model.TaskResultDTO;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.rdbms.service.BaseService;

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

/**
 * 服务实现类
 *
 * @author system_generator
 * @date 2024-04-01
 */
@Service
public class FinancingInfoServiceImpl extends BaseService<FinancingInfoDto, FinancingInfo, FinancingInfoMapper> implements IFinancingInfoService {
    private static String PROCESSKEY = "StationFinancing";
    @Autowired
    RedisUtils redisUtils;
    /**
     * 分页查询
     */
    @Autowired
    private FinancingInfoMapper financingInfoMapper;
    @Autowired
    private WorkFlowService workFlowService;
    @Autowired
    private WorkflowImpl workflow;
    @Autowired
    private FinancingAuditingServiceImpl financingAuditingService;
    @Autowired
    private FinancingRectificationOrderServiceImpl financingRectificationOrderService;
    @Autowired
    private CommonServiceImpl commonService;

    @Resource(type = RedisLockUtil.class)
    private RedisLockUtil redisLockUtil;

    @UserLimits
    public Page<Map<String, Object>> queryForFinancingInfoPage(Page<Map<String, Object>> page, String type, String status, String regionalCompaniesCode, String ownersName) {
        StdUserEmpower orgCode = (StdUserEmpower) redisUtils.get("Emp_" + RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken()));
        ReginParams reginParams = JSON.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        List<String> amosOrgCodes = orgCode.getAmosOrgCode();
        Map<String, Object> params = new HashMap<>();
        params.put("ownersName", ownersName);
        params.put("status", status);
        params.put("regionalCompaniesCode", regionalCompaniesCode);
        params.put("type", type);
        // 1 投融人员  2.融资  3经销商管理员
        switch (type) {
            case "1":
                break;
            case "2":
                Long sequenceNbr = reginParams.getCompany().getSequenceNbr();
                params.put("financingCompaniesSeq", String.valueOf(sequenceNbr));
                break;
            default:
                amosOrgCodes = Arrays.asList(orgCode.getAdminRegionalCompaniesCode().split(","));
        }
        PageHelper.startPage((int) page.getCurrent(), (int) page.getSize());
        List<Map<String, Object>> list = financingInfoMapper.getStationFinancingInfoList(params, amosOrgCodes);
        list.forEach(e -> {
            if (null != e.get("instanceId") && e.get("instanceId").toString().contains(",")) {
                String[] instanceIds = e.get("instanceId").toString().split(",");
                e.put("instanceId", instanceIds[0]);
                e.put("nodeRouting", instanceIds[1]);
            }
        });
        PageInfo<Map<String, Object>> infos = new PageInfo<>(list);
        page.setRecords(list);
        page.setTotal(infos.getTotal());
        return page;
    }

    /**
     * 列表查询 示例
     */
    public List<FinancingInfoDto> queryForFinancingInfoList() {
        return this.queryForList("", false);
    }

    public FinancingInfoDto saveModel(FinancingInfoDto model) {
        String lockName = String.format("LockName:powerStationExamine");
        try{
            Boolean isLocked = redisLockUtil.tryLock(lockName, lockName, 10, 1);
            if (BooleanUtils.isNotTrue(isLocked)) {
                throw new com.yeejoin.amos.component.robot.BadRequest("其他用户正在操作，请刷新后再试！");
            }

            List<String> ids;
            if (model.getPeasantHouseholdIds().contains(",")) {
                ids = Arrays.asList(model.getPeasantHouseholdIds().split(","));
            } else {
                ids = Arrays.asList(new String[]{model.getPeasantHouseholdIds()});
            }
            Map<String, Object> orgInfo = this.getBaseMapper().selectRZOrgInfo(model.getFinancingCompaniesSeq());
            model.setFinancingCompaniesCode(orgInfo.getOrDefault("ORG_CODE", "").toString());
            model.setFinancingCompaniesName(orgInfo.getOrDefault("COMPANY_NAME", "").toString());
            ids.stream().forEach(e -> {
                LambdaQueryWrapper<FinancingInfo> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(FinancingInfo::getPeasantHouseholdId, Long.valueOf(e));
                FinancingInfo financingInfos = this.getBaseMapper().selectOne(queryWrapper);
                if (ObjectUtils.isEmpty(financingInfos)) {
                    model.setStatus(FinancingAuditEnum.待融资审核.getName());
                    model.setPeasantHouseholdId(Long.valueOf(e));
                    FinancingInfoDto financingInfoDto = new FinancingInfoDto();
                    BeanUtils.copyProperties(model, financingInfoDto);
                    financingInfoDto.setSequenceNbr(null);
                    this.createWithModel(financingInfoDto);
                    //开启工作流 并执行一步
                    ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
                    List<ActWorkflowStartDTO> list = new ArrayList<>();
                    ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
                    dto.setProcessDefinitionKey(PROCESSKEY);
                    Date date = new Date();
                    dto.setBusinessKey(String.valueOf(date.getTime()));
                    dto.setCompleteFirstTask(true);
                    //工作流程图第一步执行后存在互斥网关 isFlag为表达式 默认为1执行到融资审核
                    HashMap<String, Object> map = new HashMap<>();
                    map.put("isFlag", "0");
                    dto.setVariables(map);
                    list.add(dto);
                    actWorkflowBatchDTO.setProcess(list);
                    List<ProcessTaskDTO> processTaskDTOS = workFlowService.startBatch(actWorkflowBatchDTO);
                    List<WorkflowResultDto> workflowResultDtos = workFlowService.buildWorkFlowInfo(processTaskDTOS);
                    WorkflowResultDto workflowResultDto = workflowResultDtos.get(0);
                    FinancingAuditingDto financingAuditingDto = new FinancingAuditingDto();
                    BeanUtils.copyProperties(workflowResultDto, financingAuditingDto);
                    financingAuditingDto.setPeasantHouseholdId(Long.valueOf(e));
                    financingAuditingDto.setPromoter(RequestContext.getExeUserId());
                    financingAuditingService.createWithModel(financingAuditingDto);
                }
                //批量 兼容审核不通过及整改待推送
                else if (financingInfos.getStatus().equals(FinancingAuditEnum.审核不通过.getName()) || financingInfos.getStatus().equals(FinancingAuditEnum.整改待推送.getName()) ){
                    financingInfos.setStatus(FinancingAuditEnum.待融资审核.getName());

                    Map<String, Object> orgInfo1 = this.getBaseMapper().selectRZOrgInfo(model.getFinancingCompaniesSeq());
                    //业务表中无工作流id 需要补充
                    LambdaQueryWrapper<FinancingAuditing> queryWrapper1 = new LambdaQueryWrapper<>();
                    queryWrapper1.eq(FinancingAuditing::getPeasantHouseholdId, Long.valueOf(e));
                    queryWrapper1.orderByDesc(BaseEntity::getRecDate);
                    queryWrapper1.last("limit 1");
                    FinancingAuditing financingInfos1 = financingAuditingService.getBaseMapper().selectOne(queryWrapper1);


                    financingInfos.setFinancingCompaniesCode(orgInfo1.getOrDefault("ORG_CODE", "").toString());
                    financingInfos.setFinancingCompaniesName(orgInfo1.getOrDefault("COMPANY_NAME", "").toString());
                    this.updateById(financingInfos);
                    Map<String, Object> map = BeanUtil.beanToMap(financingInfos);
                    map.put("isFlag","0");
                    map.put("instanceId",financingInfos1.getInstanceId());
                    this.execueFlow(map);
                }
                //发起待办
//            commonService.buildTaskModel(buildDZTRZTaskModel(model, workflowResultDto, date));
            });
        }finally {
            redisLockUtil.releaseLock(lockName);
        }
        return model;
    }

    private List<TaskModelDto> buildDZTRZTaskModel(FinancingInfoDto model, WorkflowResultDto workflowResultDto, Date startDate) {
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        List<TaskModelDto> taskModelDtoList = new ArrayList<>();
        TaskModelDto taskModelDto = new TaskModelDto();
        taskModelDto.setFlowCode(workflowResultDto.getNextTaskId());
        taskModelDto.setFlowCreateDate(new Date());
        taskModelDto.setFlowStatus(FlowStatusEnum.TO_BE_PROCESSED.getCode());
        taskModelDto.setFlowStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
        taskModelDto.setPageType(null);
        taskModelDto.setExecuteUserIds(workflowResultDto.getNextExecuteUserIds());
        taskModelDto.setModel(model);
        taskModelDto.setRelationId(workflowResultDto.getInstanceId());
        taskModelDto.setRoutePath(null);
        taskModelDto.setStartUserId(reginParams.getUserModel().getUserId());
        taskModelDto.setStartUser(reginParams.getUserModel().getUserName());
        taskModelDto.setStartDate(startDate);
        taskModelDto.setStartUserCompanyName(null);
        taskModelDto.setTaskName(workflowResultDto.getNextNodeName());
        taskModelDto.setTaskCode(workflowResultDto.getNextNodeCode());
        taskModelDto.setTaskType(BusinessTypeEnum.HYGF_DZTRRZ.getCode());
        taskModelDto.setTaskTypeLabel(BusinessTypeEnum.HYGF_DZTRRZ.getName());
        taskModelDto.setTaskStatus(TaskStatusEnum.UNDERWAY.getValue());
        taskModelDto.setTaskStatusLabel(TaskStatusEnum.UNDERWAY.getName());
//        taskModelDto.setTaskDesc();
//        taskModelDto.setTaskContent();
        taskModelDto.setNextExecuteUser(workflowResultDto.getNextExecutorIds());
        taskModelDtoList.add(taskModelDto);
        return taskModelDtoList;
    }


    @Override
    public void rollback(String processId, String peasantHouseholdId) {
        workFlowService.stopProcess(processId);
        LambdaQueryWrapper<FinancingInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FinancingInfo::getPeasantHouseholdId, peasantHouseholdId);
        List<FinancingInfo> financingInfos = this.getBaseMapper().selectList(queryWrapper);

        if (!CollectionUtils.isEmpty(financingInfos)) {
            FinancingInfo financingInfo = financingInfos.get(0);

            LambdaQueryWrapper<FinancingAuditing> wrapper = new LambdaQueryWrapper();
            wrapper.eq(FinancingAuditing::getPeasantHouseholdId,financingInfo.getPeasantHouseholdId());
            financingAuditingService.getBaseMapper().delete(wrapper);

            LambdaQueryWrapper<FinancingRectificationOrder> wrapper1 = new LambdaQueryWrapper();
            wrapper1.eq(FinancingRectificationOrder::getPeasantHouseholdId,financingInfo.getPeasantHouseholdId());
            financingRectificationOrderService.getBaseMapper().delete(wrapper1);

            this.deleteBySeq(financingInfo.getSequenceNbr());
        }
    }

    @Override
    public FinancingInfoDto selectDataInfo(Long peasantHouseholdId) {
        FinancingInfoDto financingInfoDto = this.getBaseMapper().selectDataInfo(peasantHouseholdId);
        financingInfoDto.setFiles(JSONArray.parseArray(financingInfoDto.getFile()));
        return financingInfoDto;
    }

    @Override
    public void execueFlow(Map<String, Object> params) {
        LambdaQueryWrapper<FinancingAuditing> query = new LambdaQueryWrapper<>();
        query.eq(FinancingAuditing::getInstanceId, params.get("instanceId").toString());
        query.orderByDesc(BaseEntity::getRecDate);
        query.last("limit 1");
        FinancingAuditing financingAuditing = financingAuditingService.getBaseMapper().selectOne(query);

        //组装信息
        TaskResultDTO task = new TaskResultDTO();

        task.setTaskId(financingAuditing.getNextTaskId());
        HashMap<String, Object> map = new HashMap<>();
        FinancingAuditingDto financingAuditingDto = new FinancingAuditingDto();

        //此处是工作流网关路线原因 相同参数存在工作流不知道怎么执行报错问题 暂未排除问题 先修改不同表达式
        if (params.containsKey("isFlag")) {
            task.setResultCode("isFlag");
            map.put("isFlag", params.get("isFlag"));
            if (params.get("isFlag").equals("1")) {
                params.put("comments", "退回整改");
                params.put("approvalStatus",params.getOrDefault("problemDescription",""));
            }else {
                params.put("approvalStatus","");

            }
        } else {
            task.setResultCode("approvalStatus");
            map.put("approvalStatus", params.get("approvalStatus"));
        }
        task.setComment(params.getOrDefault("comments", "").toString());
        task.setVariable(map);
        //执行流程
        ProcessTaskDTO processTaskDTO = workFlowService.complete(financingAuditing.getNextTaskId(), task);
        List<WorkflowResultDto> workflowResultDtos = workFlowService.buildWorkFlowInfo(CollectionUtil.newArrayList(processTaskDTO));
        WorkflowResultDto workflowResultDto = workflowResultDtos.get(0);
        BeanUtils.copyProperties(workflowResultDto, financingAuditingDto);
        financingAuditingDto.setPeasantHouseholdId(financingAuditing.getPeasantHouseholdId());
        financingAuditingDto.setPromoter(financingAuditing.getPromoter());
        if (null == financingAuditingDto.getInstanceId()) {
            financingAuditingDto.setInstanceId(financingAuditing.getInstanceId());
        }
        financingAuditingDto.setStatus(params.getOrDefault("comments", "").toString());
        financingAuditingDto.setNodeRouting(FinancingAuditEnum.getNodeByCode(workflowResultDto.getNextNodeKey()));
        financingAuditingService.createWithModel(financingAuditingDto);

        String nameByCode = FinancingAuditEnum.getNameByCode(workflowResultDto.getNextNodeKey());
        String statusName = nameByCode == null || nameByCode.equals("") ? "放款完成" : nameByCode;

        LambdaQueryWrapper<FinancingInfo> info = new LambdaQueryWrapper<>();
        info.eq(FinancingInfo::getPeasantHouseholdId, financingAuditing.getPeasantHouseholdId());
        FinancingInfo financingInfo = this.getBaseMapper().selectOne(info);
        if (params.containsKey("financingCompaniesSeq") && params.get("financingCompaniesSeq")!= null) {
            financingInfo.setFinancingCompaniesSeq(Long.valueOf(params.get("financingCompaniesSeq").toString()));
        }
        //标识对于整改待推送状态
        if (params.containsKey("isZG")) {
            financingInfo.setStatus("整改待推送");
        } else {
            financingInfo.setStatus(statusName);
        }


        this.updateById(financingInfo);

        //节点为待整改时生成整改单
        if (params.containsKey("isFlag") && params.get("isFlag").equals("1") && workflowResultDto.getNextNodeKey().equals(FinancingAuditEnum.待整改.getCode())) {

            LambdaQueryWrapper<FinancingRectificationOrder> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(FinancingRectificationOrder::getPeasantHouseholdId, financingInfo.getPeasantHouseholdId());
            queryWrapper.orderByDesc(BaseEntity::getRecDate);
            queryWrapper.last("limit 1");
            FinancingRectificationOrder oldData = financingRectificationOrderService.getBaseMapper().selectOne(queryWrapper);

            FinancingRectificationOrder financingRectificationOrder = new FinancingRectificationOrder();
            //若存在历史整改单 将历史整改单数据同步至新整改单 便于修改
            if (ObjectUtils.isNotEmpty(oldData)) {
                BeanUtils.copyProperties(oldData, financingRectificationOrder);
                financingRectificationOrder.setSequenceNbr(null);
                financingRectificationOrder.setCompleteDate(null);
                financingRectificationOrder.setRectificationPhoto(null);
            }
            financingRectificationOrder.setRectificationOrderCode(String.valueOf(new Date().getTime()));
            financingRectificationOrder.setRectificationStatus("待整改");
            financingRectificationOrder.setProblemDescription(params.getOrDefault("problemDescription", "").toString());
            financingRectificationOrder.setPeasantHouseholdName(params.getOrDefault("peasantHouseholdName", "").toString());
            financingRectificationOrder.setRectificationDescription(params.getOrDefault("rectificationDescription", "").toString());
            financingRectificationOrder.setPeasantHouseholdId(financingInfo.getPeasantHouseholdId());
            financingRectificationOrder.setResponsibleUserName(params.getOrDefault("responsibleUserName", "").toString());
            financingRectificationOrder.setResponsibleUserPhone(params.getOrDefault("responsibleUserPhone", "").toString());
            financingRectificationOrderService.save(financingRectificationOrder);
        }


    }

    public List<Map<String, Object>> selectOrgList() {
        return this.getBaseMapper().selectOrgList();

    }
}