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

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.patzn.lims.common.StringHandleUtils;
import com.patzn.lims.core.api.PtAssert;
import com.patzn.lims.core.web.Account;
import com.patzn.lims.core.web.BaseServiceImpl;
import com.patzn.lims.core.oss.OssClient;
import com.patzn.lims.core.web.LoginHelper;
import com.patzn.lims.frame.entity.*;
import com.patzn.lims.frame.enums.PlanStatusEnum;
import com.patzn.lims.frame.mapper.LmsQcMainPlanMapper;
import com.patzn.lims.frame.service.*;
import com.patzn.lims.frame.vo.LmsQcMainPlanVO;
import com.patzn.lims.res.service.ILmsBaseDictService;
import com.patzn.lims.res.service.ILmsPropertyService;
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 patzn
 * @since 2018-07-09
 */
@Service
public class LmsQcMainPlanServiceImpl extends BaseServiceImpl<LmsQcMainPlanMapper, LmsQcMainPlan> implements ILmsQcMainPlanService {

    @Autowired
    private ILmsPropertyService lmsPropertyService;
    @Autowired
    private ILmsQcMainPlanRecordService lmsQcMainPlanRecordService;
    @Autowired
    private IFlowProcessService flowProcessClient;
    @Autowired
    private ILmsQcSubPlanService lmsQcSubPlanService;
//    @Autowired
//    private ILmsExportService lmsExportService;
    @Autowired
    private ILmsBaseDictService lmsBaseDictService;
    @Autowired
    private ILmsQcMainPlanAttachmentService lmsQcMainPlanAttachmentService;
    @Autowired
    private OssClient ossClient;

    @Override
    public Page<LmsQcMainPlan> page(Page<LmsQcMainPlan> page, LmsQcMainPlan lmsQcMainPlan) {
        QueryWrapper wrapper = Wrappers.query(lmsQcMainPlan);
        return page(page, wrapper);
    }


    @Override
    public List<LmsQcMainPlan> list(LmsQcMainPlan lmsQcMainPlan) {
        return list( Wrappers.query(lmsQcMainPlan));
    }

    @Override
    public Page<LmsQcMainPlan> pageMainPlan(Page<LmsQcMainPlan> page, LmsQcMainPlan lmsQcMainPlan, Date startDate, Date endDate) {
        return page.setRecords(baseMapper.selectPageMainPlan(page, lmsQcMainPlan, startDate, endDate));
    }

