package com.chinaweal.aiccs.aiccs.abnormal.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.chinaweal.aiccs.aiccs.abnormal.entity.TSAbnList;
import com.chinaweal.aiccs.aiccs.abnormal.entity.TSAttachment;
import com.chinaweal.aiccs.aiccs.abnormal.entity.TSBizSpeList;
import com.chinaweal.aiccs.aiccs.abnormal.entity.TSWrit;
import com.chinaweal.aiccs.aiccs.abnormal.service.TSAbnListService;
import com.chinaweal.aiccs.aiccs.abnormal.service.TSAttachmentService;
import com.chinaweal.aiccs.aiccs.abnormal.service.TSBizSpeListService;
import com.chinaweal.aiccs.aiccs.abnormal.service.TSWritService;
import com.chinaweal.aiccs.aiccs.auditing.entity.TSOpinion;
import com.chinaweal.aiccs.aiccs.business.entity.BizCorrections;
import com.chinaweal.aiccs.aiccs.business.entity.TSTaskList;
import com.chinaweal.aiccs.aiccs.business.entity.TSTwfProcessNode;
import com.chinaweal.aiccs.aiccs.business.entity.dto.CorrectionsProcessDto;
import com.chinaweal.aiccs.aiccs.business.service.BizCorrectionsService;
import com.chinaweal.aiccs.aiccs.business.service.TSTaskListService;
import com.chinaweal.aiccs.aiccs.business.service.TSTwfProcessNodeService;
import com.chinaweal.aiccs.aiccs.business.service.WorkFlowService;
import com.chinaweal.aiccs.aiccs.system.entity.TRBaseCode;
import com.chinaweal.aiccs.aiccs.system.service.TRBaseCodeService;
import com.chinaweal.aiccs.common.base.controller.BaseController;
import com.chinaweal.aiccs.common.constant.BaseDataConstant;
import com.chinaweal.aiccs.common.constant.Constant;
import com.chinaweal.aiccs.common.util.ConstantsUtil;
import com.chinaweal.aiccs.common.util.StringUtils;
import com.chinaweal.aiccs.org.entity.TUsers;
import com.chinaweal.aiccs.org.service.AicorgService;
import com.chinaweal.aiccs.org.service.TUsersService;
import com.chinaweal.aicorg.model.AICUser;
import com.chinaweal.youfool.framework.springboot.exception.custom.BusinessException;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.page.PageRequestDto;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.chinaweal.youfool.framework.springboot.rest.ResultCode;
import com.chinaweal.youfool.framework.springboot.util.AssertUtils;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 列异勘误业务Controller
 *
 * @author <a href="https://blog.lroyia.top">lroyia</a>
 * @since 2021/4/25 16:11
 **/
@RestController
@RequestMapping("/corrections/abnormal")
public class AbnormalCorrectionsController extends BaseController {

    @Autowired
    private TSAbnListService abnListService;
    @Autowired
    private TRBaseCodeService baseCodeService;
    @Autowired
    private BizCorrectionsService bizCorrectionsService;
    @Autowired
    private TSTaskListService taskListService;
    @Autowired
    private TSTwfProcessNodeService twfProcessNodeService;
    @Autowired
    private AicorgService aicorgService;
    @Autowired
    private TSBizSpeListService tsBizSpeListService;
    @Autowired
    private WorkFlowService workFlowService;
    @Autowired
    private TUsersService usersService;
    @Autowired
    private TSAttachmentService attachmentService;
    @Autowired
    private TSWritService writService;

