package digital.laboratory.platform.inspection.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import digital.laboratory.platform.common.mybatis.security.service.DLPUser;
import digital.laboratory.platform.common.oss.service.OssFile;
import digital.laboratory.platform.inspection.enums.TestRecordFileUrl;
import digital.laboratory.platform.inspection.entity.TestRecordMethod;
import digital.laboratory.platform.inspection.entity.TestTemplate;
import digital.laboratory.platform.inspection.enums.TestRecordArgumentType;
import digital.laboratory.platform.inspection.mapper.TestRecordMapper;
import digital.laboratory.platform.inspection.mapper.TestTemplateMapper;
import digital.laboratory.platform.inspection.service.TestRecordInstrumentConditionService;
import digital.laboratory.platform.inspection.service.TestRecordMethodService;
import digital.laboratory.platform.inspection.service.TestTemplateService;
import digital.laboratory.platform.inspetion.api.vo.TestRecordVo;
import digital.laboratory.platform.inspection.vo.TestTemplateVo;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
public class TestTemplateServiceImpl extends ServiceImpl<TestTemplateMapper, TestTemplate> implements TestTemplateService {
    @Resource
    private TestRecordMapper testRecordMapper;
    @Resource
    private TestTemplateMapper testTemplateMapper;
    @Resource
    private TestRecordMethodService testRecordMethodService;

    @Resource
    private TestRecordInstrumentConditionService testRecordInstrumentConditionService;

    @Resource
    private OssFile ossFile;

    /**
     * 将实验设置为模板
     * @param testTemplate
     * @param testId
     * @param dlpUser
     * @return
     * @throws Exception
     */
    @Override
    public TestTemplate createTemplate(TestTemplate testTemplate, String testId, DLPUser dlpUser) throws Exception {
        TestRecordVo testRecord = testRecordMapper.getTestRecordMapById(testId);
        if (testRecord.getDeviceIdList() != null && testRecord.getDeviceIdList().size() > 0) {
            testTemplate.setDeviceIdList(testRecord.getDeviceIdList());
        }
        if (testRecord.getTestMethodList() != null && testRecord.getTestMethodList().size() > 0) {
            testTemplate.setTestMethods(testRecord.getTestMethodList());
        }
        if (testRecord.getReagentConsumablesList() != null && testRecord.getReagentConsumablesList().size() > 0) {
            testTemplate.setReagentConsumables(testRecord.getReagentConsumablesList());
        }
        if (testRecord.getDeviceUseCondition() != null && testRecord.getDeviceUseCondition().size() > 0) {
            testTemplate.setDeviceUseCondition(testRecord.getDeviceUseCondition());
        }
        testTemplate.setAuthor(dlpUser.getId());
        testTemplate.setStatus(0);
        testTemplate.setCreateDate(LocalDateTime.now());
        testTemplate.setUseCount(0);
        testTemplate.setId(IdWorker.get32UUID().toUpperCase());
        //创建仪器条件
        testRecordInstrumentConditionService.copyConditionWord(testTemplate.getId(), testId);
        return this.save(testTemplate) ? testTemplate : null;
    }

    /**
     * 修改模板
     * @param testTemplate
     * @return
     */
    @Override
    public TestTemplate editTemplate(TestTemplate testTemplate) {
        if (testTemplate.getStatus() != 0) {
            throw new RuntimeException(String.format("当前模板仍处于发布状态，请先停用后再进行编辑!"));
        }
        return this.updateById(testTemplate) ? testTemplate : null;
    }

    /**
     * 删除模板 支持批量
     * @param idList
     * @param dlpUser
     * @return
     */
    @Override
    public boolean delTemplate(List<String> idList, DLPUser dlpUser) {
        List<TestTemplate> list = this.list(Wrappers.<TestTemplate>lambdaQuery().in(TestTemplate::getId, idList));
        for (TestTemplate testTemplate : list) {
            if (!testTemplate.getAuthor().equals(dlpUser.getId())) {
                throw new RuntimeException(String.format("这个模板不是你创建的，无法删除!"));
            }
            if (testTemplate.getStatus() != 0) {
                throw new RuntimeException(String.format("请先停用模板后再进行删除!"));
            }
        }
        return this.removeBatchByIds(list);
    }