    @Override
    public boolean copy(LmsQcMainPlan lmsQcMainPlan, Account account) {
        lmsQcMainPlan.setId(IdWorker.getId());
        lmsQcMainPlan.setMakerId(account.getUserId());
        lmsQcMainPlan.setMaker(account.getUserName());
        lmsQcMainPlan.setMakeDate(new Date());
        lmsQcMainPlan.setStatus((Integer) PlanStatusEnum.DRAFT.getValue());
        lmsQcMainPlan.setProgress((Integer)PlanStatusEnum.DRAFT.getValue());
        return super.save(lmsQcMainPlan);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean removeByIds(Long[] ids) {
        try {
            PtAssert.fail(ArrayUtils.isEmpty(ids), "请选择计划");
            int num = super.count(Wrappers.<LmsQcMainPlan>query().in("id", ids).eq("status", PlanStatusEnum.DRAFT.getValue()));
            PtAssert.fail(num != ids.length, "只能删除草稿计划");
            super.remove(Wrappers.<LmsQcMainPlan>query().in("id", ids));
            lmsQcSubPlanService.remove(Wrappers.<LmsQcSubPlan>query().in("main_plan_id", ids));
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public boolean updatePlanById(LmsQcMainPlan lmsQcMainPlan) {
        PtAssert.fail(null == lmsQcMainPlan.getId(), "id不能为空");
        LmsQcMainPlan dbMainPlan = super.getById(lmsQcMainPlan.getId());
        String remark = lmsPropertyService.getCompareDifferent(lmsQcMainPlan, dbMainPlan, "内部质控计划对比", "内部质控计划计划修改内容：");
        if (StringUtils.isNotEmpty(remark)) {
            lmsQcMainPlanRecordService.saveQcMainPlanRecordByIds(dbMainPlan, PlanStatusEnum.valueOf(dbMainPlan.getStatus()), 2, new Long[]{lmsQcMainPlan.getId()}, remark);
        }
        return super.updateById(lmsQcMainPlan);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<FlowProcess> submitCheckFlow(Long[] ids, Account account) {
        if (ArrayUtils.isEmpty(ids)) {
            return null;
        }
        List<LmsQcMainPlan> mainPlanList = super.list(Wrappers.<LmsQcMainPlan>query().in("id", ids));
        for (LmsQcMainPlan plan : mainPlanList) {
            PtAssert.fail(!PlanStatusEnum.DRAFT.getValue().equals(plan.getStatus()) , "只能提交草稿计划");
        }
        List<FlowInfo> flowInfoList = new ArrayList<>();
        List<LmsQcMainPlanRecord> recordList = new ArrayList<>();
        List<LmsQcMainPlan> updateList = mainPlanList.stream().filter(mainPlan -> null != mainPlan).map(mainPlan -> {
            flowInfoList.add(FlowInfo.convertFlowInfo(FlowType.QC_PLAN_CHECK, account, mainPlan.getId(),
                    StringHandleUtils.getObjectValue(mainPlan.getName()).toString()));
            LmsQcMainPlan plan = new LmsQcMainPlan();
            plan.setId(mainPlan.getId());
            plan.setStatus((Integer) PlanStatusEnum.AUDIT.getValue());
            plan.setProgress((Integer)PlanStatusEnum.AUDIT.getValue());

            LmsQcMainPlanRecord record = new LmsQcMainPlanRecord();
            record.setMainPlanId(mainPlan.getId());
            record.setType(0);
            record.setOperator(account.getUserName());
            record.setLiable(account.getUserName());
            record.setOrigin(PlanStatusEnum.DRAFT.getDisplay());
            record.setTarget(PlanStatusEnum.AUDIT.getDisplay());
            record.setRemark("内部质控计划提交审批");
            recordList.add(record);

            return plan;
        }).collect(Collectors.toList());
        super.updateBatchById(updateList);
        if (CollectionUtils.isNotEmpty(recordList)) {
            lmsQcMainPlanRecordService.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();
        PtAssert.fail(StringUtils.isBlank(status), "status不能为空");
        PtAssert.fail(!(status.equalsIgnoreCase("pass") || status.equalsIgnoreCase("back")), "通过状态为'pass'，驳回状态为'back'");

        LmsQcMainPlan plan = new LmsQcMainPlan();
        plan.setApproveOpinion(reason);
        plan.setApproveDate(new Date());
        plan.setApproverId(account.getUserId());
        plan.setApprover(account.getUserName());

        LmsQcMainPlanRecord record = new LmsQcMainPlanRecord();
        record.setOperator(account.getUserName());
        record.setLiable(account.getUserName());
        record.setOrigin(PlanStatusEnum.AUDIT.getDisplay());

        if ("pass".equals(status)) {
            //审批通过
            map.put("qcPlanCheckPass", true);
            plan.setStatus((Integer)PlanStatusEnum.PASS.getValue());
            plan.setProgress((Integer)PlanStatusEnum.PASS.getValue());

            record.setType(0);
            record.setTarget(PlanStatusEnum.PASS.getDisplay());
            record.setRemark("内部质控计划审批通过：" + reason);
        } else if ("back".equals(status)) {
            //审批驳回
            map.put("qcPlanCheckPass", false);
            plan.setStatus((Integer)PlanStatusEnum.DRAFT.getValue());
            plan.setProgress((Integer)PlanStatusEnum.BACK.getValue());

            record.setType(1);
            record.setTarget(PlanStatusEnum.BACK.getDisplay());
            record.setRemark("内部质控计划审批驳回：" + reason);
        }
        map.put(FlowInfo.APPLY_ID, account.getUserId());
        flowVariables.setVariables(map);
        flowInfo = flowProcessClient.complete(flowVariables);
        PtAssert.fail(null == flowInfo, "流程审批错误");
        plan.setId(flowInfo.getId());
        record.setMainPlanId(flowInfo.getId());
        lmsQcMainPlanRecordService.save(record);
        return updateById(plan);
    }

    @Override
    public void exportPlan(HttpServletResponse response, Long id) {
//        LmsQcMainPlan mainPlan = getById(id);
//        PtAssert.fail(null == mainPlan, "数据有误");
//        List<LmsQcSubPlan> subPlanList = lmsQcSubPlanService.list(Wrappers.<LmsQcSubPlan>query().eq("main_plan_id", id));
//        Map<String, String> replaceMap = new HashMap<>();
//        Map<String, Object> objectMap = lmsExportService.wordToMap("qc_plan.docx");
//        Iterator<XWPFTable> tableIterator = (Iterator<XWPFTable>) objectMap.get("table");
//        XWPFDocument doc = (XWPFDocument) objectMap.get("doc");
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//        replaceMap.put("system_code", lmsBaseDictService.getCodeByKeyword("受控编号", "qc_plan_code"));
//        replaceMap.put("make_date", sdf.format(mainPlan.getMakeDate()).substring(0, 4));
//        replaceMap.put("maker", mainPlan.getMaker());
//        replaceMap.put("approver", mainPlan.getApprover() == null ? "" : mainPlan.getApprover());
//        PoiUtil2007ForReplace.replaceText(doc, replaceMap);
//        PoiUtil2007ForReplace.replaceHeadText(doc, replaceMap);
//        while (tableIterator.hasNext()) {
//            XWPFTable table = tableIterator.next();
//
//            int total = subPlanList.size();
//            if (total > 0) {
//                for (int i = 1; i <= total; i++) {
//                    //表格指定位置插入一行, index为新增行所在的行位置(不能大于表行数)
//                    PoiUtil2007.insertTableRowAtIndex(table, 1);
//                }
//            }
//
//            int rowsLength = table.getNumberOfRows();
//            for (int rowIndex = 1; rowIndex < rowsLength - 1; rowIndex++) {
//                //从第2行开始
//                LmsQcSubPlan subPlan = subPlanList.get(rowIndex - 1);
//                StringHandleUtils.setText(table, rowIndex, 0, String.valueOf(rowIndex));
//                StringHandleUtils.setText(table, rowIndex, 1, subPlan.getMethod());
//                StringHandleUtils.setText(table, rowIndex, 2, subPlan.getName());
//                StringHandleUtils.setText(table, rowIndex, 3, String.valueOf(subPlan.getFrequency()));
//                StringHandleUtils.setText(table, rowIndex, 4, subPlan.getTime());
//                StringHandleUtils.setText(table, rowIndex, 5, subPlan.getMonitorUnit());
//                StringHandleUtils.setText(table, rowIndex, 6, subPlan.getMonitorMan());
//            }
//        }
//        lmsExportService.downloadDoc(response, mainPlan.getName() + "内部质控计划.docx", doc);
    }

    @Override
    public LmsQcMainPlanVO getTempVO() {
        LmsQcMainPlan entity = new LmsQcMainPlan();
        entity.setTempStatus(0);
        LmsQcMainPlan mainPlan = baseMapper.selectOne(Wrappers.query(entity));
        if (null != mainPlan) {
            LmsQcMainPlanVO vo = mainPlan.convert(LmsQcMainPlanVO.class);
            //获取附件
            LmsQcMainPlanAttachment attachment = new LmsQcMainPlanAttachment();
            attachment.setMainPlanId(mainPlan.getId());
            List<LmsQcMainPlanAttachment> attachmentList = lmsQcMainPlanAttachmentService.list(attachment);
            attachmentList.forEach(e -> {
                e.setObjectKey(ossClient.getUrl(e.getObjectKey()).toString());
            });
            vo.setFileList(attachmentList);
            return vo;
        }

        LmsQcMainPlan plan = new LmsQcMainPlan();
        plan.setTempStatus(0);
        plan.setStatus((Integer)PlanStatusEnum.DRAFT.getValue());
        plan.setProgress((Integer)PlanStatusEnum.DRAFT.getValue());
        plan.setName(" ");
        if (save(plan)) {
            LmsQcMainPlanVO vo = new LmsQcMainPlanVO();
            vo.setTempStatus(plan.getTempStatus());
            vo.setId(plan.getId());
            return vo;
        }
        return null;
    }

    @Override
    public LmsQcMainPlanAttachment uploadFile(MultipartFile file, LmsQcMainPlan lmsQcMainPlan) {
        Long companyId = LoginHelper.getAccount().getCompanyId();
        String folderPath = "base/qcMainPlan/" + companyId + "/";
        return lmsQcMainPlanAttachmentService.saveAndUpload(file, "lims", folderPath, lmsQcMainPlan.getId(), 0);
    }

    @Override
    public Boolean deleteFile(Long id) {
        Long[] ids = new Long[]{id};
        return lmsQcMainPlanAttachmentService.deleteBatch(ids);
    }

    @Override
    public LmsQcMainPlanVO getVOById(Long id) {
        LmsQcMainPlanVO lmsQcMainPlanVO = new LmsQcMainPlanVO();
        LmsQcMainPlan lmsQcMainPlan = getById(id);
        if (null != lmsQcMainPlan) {
            BeanUtils.copyProperties(lmsQcMainPlan, lmsQcMainPlanVO);
            //获取附件
            LmsQcMainPlanAttachment attachment = new LmsQcMainPlanAttachment();
            attachment.setMainPlanId(lmsQcMainPlan.getId());
            List<LmsQcMainPlanAttachment> list = lmsQcMainPlanAttachmentService.list(attachment);
            list.forEach(e -> {
                e.setObjectKey(ossClient.getUrl(e.getObjectKey()).toString());
            });
            lmsQcMainPlanVO.setFileList(list);
        }
        return lmsQcMainPlanVO;
    }

    @Override
    public Boolean add(LmsQcMainPlan lmsQcMainPlan) {
        LmsQcMainPlan entity = new LmsQcMainPlan();
        entity.setTempStatus(0);
        LmsQcMainPlan temp = baseMapper.selectOne(Wrappers.query(entity));
        lmsQcMainPlan.setTempStatus(1);
        if (null != temp) {
            lmsQcMainPlan.setId(temp.getId());
            updateById(lmsQcMainPlan);
        } else {
            save(lmsQcMainPlan);
        }
        return true;
    }
}