    /**
     * 列异记录分页
     *
     * @param pageRequestDto 分页参数
     * @param request        请求
     * @return 分页结果
     * @author lroyia
     * @since 2021年4月25日 16:16:21
     */
    @ApiOperation("列异记录分页")
    @PostMapping("listPage")
    public RestResult<?> abnormalListPage(@ApiParam("分页参数") @RequestBody PageRequestDto pageRequestDto, HttpServletRequest request) {
        AssertUtils.isNotNull(pageRequestDto);
        AICUser user = getLoginUser(request);
        pageRequestDto.checkDefault(1, 10, "lauptime");

        Map<String, TRBaseCode> codeMap = baseCodeService.getBaseCodeMapFormCache("CD71");
        String orgCode = aicorgService.getRegionCodeByUser(user);
//        String orgCode = usersService.findOrgCode(user.getPrimaryKey());
        String[] decOrgList = ConstantsUtil.getDecOrgList(orgCode);
        return RestResult.ok(abnListService.defaultPaging(pageRequestDto, w -> {
            LambdaQueryWrapper<TSAbnList> wrapper = w.lambda();
            wrapper.in(decOrgList.length>0, TSAbnList::getDecorg,decOrgList);

            Map<String, Object> customParamMap = pageRequestDto.getCustomParamMap();
            if (MapUtils.isEmpty(customParamMap)) return;
            String entType = StringUtils.tranObject(customParamMap.get("entType"));
            String entname = StringUtils.tranObject(customParamMap.get("entname"));
            String searchCode = StringUtils.tranObject(customParamMap.get("searchCode"));

            wrapper.like(StringUtils.isNotEmpty(entname),TSAbnList::getEntname,entname);
            if(StringUtils.isNotEmpty(searchCode)){
                if(StringUtils.isUscc(searchCode)){
                    wrapper.eq(TSAbnList::getUniscid,searchCode);
                }else {
                    wrapper.eq(TSAbnList::getRegno,searchCode);
                }
            }
            if (StringUtils.isNotBlank(entType)) {
                switch (entType) {
                    case "0":
                        wrapper.notIn(TSAbnList::getEnttype, "9000", "9100", "9200", "9910", "99100", "99101", "99102", "99103", "9999");
                        break;
                    case "1":
                        wrapper.in(TSAbnList::getEnttype, "9910", "99100", "99101", "99102", "99103", "9999");
                        break;
                    case "2":
                        wrapper.in(TSAbnList::getEnttype, "9100", "9200");
                        break;
                    default:
                }
            }
        }, each -> {
            if(StringUtils.isNotBlank(each.getSpereasons())){
                each.setSpecauseCn(each.getSpereasons());
            }else{
                TRBaseCode code = codeMap.get(each.getSpecause());
                if (code != null) {
                    each.setSpecauseCn(code.getName());
                }
            }
        }));
    }

    /**
     * 获取业务详情
     *
     * @param bizseq 业务号
     * @return 获取结果
     * @author lroyia
     * @since 2021年4月25日 19:51:07
     */
    @ApiOperation("获取业务详情")
    @GetMapping("detail")
    public RestResult<?> getCorrectionsDetail(@ApiParam("业务号") String bizseq) {
        AssertUtils.isNotBlank(bizseq);
        // 查询列异勘误业务信息
        BizCorrections detail = bizCorrectionsService.getOne(new LambdaQueryWrapper<BizCorrections>().eq(BizCorrections::getBizseq, bizseq));
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("detail", detail);

        // 查询待办信息
        TSTaskList taskList = taskListService.getOne(new LambdaQueryWrapper<TSTaskList>().eq(TSTaskList::getBizseqid, bizseq));
        resultMap.put("taskList", taskList);

        // 查询流程节点信息
        List<TSTwfProcessNode> node = twfProcessNodeService.list(new LambdaQueryWrapper<TSTwfProcessNode>()
                .eq(TSTwfProcessNode::getProcessid, taskList.getWorkflowid()).orderByDesc(TSTwfProcessNode::getLauptime));
        resultMap.put("nodes", node);
        return RestResult.ok(resultMap);
    }