    /**
     * 向模板添加或移除参数
     * @param templateId 模板ID
     * @param argumentId 物品ID
     * @param argument 物品类型
     * @param opCode 添加还是移除
     * @return
     */
    @Override
    public boolean updateTestTemplate(String templateId, String argumentId, String argument, Integer opCode) {
        TestTemplateVo templateVo = baseMapper.getTestTemplateMapById(templateId);
        if (templateVo.getStatus() != 0) {
            throw new RuntimeException(String.format("当前模板仍处于发布状态，请先停用后再进行编辑!"));
        }
        ArrayList<String> argumentIdList = new ArrayList<>();
        if (argument.equals(TestRecordArgumentType.TEST_RECORD_ARGUMENT_INSTRUMENT.getType())) {
            if (templateVo.getDeviceIdList() != null && templateVo.getDeviceIdList().size() > 0) {
                argumentIdList.addAll(templateVo.getDeviceIdList());
            }
            this.updateArgument(argumentIdList, opCode, argumentId);
            templateVo.setDeviceIdList(argumentIdList);
        } else if (argument.equals(TestRecordArgumentType.TEST_RECORD_ARGUMENT_INSTRUMENT_CONDITION.getType())) {
            if (templateVo.getDeviceUseCondition() != null && templateVo.getDeviceUseCondition().size() > 0) {
                argumentIdList.addAll(templateVo.getDeviceUseCondition());
            }
            this.updateArgument(argumentIdList, opCode, argumentId);
            templateVo.setDeviceUseCondition(argumentIdList);
        } else if (argument.equals(TestRecordArgumentType.TEST_RECORD_ARGUMENT_METHOD.getType())) {
            if (templateVo.getTestMethods() != null && templateVo.getTestMethods().size() > 0) {
                argumentIdList.addAll(templateVo.getTestMethods());
            }
            this.updateArgument(argumentIdList, opCode, argumentId);
            templateVo.setTestMethods(argumentIdList);
        } else if (argument.equals(TestRecordArgumentType.TEST_RECORD_ARGUMENT_REAGENT.getType())) {
            if (templateVo.getReagentConsumables() != null && templateVo.getReagentConsumables().size() > 0) {
                argumentIdList.addAll(templateVo.getReagentConsumables());
            }
            this.updateArgument(argumentIdList, opCode, argumentId);
            templateVo.setReagentConsumables(argumentIdList);
        } else {
            throw new RuntimeException(String.format("没有传入正常的argument!"));
        }
        return this.updateById(templateVo);
    }

    /**
     * 判断添加物品的参数是否正确
     * @param argumentIdList
     * @param opCode
     * @param argumentId
     */
    public void updateArgument(List<String> argumentIdList, Integer opCode, String argumentId) {
        if (opCode == 1) {
            if (argumentIdList.size() > 0 && argumentIdList.contains(argumentId)) {
                throw new RuntimeException(String.format("当前内容已添加至模板，请勿重复添加!"));
            }
            argumentIdList.add(argumentId);
        } else if (opCode == -1 && argumentIdList.contains(argumentId)) {
            boolean ret = argumentIdList.remove(argumentId);
            if (!ret) {
                throw new RuntimeException(String.format("在模板中没有找到ID为%s的内容!", argumentId));
            }
        }
    }

    /**
     * 发布模板
     * @param id
     * @return
     */
    @Override
    public TestTemplateVo publishTemplate(String id) {
        TestTemplateVo templateVo = testTemplateMapper.getTestTemplateMapById(id);
        templateVo.setPublishDate(LocalDateTime.now());
        if (templateVo.getStatus() != 0) {
            throw new RuntimeException(String.format("当前模板不处在未发布的状态，无法进行发布!"));
        }
        templateVo.setStatus(1);
        return this.updateById(templateVo) ? templateVo : null;
    }

