package com.patzn.lims.frame.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.patzn.cloud.commons.api.RestAssert;
import com.patzn.lims.core.web.Account;
import com.patzn.lims.core.web.LoginHelper;
import com.patzn.lims.core.web.BaseServiceImpl;
import com.patzn.lims.core.oss.OssClient;
import com.patzn.lims.frame.enums.ManageCheckEnum;
import com.patzn.lims.res.service.ILmsPropertyService;
import com.patzn.lims.frame.entity.LmsFrameCheckPlan;
import com.patzn.lims.frame.entity.LmsFrameCheckPlanRecord;
import com.patzn.lims.frame.entity.LmsFrameFile;
import com.patzn.lims.frame.entity.LmsFrameLog;
import com.patzn.lims.frame.enums.FrameFileTypeEnum;
import com.patzn.lims.frame.enums.LmsInnerStatusEnum;
import com.patzn.lims.frame.mapper.LmsFrameCheckPlanMapper;
import com.patzn.lims.frame.service.*;
import com.patzn.lims.frame.vo.LmsFrameCheckPlanVO;
import com.patzn.lims.workflow.FlowInfo;
import com.patzn.lims.workflow.FlowProcess;
import com.patzn.lims.workflow.FlowType;
import com.patzn.lims.workflow.FlowVariables;
import com.patzn.lims.workflow.service.IFlowProcessService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 管理评审计划 服务实现类
 * </p>
 *
 * @author patzn123
 * @since 2018-01-09
 */
@Service
public class LmsFrameCheckPlanServiceImpl extends BaseServiceImpl<LmsFrameCheckPlanMapper, LmsFrameCheckPlan> implements ILmsFrameCheckPlanService {

    @Autowired
    private ILmsFrameFileService lmsFrameFileService;
    @Autowired
    private ILmsFrameLogService lmsFrameLogService;
    @Autowired
    private ILmsFrameCheckManageService lmsFrameCheckManageService;
    @Autowired
    private ILmsFrameCheckReportService lmsFrameCheckReportService;
    @Autowired
    private ILmsFrameCheckPlanRecordService lmsFrameCheckPlanRecordService;
    @Autowired
    private IFlowProcessService flowProcessClient;
    @Autowired
    private ILmsPropertyService lmsPropertyService;
    @Autowired
    private OssClient ossClient;

    @Override
    public Page<LmsFrameCheckPlan> page(Page<LmsFrameCheckPlan> page, LmsFrameCheckPlan lmsFrameCheckPlan) {
        lmsFrameCheckPlan.setTempStatus(1);
         QueryWrapper wrapper = Wrappers.<LmsFrameCheckPlan>query(lmsFrameCheckPlan);
         if (StringUtils.isNotBlank(lmsFrameCheckPlan.getApplyName())){
             wrapper.like("apply_name", lmsFrameCheckPlan.getApplyName());
             lmsFrameCheckPlan.setApplyName(null);
         }


        wrapper.orderBy(true,false,"status,check_plan_time");
        return page(page, wrapper);
    }


    @Override
    public List<LmsFrameCheckPlan> list(LmsFrameCheckPlan lmsFrameCheckPlan) {
        lmsFrameCheckPlan.setTempStatus(1);
        return list(Wrappers.<LmsFrameCheckPlan>query(lmsFrameCheckPlan));
    }


    @Override
    public LmsFrameCheckPlanVO getVOById(Long id) {
        LmsFrameCheckPlan lmsFrameCheckPlan = getById(id);
        if (null == lmsFrameCheckPlan) {
            return null;
        }
        LmsFrameCheckPlanVO vo = lmsFrameCheckPlan.convert(LmsFrameCheckPlanVO.class);
        //获取附件
        LmsFrameFile lmsFrameFile = new LmsFrameFile();
        lmsFrameFile.setRelId(lmsFrameCheckPlan.getId());
        List<LmsFrameFile> list=lmsFrameFileService.list(lmsFrameFile);
        list.forEach(e->{
            e.setFilePath(ossClient.getUrl(e.getFilePath()).toString());
        });
        vo.setLmsFrameFileList(list);
        return vo;
    }