    /**
     * 列异勘误流程待办创建
     *
     * @param listId  异议列表id
     * @param request 请求
     * @return 创建结果
     * @author lroyia
     * @since 2021年4月25日 19:16:51
     */
    @ApiOperation("列异勘误流程待办创建")
    @PostMapping("createTask")
    @Transactional(rollbackFor = Exception.class)
    public RestResult<?> createTask(@ApiParam("异议列表id") String listId, HttpServletRequest request) {
        // 参数校验
        AssertUtils.isNotBlank(listId);
        TSAbnList abnList = abnListService.getById(listId);
        if (abnList == null) return RestResult.error(ResultCode.PARAM_IS_INVALID);

        TSBizSpeList tsBizSpeList = tsBizSpeListService.getById(listId);
        if (tsBizSpeList == null) return RestResult.error(ResultCode.PARAM_IS_INVALID);

        // 在办业务验证
        int existsBus = bizCorrectionsService.count(new LambdaQueryWrapper<BizCorrections>()
                .eq(BizCorrections::getBusId, abnList.getAbnlistid())
                .eq(BizCorrections::getState, Constant.TRUE_1_STR));
        if (existsBus > 0) {
            return RestResult.error(ResultCode.DATA_ALREADY_EXISTED,"该信息已发起过勘误流程");
        }

        AICUser curUser = getLoginUser(request);

        String bizseq = UUID.randomUUID().toString();

        BizCorrections bizCorrections = new BizCorrections()
                .setBizseq(bizseq)
                .setBustype(Constant.FALSE_0_STR)
                .setBusId(listId)
                .setPFactDesc(abnList.getSpereasons())
//                .setFactDesc(abnList.getSpereasons())
                .setEntname(abnList.getEntname())
                .setPReason(abnList.getSpecause())
//                .setReason(abnList.getSpecause())
                .setPRemark(tsBizSpeList.getRemark())
                .setPripid(abnList.getPripid())
                .setRegno(abnList.getRegno())
                .setUniscid(abnList.getUniscid())
                .setState(Constant.TRUE_1_STR);
        // 文书内容 先从业务表获取
        if(StringUtils.isNotEmpty(tsBizSpeList.getDecisionContent())){
            bizCorrections.setPDecisionContent(tsBizSpeList.getDecisionContent());
        }
        // TODO 决定书内容获取
        // 封装主体类型 ‘company’企业  ‘individual’个体户 ‘farmer’农专社
        if("9910".equals(abnList.getEnttype())){
            bizCorrections.setEntType("individual");
        }else if("9200".equals(abnList.getEnttype()) || "9100".equals(abnList.getEnttype())){
            bizCorrections.setEntType("farmer");
        }else {
            bizCorrections.setEntType("company");
        }
        /*else {// 业务表没有则找文书表
            if(StringUtils.isNotEmpty(abnList.getIntowritid())){
                TSWrit tsWrit = writService.getById(abnList.getIntowritid());
                bizCorrections.setPDecisionContent(tsWrit.getContent());
            }else {

            }
        }*/
        boolean save = bizCorrectionsService.save(bizCorrections);
        if(!save){
            throw new BusinessException("发起勘误流程失败");
        }
        // 拷贝原业务附件，作为勘误流程的“原材料”，后续上传的作为新材料
        boolean update = bizCorrectionsService.updateBizFile(tsBizSpeList.getCorrectBizseq(), tsBizSpeList.getBizseq(), bizseq,"abn");
        if(!update) {
            throw new BusinessException("发起勘误流程失败");
        }


        // 创建勘误
        TSTaskList taskListModel = new TSTaskList();
        taskListModel.setBizseqid(bizseq);
        taskListModel.setBustype(BaseDataConstant.CORRECTIONS_ABNORMAL_BIZ);// 勘误流程
        taskListModel.setBusname(abnList.getEntname() + "列异勘误");
        bizCorrectionsService.createTask(curUser, taskListModel, bizCorrections);
        if (StringUtils.isNotBlank(taskListModel.getTasklistid())) {
            Map<String, Object> result = new HashMap<>();
            result.put("tasklistid", taskListModel.getTasklistid());
            result.put("bizseq", bizseq);
            result.put("workflowId", taskListModel.getWorkflowid());
            return RestResult.ok(result);
        }
        throw new BusinessException("发起勘误流程失败");
    }