    /**
     * 停用模板
     * @param id
     * @return
     */
    @Override
    public TestTemplateVo blockTemplate(String id) {
        TestTemplateVo templateVo = testTemplateMapper.getTestTemplateMapById(id);
        templateVo.setStatus(0);
        return this.updateById(templateVo) ? templateVo : null;
    }

    /**
     * 通过ID查询模板
     * @param id
     * @return
     */
    @Override
    public TestTemplateVo getTemplateById(String id) {
        TestTemplateVo templateVo = baseMapper.getTestTemplateMapById(id);
        this.getMethodName(templateVo);
        List<String> fileNameList = ossFile.fileList(TestRecordFileUrl.TEST_TEMPLATE_CATALOGUE.getFileUrl() + "/" + templateVo.getId());
        if (fileNameList != null && fileNameList.size() > 0) {
            boolean ret = fileNameList.contains("仪器条件.docx");
            if (ret) {
                templateVo.setInstrumentConditionFileName("仪器条件.docx");
                templateVo.setInstrumentConditionUrl(TestRecordFileUrl.TEST_TEMPLATE_CATALOGUE.getFileUrl() + "/" + templateVo.getId() + "/" + "仪器条件.docx");
            }
        }
        return templateVo;
    }

    /**
     * @param opCode 1:查询所有发布的公有模板 -1：查询自己发布的所有模板
     * @param dlpUser 用户信息
     * @param keywords 查询参数：模板名称
     * */
    @Override
    public IPage<TestTemplateVo> getTemplateVoPage(Page page, Integer opCode, DLPUser dlpUser, String keywords) {
        LambdaQueryWrapper<TestTemplate> wrapper = new LambdaQueryWrapper<>();
        //查询所有公有且已发布的模板(去掉自己发布的)
        if (opCode == 1) {
            wrapper.ne(TestTemplate::getAuthor, dlpUser.getId())
                    .eq(TestTemplate::getStatus, 1)
                    .eq(TestTemplate::isNature, true)
                    .like(StrUtil.isNotBlank(keywords), TestTemplate::getName, keywords)
                    .orderByDesc(TestTemplate::getCreateDate);
            IPage<TestTemplateVo> iPage = baseMapper.getTestTemplateMapPage(page, wrapper);
            return iPage;
            //查询所有自己发布的模板
        } else {
            wrapper.eq(TestTemplate::getAuthor, dlpUser.getId())
                    .like(StrUtil.isNotBlank(keywords), TestTemplate::getName, keywords)
                    .orderByDesc(TestTemplate::getCreateDate);
            IPage<TestTemplateVo> iPage = baseMapper.getTestTemplateMapPage(page, wrapper);
            return iPage;
        }
    }

    /**
     * 获取模板中的方法名集合
     * @param testTemplate
     */
    public void getMethodName(TestTemplateVo testTemplate) {
        if (testTemplate.getTestMethods() != null && testTemplate.getTestMethods().size() > 0) {
            ArrayList<String> nameList = new ArrayList<>();
            List<TestRecordMethod> list = testRecordMethodService.list(Wrappers.<TestRecordMethod>lambdaQuery().in(TestRecordMethod::getId, testTemplate.getTestMethods()));
            list.forEach(item -> nameList.add(item.getMethodName()));
            testTemplate.setTestMethodName(nameList);
        }
    }

    /**
     * 列表查询模板信息(创建实验时)
     * @param dlpUser
     * @return
     */
    @Override
    public List<TestTemplateVo> getTemplateVoList(DLPUser dlpUser) {
        return baseMapper.getTestTemplateMapList(Wrappers.<TestTemplate>lambdaQuery()
                .and(wrapper -> wrapper.eq(TestTemplate::getAuthor, dlpUser.getId())
                        .or()
                        .eq(TestTemplate::isNature, true))
                .eq(TestTemplate::getStatus, 1)
                .orderByDesc(TestTemplate::getCreateDate));
    }

}