    @Override
    public LmsFrameCheckPlanVO getTempVO() {
        Account account = LoginHelper.getAccount();
        LmsFrameCheckPlan entity = new LmsFrameCheckPlan();
        entity.setUserId(account.getUserId());
        entity.setTempStatus(0);

        LmsFrameCheckPlan frameCheckPlan = baseMapper.selectOne(Wrappers.<LmsFrameCheckPlan>query().eq("temp_status",0).eq("user_id",LoginHelper.getAccount().getUserId()).last("LIMIT 1"));
        if (null != frameCheckPlan) {
            LmsFrameCheckPlanVO vo = frameCheckPlan.convert(LmsFrameCheckPlanVO.class);
            //获取附件
            LmsFrameFile lmsFrameFile = new LmsFrameFile();
            lmsFrameFile.setRelId(frameCheckPlan.getId());
            List<LmsFrameFile> lmsFrameFileList = lmsFrameFileService.list(lmsFrameFile);
            lmsFrameFileList.forEach(e->{
                e.setFilePath(ossClient.getUrl(e.getFilePath()).toString());
            });
            vo.setLmsFrameFileList(lmsFrameFileList);
            return vo;
        }

        LmsFrameCheckPlan plan = new LmsFrameCheckPlan();
        plan.setTempStatus(0);
        plan.setUserId(account.getUserId());
        plan.setStatus((Integer) ManageCheckEnum.DRAFT.getValue());
        if (save(plan)) {
            LmsFrameCheckPlanVO vo = new LmsFrameCheckPlanVO();
            vo.setTempStatus(plan.getTempStatus());
            vo.setId(plan.getId());
            return vo;
        }
        return null;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean edit(LmsFrameCheckPlan lmsFrameCheckPlan) {
        if (null != lmsFrameCheckPlan.getId()) {
            //提交数据操作日志保存
            LmsFrameCheckPlan entity = getById(lmsFrameCheckPlan.getId());
            String remark = lmsPropertyService.getObjectCompareDifferent(lmsFrameCheckPlan, entity, "管理评审计划对比", "信息修改：");
            if (StringUtils.isNotBlank(remark)) {
                LmsFrameCheckPlanRecord record = new LmsFrameCheckPlanRecord();
                record.setOrigin(ManageCheckEnum.valueOf(entity.getStatus()).getDisplay());
                record.setTarget(ManageCheckEnum.valueOf(entity.getStatus()).getDisplay());
                record.setType(2);
                record.setRemark(remark);
                record.setManageCheckId(entity.getId());
                record.setOperator(LoginHelper.getAccount().getUserName());
                lmsFrameCheckPlanRecordService.save(record);
            }
            if ("1".equals(entity.getStatus().toString())) {
                LmsFrameLog log = new LmsFrameLog();
                log.setUserId(LoginHelper.getAccount().getUserId());
                log.setUserName(LoginHelper.getAccount().getUserName());
                log.setTableName("lms_frame_check_plan");
                log.setOrginParams(entity.toString());
                log.setParams(lmsFrameCheckPlan.toString());
                log.setCreateTime(new Date());
                lmsFrameLogService.save(log);
            }
        }
        return updateById(lmsFrameCheckPlan);
    }

    @Override
    public boolean add(LmsFrameCheckPlan lmsFrameCheckPlan) {
        Account account = LoginHelper.getAccount();
        lmsFrameCheckPlan.setApplyId(account.getUserId());
        lmsFrameCheckPlan.setApplyName(account.getUserName());
        lmsFrameCheckPlan.setApplyTime(new Date());

        LmsFrameCheckPlan entity = new LmsFrameCheckPlan();
        entity.setUserId(account.getUserId());
        entity.setTempStatus(0);
        LmsFrameCheckPlan temp = baseMapper.selectOne(Wrappers.query(entity));
        if (null != temp) {
            lmsFrameCheckPlan.setId(temp.getId());
            lmsFrameCheckPlan.setTempStatus(1);
            return updateById(lmsFrameCheckPlan);
        }

        lmsFrameCheckPlan.setUserId(LoginHelper.getAccount().getUserId());
        lmsFrameCheckPlan.setTempStatus(1);
        return save(lmsFrameCheckPlan);
    }


    @Override
    public boolean delete(Long[] ids) {
        if (lmsFrameCheckManageService.existByIds(ids)) {
            RestAssert.fail("请先删除该条数据下所有的评审内容数据！");
        }
        if (lmsFrameCheckReportService.existByIds(ids)) {
            RestAssert.fail("请先删除该条数据下所有的评审报表数据！");
        }

        lmsFrameFileService.deleteBatch(ids);
        return super.remove(Wrappers.<LmsFrameCheckPlan>query().in("id", ids));
    }


    @Override
    public LmsFrameFile uploadFile(MultipartFile file, LmsFrameCheckPlan lmsFrameCheckPlan) {
        Long companyId = LoginHelper.getAccount().getCompanyId();
        String folderPath = "frame/CheckPlan/" + companyId + "/";
        return lmsFrameFileService.saveAndUpload(file, "lims", folderPath, lmsFrameCheckPlan.getId(), FrameFileTypeEnum.CHECK_PLAN.getValue());

    }

    @Override
    public void downloadFile(Long id, HttpServletResponse response) {
        LmsFrameFile lmsFrameFile = lmsFrameFileService.getById(id);
        String fileUrl = lmsFrameFile.getFilePath();
        String orgFileName = lmsFrameFile.getOrginName().replaceAll("\\s*", "");
        lmsFrameFileService.downloadFile(response, "lims", fileUrl, orgFileName);
    }


    @Override
    public boolean deleteFile(Long id) {
        return lmsFrameFileService.deleteBatch(new Long[]{id});
    }


    @Override
    public boolean submit(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return false;
        }
        return updateBatchById(ids.stream().map(id -> {
            LmsFrameCheckPlan entity = new LmsFrameCheckPlan();
            entity.setAuditId(LoginHelper.getAccount().getUserId());
            entity.setAuditName(LoginHelper.getAccount().getUserName());
            entity.setAuditTime(new Date());
            entity.setId(id);
            entity.setStatus((Integer)ManageCheckEnum.EXAMINE_PASS.getValue());
            return entity;
        }).collect(Collectors.toList()));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<FlowProcess> submitCheckFlow(Long[] ids, Account account) {
        if (ArrayUtils.isEmpty(ids)) {
            return null;
        }

        List<LmsFrameCheckPlan> manageCheckList = super.list(Wrappers.<LmsFrameCheckPlan>query().in("id", ids));
        List<FlowInfo> flowInfoList = new ArrayList<>();

        List<LmsFrameCheckPlanRecord> recordList = Lists.newArrayList();

        List<LmsFrameCheckPlan> updateCheckPlanList = manageCheckList.
                stream().filter(checkPlan -> null != checkPlan).map(checkPlan -> {
            flowInfoList.add(
                    FlowInfo.convertFlowInfo(FlowType.MANAGE_CHECK,
                            account, checkPlan.getId(), checkPlan.getCheckPlanPurpose())
            );
            // 设置状态为待审批
            LmsFrameCheckPlan plan = new LmsFrameCheckPlan();
            plan.setId(checkPlan.getId());
            plan.setApplyId(account.getUserId());
            plan.setApplyName(account.getUserName());
            plan.setApplyTime(new Date());
            plan.setStatus((Integer)ManageCheckEnum.EXAMINE.getValue());
            plan.setProgress((Integer)ManageCheckEnum.EXAMINE.getValue());

            LmsFrameCheckPlanRecord record = new LmsFrameCheckPlanRecord();
            record.setManageCheckId(plan.getId());
            record.setOperator(account.getUserName());
            record.setLiable(account.getUserName());
            record.setRemark("管理评审计划提交审批");
            record.setType(0);
            record.setTarget(ManageCheckEnum.EXAMINE.getDisplay());
            record.setOrigin(ManageCheckEnum.DRAFT.getDisplay());
            recordList.add(record);
            return plan;

        }).collect(Collectors.toList());
        updateBatchById(updateCheckPlanList);
        if (CollectionUtils.isNotEmpty(recordList)) {
            lmsFrameCheckPlanRecordService.saveBatch(recordList);
        }
        return flowProcessClient.saveTask(flowInfoList,account);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean approveFlow(String taskId, String status, String reason) {
        FlowVariables flowVariables = new FlowVariables(taskId);
        FlowInfo flowInfo;
        Map<String, Object> map = new HashMap<>(2);
        Account account = LoginHelper.getAccount();
        RestAssert.fail(StringUtils.isBlank(status), "status不能为空");
        RestAssert.fail(!(status.equalsIgnoreCase("pass") || status.equalsIgnoreCase("back")), "通过状态为'pass'，驳回状态为'back'");
        //获取管理计划id
        LmsFrameCheckPlan plan = new LmsFrameCheckPlan();
        plan.setAuditId(LoginHelper.getAccount().getUserId());
        plan.setAuditName(LoginHelper.getAccount().getUserName());
        plan.setAuditTime(new Date());
        plan.setApprovalOpinion(reason);

        LmsFrameCheckPlanRecord record = new LmsFrameCheckPlanRecord();
        record.setOperator(account.getUserName());
        record.setLiable(account.getUserName());
        record.setOrigin(LmsInnerStatusEnum.EXAMINE.getDisplay());
        if ("pass".equals(status)) {
            //管理评审审批通过
            map.put("manageCheckPass", true);
            plan.setStatus((Integer)ManageCheckEnum.EXAMINE_PASS.getValue());
            plan.setProgress((Integer)ManageCheckEnum.EXAMINE_PASS.getValue());
            record.setTarget(ManageCheckEnum.EXAMINE_PASS.getDisplay());
            record.setRemark("管理评审通过" + reason);
            record.setType(0);

        } else if ("back".equals(status)) {
            //管理评审驳回
            map.put("manageCheckPass", false);
            plan.setStatus((Integer)ManageCheckEnum.DRAFT.getValue());
            plan.setProgress((Integer)ManageCheckEnum.EXAMINE_BACK.getValue());
            record.setTarget(ManageCheckEnum.EXAMINE_BACK.getDisplay());
            record.setRemark("管理评审驳回" + reason);
            record.setType(1);
        }
        map.put(FlowInfo.APPLY_ID, account.getUserId());
        flowVariables.setVariables(map);
        flowInfo = flowProcessClient.complete(flowVariables);
        RestAssert.fail(null == flowInfo, "流程审批错误");
        plan.setId(flowInfo.getId());
        updateById(plan);
        record.setManageCheckId(flowInfo.getId());
        lmsFrameCheckPlanRecordService.save(record);
        return true;
    }
}
