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.cloud.commons.toolkit.DateUtils;
import com.patzn.lims.core.oss.OssClient;
import com.patzn.lims.res.service.ILmsPropertyService;
import com.patzn.lims.frame.entity.LmsFrameFile;
import com.patzn.lims.frame.entity.LmsFrameInnerCheckPlan;
import com.patzn.lims.frame.entity.LmsFrameInnerCheckPlanRecord;
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.LmsFrameInnerCheckPlanMapper;
import com.patzn.lims.frame.service.*;
import com.patzn.lims.frame.vo.LmsFrameInnerCheckPlanVO;
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.BeanUtils;
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 LmsFrameInnerCheckPlanServiceImpl extends BaseServiceImpl<LmsFrameInnerCheckPlanMapper, LmsFrameInnerCheckPlan> implements ILmsFrameInnerCheckPlanService {

    @Autowired
    private ILmsFrameFileService lmsFrameFileService;
    @Autowired
    private ILmsFrameLogService lmsFrameLogService;
    @Autowired
    private ILmsFrameInnerCheckManageService lmsFrameInnerCheckManageService;
    @Autowired
    private ILmsFrameInnerCheckReportService lmsFrameInnerCheckReportService;
    @Autowired
    private ILmsFrameInnerCheckPlanRecordService lmsFrameInnerCheckPlanRecordService;
    @Autowired
     private IFlowProcessService flowProcessClient;
    @Autowired
    private ILmsPropertyService lmsPropertyService;
    @Autowired
    private OssClient ossClient;


    @Override
    public Page<LmsFrameInnerCheckPlan> page(Page<LmsFrameInnerCheckPlan> page, LmsFrameInnerCheckPlanVO lmsFrameInnerCheckPlan) {
        LmsFrameInnerCheckPlan innerCheckPlan =  lmsFrameInnerCheckPlan.convert(LmsFrameInnerCheckPlan.class);
        innerCheckPlan.setTempStatus(1);
         QueryWrapper wrapper = Wrappers.query(innerCheckPlan);
        if (StringUtils.isNotBlank(lmsFrameInnerCheckPlan.getCheckPlanPurpose())){
            wrapper.like("check_plan_purpose", lmsFrameInnerCheckPlan.getCheckPlanPurpose());
            lmsFrameInnerCheckPlan.setCheckPlanPurpose(null);
        }
        if (StringUtils.isNotBlank(lmsFrameInnerCheckPlan.getCheckPlanBasis())){
            wrapper.like("check_plan_basis", lmsFrameInnerCheckPlan.getCheckPlanBasis());
            lmsFrameInnerCheckPlan.setCheckPlanBasis(null);
        }
        if (lmsFrameInnerCheckPlan.getStartDate() != null) {

            wrapper.ge("to_char(check_plan_time, 'yyyy-MM-dd') ", DateUtils.toDate(lmsFrameInnerCheckPlan.getStartDate()));
            lmsFrameInnerCheckPlan.setEndDate(null);
        }
        if (lmsFrameInnerCheckPlan.getEndDate() != null) {
            wrapper.le("to_char(check_plan_time, 'yyyy-MM-dd')", DateUtils.toDate(lmsFrameInnerCheckPlan.getEndDate()));
            lmsFrameInnerCheckPlan.setStartDate(null);
        }
        wrapper.orderBy(true,true,"ctime");
        return page(page, wrapper);
    }


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

    @Override
    public LmsFrameInnerCheckPlanVO getVOById(Long id) {
        LmsFrameInnerCheckPlanVO lmsFrameInnerCheckPlanVO = new LmsFrameInnerCheckPlanVO();
        LmsFrameInnerCheckPlan lmsFrameInnerCheckPlan = getById(id);
        if (null != lmsFrameInnerCheckPlan) {
            BeanUtils.copyProperties(lmsFrameInnerCheckPlan, lmsFrameInnerCheckPlanVO);
            //获取附件
            LmsFrameFile lmsFrameFile = new LmsFrameFile();
            lmsFrameFile.setRelId(lmsFrameInnerCheckPlan.getId());
            List<LmsFrameFile> lmsFrameFileList = lmsFrameFileService.list(lmsFrameFile);
            lmsFrameFileList.forEach(e -> {
                e.setFilePath(ossClient.getUrl(e.getFilePath()).toString());
            });
            lmsFrameInnerCheckPlanVO.setLmsFrameFileList(lmsFrameFileList);
        }

        return lmsFrameInnerCheckPlanVO;
    }

    @Override
    public LmsFrameInnerCheckPlanVO getTempVO() {
        LmsFrameInnerCheckPlanVO lmsFrameInnerCheckPlanVO = new LmsFrameInnerCheckPlanVO();
        LmsFrameInnerCheckPlan entity = new LmsFrameInnerCheckPlan();
        entity.setUserId(LoginHelper.getAccount().getUserId());
        entity.setTempStatus(0);
        LmsFrameInnerCheckPlan lmsFrameInnerCheckPlan = baseMapper.selectOne(Wrappers.<LmsFrameInnerCheckPlan>query().eq("temp_status",0).eq("user_id",LoginHelper.getAccount().getUserId()).last("LIMIT 1"));
        if (null != lmsFrameInnerCheckPlan) {
            BeanUtils.copyProperties(lmsFrameInnerCheckPlan, lmsFrameInnerCheckPlanVO);
            //获取附件
            LmsFrameFile lmsFrameFile = new LmsFrameFile();
            lmsFrameFile.setRelId(lmsFrameInnerCheckPlan.getId());
            List<LmsFrameFile> lmsFrameFileList = lmsFrameFileService.list(lmsFrameFile);
            lmsFrameFileList.forEach(e->{
                e.setFilePath(ossClient.getUrl(e.getFilePath()).toString());
            });
            lmsFrameInnerCheckPlanVO.setLmsFrameFileList(lmsFrameFileList);
//            //改成删除附件
//            lmsFrameFileService.deleteByInnerCheckPlan(lmsFrameInnerCheckPlan.getId());

        } else {
            LmsFrameInnerCheckPlan plan = new LmsFrameInnerCheckPlan();
            plan.setTempStatus(0);
            plan.setUserId(LoginHelper.getAccount().getUserId());
            plan.setStatus((Integer) LmsInnerStatusEnum.DRAFT.getValue());
            save(plan);
            BeanUtils.copyProperties(plan, lmsFrameInnerCheckPlanVO);
        }

        return lmsFrameInnerCheckPlanVO;
    }

    @Override
    @Transactional
    public Boolean edit(LmsFrameInnerCheckPlan lmsFrameInnerCheckPlan) {
        if (null != lmsFrameInnerCheckPlan.getId()) {//提交数据操作日志保存
            LmsFrameInnerCheckPlan entity = getById(lmsFrameInnerCheckPlan.getId());
            String remark = lmsPropertyService.getObjectCompareDifferent(lmsFrameInnerCheckPlan, entity, "内审计划信息对比", "内容修改：");
            if (StringUtils.isNotBlank(remark)) {
                LmsFrameInnerCheckPlanRecord record = new LmsFrameInnerCheckPlanRecord();
                record.setOrigin(LmsInnerStatusEnum.valueOf(entity.getStatus()).getDisplay());
                record.setTarget(LmsInnerStatusEnum.valueOf(entity.getStatus()).getDisplay());
                record.setType(2);
                record.setRemark(remark);
                record.setInnerPlanId(entity.getId());
                record.setOperator(LoginHelper.getAccount().getUserName());
                lmsFrameInnerCheckPlanRecordService.save(record);
            }
            if (LmsInnerStatusEnum.EXAMINE_PASS.getValue().equals(entity.getStatus().toString())) {
                LmsFrameLog log = new LmsFrameLog();
                log.setUserId(LoginHelper.getAccount().getUserId());
                log.setUserName(LoginHelper.getAccount().getUserName());
                log.setTableName("lms_frame_inner_check_plan");
                log.setOrginParams(entity.toString());
                log.setParams(lmsFrameInnerCheckPlan.toString());
                log.setCreateTime(new Date());
                lmsFrameLogService.save(log);
            }
        }
        return updateById(lmsFrameInnerCheckPlan);
    }

    @Override
    public Boolean add(LmsFrameInnerCheckPlan lmsFrameInnerCheckPlan) {
        lmsFrameInnerCheckPlan.setApplyId(LoginHelper.getAccount().getUserId());
        lmsFrameInnerCheckPlan.setApplyName(LoginHelper.getAccount().getUserName());
        lmsFrameInnerCheckPlan.setApplyTime(new Date());

        LmsFrameInnerCheckPlan entity = new LmsFrameInnerCheckPlan();
        entity.setUserId(LoginHelper.getAccount().getUserId());
        entity.setTempStatus(0);
        LmsFrameInnerCheckPlan temp = baseMapper.selectOne(Wrappers.<LmsFrameInnerCheckPlan>query().eq("temp_status",0).eq("user_id",LoginHelper.getAccount().getUserId()).last("LIMIT 1"));
        lmsFrameInnerCheckPlan.setTempStatus(1);
        if (null != temp) {
            lmsFrameInnerCheckPlan.setId(temp.getId());
            updateById(lmsFrameInnerCheckPlan);
        } else {
            lmsFrameInnerCheckPlan.setUserId(LoginHelper.getAccount().getUserId());

            save(lmsFrameInnerCheckPlan);
        }

        return true;
    }

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

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

    @Override
    public LmsFrameFile uploadFile(MultipartFile file, LmsFrameInnerCheckPlan lmsFrameInnerCheckPlan) {
        Long companyId = LoginHelper.getAccount().getCompanyId();
        String folderPath = "frame/InnerCheckPlan/" + companyId + "/";
        return lmsFrameFileService.saveAndUpload(file, "lims", folderPath, lmsFrameInnerCheckPlan.getId(), FrameFileTypeEnum.INNER_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) {
        Long[] ids = new Long[]{id};
        return lmsFrameFileService.deleteBatch(ids);
    }

    @Override
    public Boolean submit(List<Long> ids) {
        List<LmsFrameInnerCheckPlan> entityList = Lists.newArrayList();
        for (Long id : ids) {
            LmsFrameInnerCheckPlan entity = new LmsFrameInnerCheckPlan();
            entity.setAuditId(LoginHelper.getAccount().getUserId());
            entity.setAuditName(LoginHelper.getAccount().getUserName());
            entity.setAuditTime(new Date());
            entity.setId(id);
            entity.setStatus((Integer) LmsInnerStatusEnum.EXAMINE.getValue());
            entityList.add(entity);
        }

        return updateBatchById(entityList);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<FlowProcess> submitInnerCheckFlow(Long[] ids) {
        if (ArrayUtils.isEmpty(ids)) {
            return null;
        }
        Account account = LoginHelper.getAccount();
        List<LmsFrameInnerCheckPlan> innerCheckPlanList = super.list(Wrappers.<LmsFrameInnerCheckPlan>query().in("id", ids));
        List<FlowInfo> flowInfoList = new ArrayList<>();

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

        List<LmsFrameInnerCheckPlan> saveInnerCheckPlanList = innerCheckPlanList.
                stream().filter(checkPlan -> null != checkPlan).map(checkPlan -> {
            flowInfoList.add(
                    FlowInfo.convertFlowInfo(FlowType.INNER_PLAN_CHECK,
                            account, checkPlan.getId(), checkPlan.getCheckPlanContentText())
            );
            // 设置状态为待审批
            LmsFrameInnerCheckPlan plan = new LmsFrameInnerCheckPlan();
            plan.setId(checkPlan.getId());
            plan.setApplyId(account.getUserId());
            plan.setApplyName(account.getUserName());
            plan.setApplyTime(new Date());
            plan.setStatus((Integer) LmsInnerStatusEnum.EXAMINE.getValue());
            plan.setProgress((Integer)LmsInnerStatusEnum.EXAMINE.getValue());

            LmsFrameInnerCheckPlanRecord record = new LmsFrameInnerCheckPlanRecord();
            record.setInnerPlanId(plan.getId());
            record.setOperator(account.getUserName());
            record.setLiable(account.getUserName());
            record.setRemark("内审计划提交审批");
            record.setType(0);
            record.setTarget(LmsInnerStatusEnum.EXAMINE.getDisplay());
            record.setOrigin(LmsInnerStatusEnum.DRAFT.getDisplay());
            recordList.add(record);
            return plan;

        }).collect(Collectors.toList());
        updateBatchById(saveInnerCheckPlanList);
        if (CollectionUtils.isNotEmpty(recordList)) {
            lmsFrameInnerCheckPlanRecordService.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
        LmsFrameInnerCheckPlan plan = new LmsFrameInnerCheckPlan();
        plan.setAuditId(LoginHelper.getAccount().getUserId());
        plan.setAuditName(LoginHelper.getAccount().getUserName());
        plan.setAuditTime(new Date());
        plan.setApprovalOpinion(reason);

        LmsFrameInnerCheckPlanRecord record = new LmsFrameInnerCheckPlanRecord();
        record.setOperator(account.getUserName());
        record.setLiable(account.getUserName());
        record.setOrigin(LmsInnerStatusEnum.EXAMINE.getDisplay());
        if ("pass".equals(status)) {
            //内审计划审批通过
            map.put("innerCheckPass", true);
            plan.setStatus((Integer)LmsInnerStatusEnum.EXAMINE_PASS.getValue());
            plan.setProgress((Integer)LmsInnerStatusEnum.EXAMINE_PASS.getValue());

            record.setTarget(LmsInnerStatusEnum.EXAMINE_PASS.getDisplay());
            record.setRemark("内审计划审批通过" + reason);
            record.setType(0);

        } else if ("back".equals(status)) {
            //内审计划审批驳回
            map.put("innerCheckPass", false);
            plan.setStatus((Integer)LmsInnerStatusEnum.DRAFT.getValue());
            plan.setProgress((Integer)LmsInnerStatusEnum.EXAMINE_BACK.getValue());
            record.setTarget(LmsInnerStatusEnum.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.setInnerPlanId(flowInfo.getId());
        lmsFrameInnerCheckPlanRecordService.save(record);
        return true;
    }
}