    /**
     * 进入下一个勘误流程
     *
     * @param processDto 流转信息
     * @return 处理结果
     * @author lroyia
     * @since 2021年4月26日 14:22:42
     */
    @PostMapping("nextProcess")
    @ApiOperation("进入下一个勘误流程")
    @Transactional(rollbackFor = Exception.class)
    public RestResult<?> nextProcess(@ApiParam("流转信息") CorrectionsProcessDto processDto, HttpServletRequest request) {
        // 参数校验
        AssertUtils.isNotNull(processDto);
        AssertUtils.isNotBlank(processDto.getNextNodeId(), processDto.getBizseq(),
                processDto.getNextUserIds(), processDto.getNextUserNames(),
                processDto.getOpiniontype(), processDto.getCurNodeId(),
                processDto.getOpinioncontent(), processDto.getTasklistid(), processDto.getWorkflowId());

        AICUser curUser = getLoginUser(request);

        // 读取必须参数
        String link = String.format("%s_%s", processDto.getCurNodeId(), processDto.getNextNodeId());
        String[] ids = null;
        String[] names = null;
        if("approvelist_handleFeedback".equals(link) || "handleFeedback_feedbackEnter".equals(link)){
            String userId = workFlowService.findLastTwfprocessnodeByProcessidAndNodename(processDto.getWorkflowId(), processDto.getCurNodeId(), processDto.getNextNodeId());
            if (StringUtils.isEmpty(userId)){
                return RestResult.error(ResultCode.DATA_NONE);
            }

            TUsers userInfo = usersService.selectTusersById(userId);
            ids = new String[]{userInfo.getUserid()};
            names = new String[]{userInfo.getRealname()};
        }else {
            ids = StringUtils.split(processDto.getNextUserIds(), ",");
            names = StringUtils.split(processDto.getNextUserNames(), ",");
        }
        TSTaskList taskListModel = taskListService.selectByTasklistID(processDto.getTasklistid());
        TSOpinion opinionModel = new TSOpinion()
                .setHandler(curUser.getName())
                .setHandlerid(curUser.getPrimaryKey())
                .setWorkflowid(taskListModel.getWorkflowid())
                .setOpiniontype(processDto.getOpiniontype())
                .setHandledate(LocalDateTime.now())
                .setOpinioncontent(processDto.getOpinioncontent());
        List<BizCorrections> corrections = bizCorrectionsService.list(new LambdaQueryWrapper<BizCorrections>().eq(BizCorrections::getBizseq, taskListModel.getBizseqid()));
        if (StringUtils.isNotBlank(processDto.getReason()) && StringUtils.isNotBlank(processDto.getFactDesc())) {
            for (BizCorrections each : corrections) {
                each.setFactDesc(processDto.getFactDesc());
                each.setReason(processDto.getReason());
                each.setDecisionContent(processDto.getDecisionContent());
                if(!processDto.getRemark().equals("null")) {
                    each.setRemark(processDto.getRemark());
                }
            }
        }
        // 处理流程
        bizCorrectionsService.nextProcess(curUser, taskListModel, opinionModel, processDto.getNextNodeId(), ids, names, corrections.toArray(new BizCorrections[0]));
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("bizseq", taskListModel.getBizseqid());
        resultMap.put("workflowid", taskListModel.getWorkflowid());
        resultMap.put("nextNodeID", processDto.getNextNodeId());
        resultMap.put("tasklistid", processDto.getTasklistid());

        return RestResult.ok(resultMap);
    }

    /**
     * 加载原列异业务附件清单
     * @param bizseq        勘误业务号
     * @return
     */
    @PostMapping("loadOldFileList")
    public RestResult<?> loadOldFileList(String bizseq){
        AssertUtils.isNotEmpty(bizseq);
        List<TSAttachment> attachments = new ArrayList<>();
        TSAttachment tsAttachmentModel = new TSAttachment();
        tsAttachmentModel.setBizseq(bizseq);
        tsAttachmentModel.setAttachtype("0"); // 标记为“0” 是勘误流程的原材料
        attachments = attachmentService.selectwritByPage(tsAttachmentModel);
/*
        TSBizSpeList bizSpeList = tsBizSpeListService.getById(busId);
        if(StringUtils.isNotEmpty(bizSpeList.getCorrectBizseq())){ // 如果有勘误过。加载最新勘误业务的附件
            TSAttachment tsAttachment = new TSAttachment();
            tsAttachment.setBizseq(bizSpeList.getCorrectBizseq());
            tsAttachment.setAttachtype("1");
            attachments = attachmentService.selectwritByPage(tsAttachment);
        }else {
            String bizseq = bizSpeList.getBizseq();
            attachments = attachmentService.getAbnIncFileList(bizseq);
        }
*/
        for (TSAttachment tsAttachment : attachments) {
            if(StringUtils.isBlank(tsAttachment.getTemppath())){
                tsAttachment.setTemppath(tsAttachment.getFileurl());
            }
        }
        return RestResult.ok(attachments);
    }
}
