package com.hxhq.business.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hxhq.business.domain.*;
import com.hxhq.business.dto.sj.SjListDto;
import com.hxhq.business.dto.study.StudyFormFillCc;
import com.hxhq.business.dto.study.StudyFormFillCz;
import com.hxhq.business.dto.study.StudyFormFillResource;
import com.hxhq.business.enums.archive.ArchiveLogTypeEnum;
import com.hxhq.business.enums.zykgl.*;
import com.hxhq.business.form.gsp.GspGdForm;
import com.hxhq.business.form.gsp.GspJyForm;
import com.hxhq.business.form.gsp.GspSearchListForm;
import com.hxhq.business.form.mjy.GdForm;
import com.hxhq.business.form.sj.*;
import com.hxhq.business.service.*;
import com.hxhq.business.utils.JctUtil;
import com.hxhq.business.utils.ObjectCompareUtil;
import com.hxhq.common.core.exception.ServiceException;
import com.hxhq.common.core.utils.DateUtils;
import com.hxhq.common.security.utils.SecurityUtils;
import com.hxhq.system.api.domain.SysUser;
import com.hxhq.system.service.ISysUserService;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.hxhq.business.mapper.SjMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

/**
 * 试剂库存Service业务层处理
 *
 * @author HanLong
 * @date 2025-12-22
 */
@Service
public class SjServiceImpl extends ServiceImpl<SjMapper, Sj> implements ISjService
{
    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private ISjJcgjService sjJcgjService;

    @Autowired
    private ISjTzService sjTzService;

    @Autowired
    private IStudySjService studySjService;

    @Autowired
    private IArchiveLogService archiveLogService;

    @Autowired
    private INoticeService noticeService;

    /**
     * 查询试剂库存列表
     *
     * @param form 试剂库存
     * @return 试剂库存
     */
    @Override
    public List<SjListDto> queryList(SjSearchListForm form)
    {
        QueryWrapper<Sj> queryWrapper = Wrappers.query();
        queryWrapper.eq("s.del_flag", 0);
        if(StringUtils.isNotEmpty(form.getMc())) {
            queryWrapper.like("s.mc", form.getMc());
        }
        if(StringUtils.isNotEmpty(form.getBh())) {
            queryWrapper.like("s.bh", form.getBh());
        }
        if(StringUtils.isNotEmpty(form.getStartDate())) {
            queryWrapper.ge("s.sxr", form.getStartDate());
        }
        if(StringUtils.isNotEmpty(form.getEndDate())) {
            queryWrapper.le("s.sxr", form.getEndDate());
        }
        if(form.getZjzt() != null) {
            queryWrapper.eq("s.zjzt", form.getZjzt());
        }
        if(form.getJyzt() != null) {
            queryWrapper.eq("s.jyzt", form.getJyzt());
        }
        if(StringUtils.isNotEmpty(form.getDeptName())) {
            queryWrapper.like("d.dept_name", form.getDeptName());
        }
        if(StringUtils.isNotEmpty(form.getStudyName())) {
            queryWrapper.like("t.name", form.getStudyName());
        }
        if(form.getArchive() != null && form.getArchive() == DaztEnum.ygd.getValue()) {
            queryWrapper.in("s.zjzt", ZjztEnum.dgd.getValue(), ZjztEnum.gd.getValue(), ZjztEnum.djd.getValue());
        }
        queryWrapper.orderByDesc("s.id");
        return baseMapper.queryList(queryWrapper);
    }

    @Override
    public List<SjListDto> queryPublicList(SjSearchListForm form) {
        QueryWrapper<Sj> queryWrapper = Wrappers.query();
        queryWrapper.eq("s.del_flag", 0);
        queryWrapper.and(p -> p.apply("(s.zjzt = {0} OR (s.zjzt IS NULL AND s.study_form_id = {1}))"
                , ZjztEnum.rk.getValue(), form.getStudyFormId()));
        if(StringUtils.isNotEmpty(form.getMc())) {
            queryWrapper.like("s.mc", form.getMc());
        }
        if(StringUtils.isNotEmpty(form.getBh())) {
            queryWrapper.like("s.bh", form.getBh());
        }
        if(StringUtils.isNotEmpty(form.getStudyName())) {
            queryWrapper.like("t.name", form.getStudyName());
        }
        queryWrapper.orderByDesc("s.id");
        return baseMapper.queryList(queryWrapper);
    }

    @Override
    public Sj getSjByBh(String bh) {
        LambdaQueryWrapper<Sj> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Sj::getBh, bh);
        return this.getOne(queryWrapper);
    }

    @Override
    public SjListDto getInfo(Long id) {

        return baseMapper.queryInfo(id);
    }

    @Override
    public void xgkc(SjXgkcForm form) {
        SysUser qmr = sysUserService.selectUserById(form.getQmrId());
        sysUserService.checkPassword(qmr, form.getQmrmm(), false);
        if (form.getId() == null || form.getId().longValue() < 0) {
            throw new SecurityException("参数id不正确");
        }
        Sj sjOld = this.getById(form.getId());
        if (sjOld == null) {
            throw new SecurityException("试剂不存在或已删除");
        }
        if (!sjOld.getZjzt().equals(ZjztEnum.rk.getValue())) {
            throw new SecurityException("试剂【" + sjOld.getMc() + "】不是入库状态，不能修改库存");
        }
        List<ObjectCompareUtil.FieldChange> fieldChanges = ObjectCompareUtil.compareObjects(sjOld, form);
        if (fieldChanges.size() == 0) {
            throw new SecurityException("你没有修改任何内容");
        }
        sjOld.setKcdw(form.getKcdw());
        sjOld.setKc(form.getKc());
        this.updateById(sjOld);

        List<SjJcgj> sjJcgjList = new ArrayList<>();
        //region 稽查轨迹
        for (ObjectCompareUtil.FieldChange fieldChange : fieldChanges) {
            SjJcgj jcgj = new SjJcgj();
            jcgj.setSjId(sjOld.getId());
            jcgj.setJcgjlx(JcgjlxEnum.lc.getValue());
            jcgj.setJcmc("修改库存");
            jcgj.setJcmcEn("Change Inventory");
            jcgj.setJcmcys(JcmcysEnum.green.getValue());
            jcgj.setJcnr(fieldChange.toString());
            jcgj.setJcnrEn(fieldChange.toEnString());
            jcgj.setQmrId(qmr.getUserId());
            jcgj.setQmrMc(qmr.getNickName());
            jcgj.setQmrMcEn(qmr.getUserName());
            jcgj.setRemark(form.getKcbjbz());
            sjJcgjList.add(jcgj);
        }
        sjJcgjService.saveBatch(sjJcgjList);
        //endregion

        // 台账
        sjTzService.saveTz(sjOld.getId(), qmr.getUserId(), qmr.getNickName(), qmr.getUserName(),
                "修改库存",  "Change Inventory", form.getKc(), form.getKcdw(), form.getKcbjbz());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cz(CzSjForm form) {
        SysUser qmr = sysUserService.selectUserById(form.getQmrId());
        sysUserService.checkPassword(qmr, form.getQmrmm(), false);

        if (form.getId() == null || form.getId() < 0) {
            throw new SecurityException("参数id不正确");
        }
        Sj sjOld = this.getById(form.getId());
        if (sjOld == null) {
            throw new SecurityException("试剂不存在或已删除");
        }
        if (!sjOld.getZjzt().equals(ZjztEnum.rk.getValue())) {
            throw new SecurityException("试剂【" + sjOld.getMc() + "】不是入库状态，不能处置");
        }
        if(!NumberUtils.isParsable(form.getCzl())) {
            throw new ServiceException("请输入正确的处置量");
        }
        BigDecimal czl = new BigDecimal(form.getCzl());
        BigDecimal kc = new BigDecimal(sjOld.getKc());
        if(czl.compareTo(kc) > 0) {
            throw new ServiceException("处置量不应大于库存量");
        }
        kc = kc.subtract(czl);
        sjOld.setKc(kc.toString());
        updateById(sjOld);

        LinkedHashMap<String, String> jcnrMap = new LinkedHashMap<>();
        jcnrMap.put("处置方式", form.getCzfs());
        jcnrMap.put("处置量", form.getCzl());
        jcnrMap.put("原因", form.getRemark());

        LinkedHashMap<String, String> jcnrEnMap = new LinkedHashMap<>();
        jcnrEnMap.put("Dispose Method", form.getCzfs());
        jcnrEnMap.put("Amount", form.getCzl());
        jcnrEnMap.put("Reason", form.getRemark());
        SjJcgj sjJcgj = new SjJcgj();
        sjJcgj.setSjId(sjOld.getId());
        sjJcgj.setJcgjlx(JcgjlxEnum.bj.getValue());
        sjJcgj.setJcmc("处置");
        sjJcgj.setJcmcEn("Dispose");
        sjJcgj.setJcnr(JctUtil.formatStr(jcnrMap));
        sjJcgj.setJcnrEn(JctUtil.formatStr(jcnrEnMap));
        sjJcgj.setJcmcys(JcmcysEnum.green.getValue());
        sjJcgj.setQmrId(qmr.getUserId());
        sjJcgj.setQmrMc(qmr.getNickName());
        sjJcgj.setQmrMcEn(qmr.getUserName());
        sjJcgjService.save(sjJcgj);

        // 台账
        sjTzService.saveTz(sjOld.getId(), qmr.getUserId(), qmr.getNickName(), qmr.getUserName(),
                "处置", "Dispose", form.getCzl(), sjOld.getKcdw(), form.getRemark());

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void plcz(PlczSjForm form) {
        SysUser qmr = sysUserService.selectUserById(form.getQmrId());
        sysUserService.checkPassword(qmr, form.getQmrmm(), false);

        List<Sj> sjList = new ArrayList<>();
        Map<Long, Sj> map = new HashMap<>();
        for (PlczSjItemForm itemForm : form.getList()) {
            if (itemForm.getId() == null || itemForm.getId() < 0) {
                throw new SecurityException("参数id不正确");
            }
            Sj sj = this.getById(itemForm.getId());
            if (sj == null) {
                throw new SecurityException("试剂不存在或已删除");
            }
            if (!sj.getZjzt().equals(ZjztEnum.rk.getValue())) {
                throw new SecurityException("试剂【" + sj.getMc() + "】不是入库状态，不能处置");
            }
            if(!NumberUtils.isParsable(itemForm.getCzl())) {
                throw new ServiceException("请输入正确的处置量");
            }
            BigDecimal czl = new BigDecimal(itemForm.getCzl());
            BigDecimal kc = new BigDecimal(sj.getKc());
            if(czl.compareTo(kc) > 0) {
                throw new ServiceException("处置量不应大于库存量");
            }
            kc = kc.subtract(czl);
            sj.setKc(kc.toString());
            sjList.add(sj);

            map.put(sj.getId(), sj);
        }
        updateBatchById(sjList);

        List<SjJcgj> sjJcgjList = new ArrayList<>();
        List<SjTz> sjTzList = new ArrayList<>();
        for (PlczSjItemForm itemForm : form.getList()) {
            Sj sj = map.get(itemForm.getId());

            LinkedHashMap<String, String> jcnrMap = new LinkedHashMap<>();
            jcnrMap.put("处置方式", itemForm.getCzfs());
            jcnrMap.put("处置量", itemForm.getCzl());
            jcnrMap.put("原因", itemForm.getRemark());
            LinkedHashMap<String, String> jcnrEnMap = new LinkedHashMap<>();
            jcnrEnMap.put("Dispose Method", itemForm.getCzfs());
            jcnrEnMap.put("Amount", itemForm.getCzl());
            jcnrEnMap.put("Reason", itemForm.getRemark());
            SjJcgj sjJcgj = new SjJcgj();
            sjJcgj.setSjId(itemForm.getId());
            sjJcgj.setJcgjlx(JcgjlxEnum.bj.getValue());
            sjJcgj.setJcmc("处置");
            sjJcgj.setJcmcEn("Dispose");
            sjJcgj.setJcnr(JctUtil.formatStr(jcnrMap));
            sjJcgj.setJcnrEn(JctUtil.formatStr(jcnrEnMap));
            sjJcgj.setJcmcys(JcmcysEnum.green.getValue());
            sjJcgj.setQmrId(qmr.getUserId());
            sjJcgj.setQmrMc(qmr.getNickName());
            sjJcgj.setQmrMcEn(qmr.getUserName());
            sjJcgjList.add(sjJcgj);

            // 台账
            SjTz sjTz = new SjTz();
            sjTz.setSjId(sj.getId());
            sjTz.setQmrId(qmr.getUserId());
            sjTz.setQmrMc(qmr.getNickName());
            sjTz.setQmrMcEn(qmr.getUserName());
            sjTz.setQmyy("处置");
            sjTz.setQmyyEn("Dispose");
            sjTz.setCzl(itemForm.getCzl());
            sjTz.setCzldw(sj.getKcdw());
            sjTz.setRemark(itemForm.getRemark());
            sjTzList.add(sjTz);
        }
        sjJcgjService.saveBatch(sjJcgjList);
        sjTzService.saveBatch(sjTzList);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sd(SdSjForm form) {
        SysUser qmr = sysUserService.selectUserById(form.getQmrId());
        sysUserService.checkPassword(qmr, form.getQmrmm(), false);
        if (form.getId() == null || form.getId().longValue() < 0) {
            throw new SecurityException("参数id不正确");
        }
        Sj sj = this.getById(form.getId());
        if (sj == null) {
            throw new SecurityException("试剂不存在或已删除");
        }
        if (!sj.getZjzt().equals(ZjztEnum.rk.getValue())) {
            throw new SecurityException("试剂【" + sj.getMc() + "】不是入库状态，不能锁定");
        }
        sj.setZjzt(ZjztEnum.ysd.getValue());
        this.updateById(sj);
        //稽查轨迹
        Map<String, String> formData = new LinkedHashMap<>();
        formData.put("备注", form.getRemark());

        Map<String, String> formDataEn = new LinkedHashMap<>();
        formDataEn.put("Comment", form.getRemark());
        sjJcgjService.saveJcgj(sj.getId(), JcgjlxEnum.lc.getValue(), "锁定试剂", "Lock Reagent",JcmcysEnum.green.getValue(),
                JctUtil.formatStr(formData), JctUtil.formatStr(formDataEn));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void plsd(SdSjForm form) {
        SysUser qmr = sysUserService.selectUserById(form.getQmrId());
        sysUserService.checkPassword(qmr, form.getQmrmm(), false);

        List<Sj> sjList = new ArrayList<>();
        for (Long id : form.getIds()) {
            if (id == null || id < 0) {
                throw new SecurityException("参数id不正确");
            }
            Sj sj = this.getById(id);
            if (sj == null) {
                throw new SecurityException("试剂不存在或已删除");
            }
            if (!sj.getZjzt().equals(ZjztEnum.rk.getValue())) {
                throw new SecurityException("试剂【" + sj.getMc() + "】不是入库状态，不能锁定");
            }
            sj.setZjzt(ZjztEnum.ysd.getValue());
            sjList.add(sj);
        }
        this.updateBatchById(sjList);
        //稽查轨迹
        for (Sj sj : sjList) {
            //稽查轨迹
            Map<String, String> formData = new LinkedHashMap<>();
            formData.put("备注", form.getRemark());

            Map<String, String> formDataEn = new LinkedHashMap<>();
            formDataEn.put("Comment", form.getRemark());
            sjJcgjService.saveJcgj(sj.getId(), JcgjlxEnum.lc.getValue(), "锁定试剂", "Lock Reagent", JcmcysEnum.green.getValue(), JctUtil.formatStr(formData),
                    JctUtil.formatStr(formDataEn));
        }

    }

    @Override
    public void js(JsSjForm form) {
        SysUser qmr = sysUserService.selectUserById(form.getQmrId());
        sysUserService.checkPassword(qmr, form.getQmrmm(), false);
        if (form.getId() == null || form.getId().longValue() < 0) {
            throw new SecurityException("参数id不正确");
        }
        Sj sjOld = this.getById(form.getId());
        if (sjOld == null) {
            throw new SecurityException("试剂不存在或已删除");
        }
        if (!sjOld.getZjzt().equals(ZjztEnum.ysd.getValue())) {
            throw new SecurityException("试剂【" + sjOld.getMc() + "】不是已锁定状态，不能解锁");
        }
        //点击解锁，状态更新为入库；
        sjOld.setZjzt(ZjztEnum.rk.getValue());
        this.updateById(sjOld);
        //稽查轨迹
        Map<String, String> formData = new LinkedHashMap<>();
        formData.put("备注", form.getRemark());

        Map<String, String> formDataEn = new LinkedHashMap<>();
        formDataEn.put("Comment", form.getRemark());
        sjJcgjService.saveJcgj(sjOld.getId(), JcgjlxEnum.lc.getValue(), "解锁试剂","Unlock Reagent",
                JcmcysEnum.green.getValue(), JctUtil.formatStr(formData), JctUtil.formatStr(formDataEn));
    }

    @Override
    public void jy(JySjForm form) {
        SysUser qmr = sysUserService.selectUserById(form.getQmrId());
        sysUserService.checkPassword(qmr, form.getQmrmm(), false);

        if (form.getId() == null || form.getId().longValue() < 0) {
            throw new SecurityException("参数id不正确");
        }
        Sj sjOld = this.getById(form.getId());
        if (sjOld == null) {
            throw new SecurityException("试剂不存在或已删除");
        }
        if (!sjOld.getZjzt().equals(ZjztEnum.gd.getValue())) {
            throw new SecurityException("试剂【" + sjOld.getMc() + "】不是归档状态，不能借阅");
        }
        if (!sjOld.getJyzt().equals(JyztEnum.wjy.getValue())) {
            throw new SecurityException("试剂【" + sjOld.getMc() + "】不是未借阅状态，不能借阅");
        }
        if(!sjOld.getDasqrId().equals(qmr.getUserId())){
            throw new ServiceException("只有归档申请人才能操作");
        }
        //申请借阅后，借阅状态更新为待借阅，等待档案员审核期间无法进行其他操作；
        sjOld.setJyzt(JyztEnum.djy.getValue());
        sjOld.setJyksrq(form.getStartDate());
        sjOld.setJyjsrq(form.getEndDate());
        this.updateById(sjOld);
        //稽查轨迹
        Map<String, String> formData = new LinkedHashMap<>();
        formData.put("借阅开始时间", DateUtils.dateTime(form.getStartDate()));
        formData.put("借阅结束时间", DateUtils.dateTime(form.getEndDate()));
        formData.put("备注", form.getRemark());

        Map<String, String> formDataEn = new LinkedHashMap<>();
        formDataEn.put("Start Date", DateUtils.dateTime(form.getStartDate()));
        formDataEn.put("End Date", DateUtils.dateTime(form.getEndDate()));
        formDataEn.put("Comment", form.getRemark());
        sjJcgjService.saveJcgj(sjOld.getId(), JcgjlxEnum.lc.getValue(), "申请借阅", "Apply for Check-out",
                JcmcysEnum.orange.getValue(), JctUtil.formatStr(formData), JctUtil.formatStr(formDataEn));

        archiveLogService.saveInfo(ArchiveLogTypeEnum.sj, sjOld.getId(), sjOld.getMc(), sjOld.getBh(), sjOld.getNd() + sjOld.getNddw(), "申请借阅");

    }

    @Override
    public void jd(JdSjForm form) {
        SysUser qmr = sysUserService.selectUserById(form.getQmrId());
        sysUserService.checkPassword(qmr, form.getQmrmm(), false);

        if (form.getId() == null || form.getId().longValue() < 0) {
            throw new SecurityException("参数id不正确");
        }
        Sj sjOld = this.getById(form.getId());
        if (sjOld == null) {
            throw new SecurityException("试剂不存在或已删除");
        }
        if (!sjOld.getZjzt().equals(ZjztEnum.gd.getValue())) {
            throw new SecurityException("试剂【" + sjOld.getMc() + "】未归档，不能解档");
        }
        if(!sjOld.getDasqrId().equals(qmr.getUserId())){
            throw new ServiceException("只有归档申请人才能操作");
        }
        //申请解档后，制剂状态更新为待解档，等待档案员审核期间无法进行其他操作；
        sjOld.setZjzt(ZjztEnum.djd.getValue());
        this.updateById(sjOld);
        //稽查轨迹
        Map<String, String> formData = new LinkedHashMap<>();
        formData.put("备注", form.getRemark());

        Map<String, String> formDataEn = new LinkedHashMap<>();
        formDataEn.put("Comment", form.getRemark());
        sjJcgjService.saveJcgj(sjOld.getId(), JcgjlxEnum.lc.getValue(), "申请解档", "Apply for De-archiving",
                JcmcysEnum.green.getValue(), JctUtil.formatStr(formData), JctUtil.formatStr(formDataEn));

        archiveLogService.saveInfo(ArchiveLogTypeEnum.sj, sjOld.getId(), sjOld.getMc(), sjOld.getBh(), sjOld.getNd() + sjOld.getNddw(), "申请解档");

    }

    @Override
    public void gd(GdSjForm form) {
        SysUser qmr = sysUserService.selectUserById(form.getQmrId());
        sysUserService.checkPassword(qmr, form.getQmrmm(), false);

        if (form.getId() == null || form.getId().longValue() < 0) {
            throw new SecurityException("参数id不正确");
        }
        Sj sjOld = this.getById(form.getId());
        if (sjOld == null) {
            throw new SecurityException("试剂不存在或已删除");
        }
        if (!sjOld.getZjzt().equals(ZjztEnum.ysd.getValue())) {
            throw new SecurityException("试剂【" + sjOld.getMc() + "】不是锁定状态，不能归档");
        }
        //申请归档，档案员可在档案管理中进行确认归档审核；申请后状态更新成待归档；
        sjOld.setZjzt(ZjztEnum.dgd.getValue());
        sjOld.setGdsqsj(new Date());
        sjOld.setDasqrId(qmr.getUserId());
        this.updateById(sjOld);
        //稽查轨迹
        Map<String, String> formData = new LinkedHashMap<>();
        formData.put("备注", form.getRemark());

        Map<String, String> formDataEn = new LinkedHashMap<>();
        formDataEn.put("Comment", form.getRemark());
        sjJcgjService.saveJcgj(sjOld.getId(), JcgjlxEnum.lc.getValue(), "申请归档", "Apply for Archiving",
                JcmcysEnum.green.getValue(), JctUtil.formatStr(formData), JctUtil.formatStr(formDataEn));

        archiveLogService.saveInfo(ArchiveLogTypeEnum.sj, sjOld.getId(), sjOld.getMc(), sjOld.getBh(), sjOld.getNd() + sjOld.getNddw(), "申请归档");

    }

    @Override
    public void plgd(GdSjForm form) {
        SysUser qmr = sysUserService.selectUserById(form.getQmrId());
        sysUserService.checkPassword(qmr, form.getQmrmm(), false);


        List<Sj> sjList = new ArrayList<>();
        for (Long id : form.getIds()) {
            if (id == null || id < 0) {
                throw new SecurityException("参数id不正确");
            }
            Sj sjOld = this.getById(id);
            if (sjOld == null) {
                throw new SecurityException("试剂不存在或已删除");
            }
            if (!sjOld.getZjzt().equals(ZjztEnum.ysd.getValue())) {
                throw new SecurityException("试剂【" + sjOld.getMc() + "】不是锁定状态，不能归档");
            }
            //申请归档，档案员可在档案管理中进行确认归档审核；申请后状态更新成待归档；
            sjOld.setZjzt(ZjztEnum.dgd.getValue());
            sjOld.setGdsqsj(new Date());
            sjOld.setDasqrId(qmr.getUserId());
            sjList.add(sjOld);
        }
        this.updateBatchById(sjList);

        //稽查轨迹
        for (Sj sj : sjList) {
            Map<String, String> formData = new LinkedHashMap<>();
            formData.put("备注", form.getRemark());

            Map<String, String> formDataEn = new LinkedHashMap<>();
            formDataEn.put("Comment", form.getRemark());
            sjJcgjService.saveJcgj(sj.getId(), JcgjlxEnum.lc.getValue(), "申请归档", "Apply for Archiving",
                    JcmcysEnum.green.getValue(), JctUtil.formatStr(formData), JctUtil.formatStr(formDataEn));

            archiveLogService.saveInfo(ArchiveLogTypeEnum.sj, sj.getId(), sj.getMc(), sj.getBh(), sj.getNd() + sj.getNddw(), "申请归档");
        }

    }

    @Override
    public void bj(SjBjForm form) {
        SysUser qmr = sysUserService.selectUserById(form.getQmrId());
        sysUserService.checkPassword(qmr, form.getQmrmm(), false);


        Sj sjOld = this.getById(form.getId());
        if (sjOld == null) {
            throw new SecurityException("试剂不存在或已删除");
        }
        if (!sjOld.getZjzt().equals(ZjztEnum.rk.getValue())) {
            throw new SecurityException("试剂【" + sjOld.getMc() + "】不是入库状态，不能编辑");
        }
        List<ObjectCompareUtil.FieldChange> fieldChanges = ObjectCompareUtil.compareObjects(sjOld, form);
        if (fieldChanges.size() == 0) {
            throw new ServiceException("你没有修改任何内容");
        }

        BeanUtils.copyProperties(form, sjOld);
        updateById(sjOld);

        List<SjJcgj> gspJcgjList = new ArrayList<>();
        for (ObjectCompareUtil.FieldChange fieldChange : fieldChanges) {
            SjJcgj sjJcgj = new SjJcgj();
            sjJcgj.setSjId(sjOld.getId());
            sjJcgj.setJcgjlx(JcgjlxEnum.lc.getValue());
            sjJcgj.setJcmc("编辑");
            sjJcgj.setJcmcEn("Edit");
            sjJcgj.setJcmcys(JcmcysEnum.green.getValue());
            sjJcgj.setJcnr(fieldChange.toString());
            sjJcgj.setJcnrEn(fieldChange.toEnString());
            sjJcgj.setQmrId(qmr.getUserId());
            sjJcgj.setQmrMc(qmr.getNickName());
            sjJcgj.setQmrMcEn(qmr.getUserName());
            sjJcgj.setRemark(form.getQmbz());
            gspJcgjList.add(sjJcgj);
        }
        sjJcgjService.saveBatch(gspJcgjList);
    }

    @Override
    public List<SjListDto> queryStudyList(GspSearchListForm form) {
        QueryWrapper<Sj> queryWrapper = Wrappers.query();
        queryWrapper.eq("ts.del_flag", "0");
        queryWrapper.eq("ts.study_id", form.getStudyId());
        if (form.getJyzt() != null && form.getJyzt().intValue() > 0) {
            queryWrapper.eq("t.jyzt", form.getJyzt());
        }
        if (form.getZjzt() != null && form.getZjzt().intValue() > 0) {
            queryWrapper.eq("t.zjzt", form.getZjzt());
        } else {
            queryWrapper.isNotNull("t.zjzt");
        }
        if(StringUtils.isNotEmpty(form.getLy())) {
            queryWrapper.like("t.ly", form.getLy());
        }
        if (StringUtils.isNoneBlank(form.getMc())) {
            queryWrapper.and(p -> p.like("t.`mc`", form.getMc()));
        }
        if (StringUtils.isNoneBlank(form.getBh())) {
            queryWrapper.and(p -> p.like("t.`bh`", form.getBh()));
        }
        if (StringUtils.isNoneBlank(form.getStartDate())) {
            queryWrapper.apply("t.sxrq>={0}", form.getStartDate());
        }
        if (StringUtils.isNoneBlank(form.getEndDate())) {
            queryWrapper.apply("t.sxrq<{0}", form.getEndDate());
        }
        queryWrapper.orderByDesc("ts.id");
        return baseMapper.queryStudyList(queryWrapper);
    }

    @Override
    public void genResource(StudyFormFill studyFormFill, Template template) {
        System.out.println(System.currentTimeMillis());
        SysUser qmr = sysUserService.selectUserById(SecurityUtils.getUserId());

        Long studyId = studyFormFill.getStudyId();
        Long studyFormId = studyFormFill.getId();
        // 生成/使用
        String resource = studyFormFill.getResource();
        Map<String, Sj> sjMap = new HashMap<>();
        List<Sj> sjList = new ArrayList<>();
        LinkedList<SjJcgj> jcgjList = new LinkedList<>();
        LinkedList<SjTz> tzList = new LinkedList<>();
        if(StringUtils.isNotEmpty(resource) && !StringUtils.equals("[]", resource)) {
            List<StudyFormFillResource> studyFormFillResourceList = JSONUtil.toList(resource, StudyFormFillResource.class);
            List<String> bhList = studyFormFillResourceList.stream().map(StudyFormFillResource::getBh).collect(Collectors.toList());
            // 根据编号获取需要处置的试剂列表
            LambdaQueryWrapper<Sj> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(Sj::getBh, bhList);
            sjList = this.list(queryWrapper);
            for (Sj sj : sjList) {
                sjMap.put(sj.getBh(), sj);
            }

            for (StudyFormFillResource studyFormFillResource : studyFormFillResourceList) {
                Sj sj = sjMap.get(studyFormFillResource.getBh());
                if(sj == null) {
                    sj = new Sj();
                    sj.setStudyId(studyId);
                    sj.setStudyFormId(studyFormId);
                    sj.setZjzt(ZjztEnum.rk.getValue());
                    sj.setJyzt(JyztEnum.wjy.getValue());
                    sj.setDeptId(template.getDeptId());
                }
                sj.setMc(studyFormFillResource.getMc());
                sj.setBh(studyFormFillResource.getBh());
                sj.setNd(String.valueOf(studyFormFillResource.getNdz()));
                sj.setNddw(studyFormFillResource.getNddw());
                sj.setKc(String.valueOf(studyFormFillResource.getKc()));
                sj.setKcdw(studyFormFillResource.getKcdw());
                sj.setLy(studyFormFillResource.getSource());
                sj.setSxr(DateUtils.parseDate(studyFormFillResource.getSxrq()));
                sj.setPzrq(studyFormFill.getStartDate());
                sj.setYxzq(studyFormFillResource.getYxzq());
                sj.setYxzqdw(studyFormFillResource.getYxzqdw());
                if(sj.getId() == null) {
                    this.save(sj);
                    sjList.add(sj);
                    sjMap.put(sj.getBh(), sj);

                    // 稽查轨迹
                    SjJcgj sjJcgj = sjJcgjService.genJcgj(sj.getId(), JcgjlxEnum.lc.getValue(), "配制完成", "Formulation Completed",
                            JcmcysEnum.green.getValue(), null, null, qmr);
                    jcgjList.add(sjJcgj);

                    // 台账
                    SjTz sjTz = sjTzService.genTz(sj.getId(), "配制完成", "Formulation Completed", sj.getKc(), sj.getKcdw(), null, qmr);
                    tzList.add(sjTz);
                } else {
                    this.updateById(sj);
                }
                // 使用
                String syl = studyFormFillResource.getSyl();
                if(StringUtils.isNotEmpty(syl) && NumberUtils.isParsable(syl)) {
                    BigDecimal kc = new BigDecimal(sj.getKc());
                    kc = kc.subtract(new BigDecimal(syl));
                    baseMapper.updateKc(sj.getId(), kc.toString());

                    // 使用稽查轨迹
                    Map<String, String> jcnrMap = new LinkedHashMap<>();
                    jcnrMap.put("使用量", syl + studyFormFillResource.getSyldw());

                    Map<String, String> jcnrEnMap = new LinkedHashMap<>();
                    jcnrEnMap.put("Usage Amount", syl + studyFormFillResource.getSyldw());

                    SjJcgj sjJcgj = sjJcgjService.genJcgj(sj.getId(), JcgjlxEnum.lc.getValue(), "使用", "Usage",
                            JcmcysEnum.green.getValue(), JctUtil.formatStr(jcnrMap), JctUtil.formatStr(jcnrEnMap), qmr);
                    jcgjList.add(sjJcgj);


                    // 台账
                    SjTz sjTz = sjTzService.genTz(sj.getId(), "使用", "Usage", syl, studyFormFillResource.getKcdw(), null, qmr);
                    tzList.add(sjTz);
                }
                sjMap.put(sj.getBh(), sj);
            }
        }

        // 存储
        String cclist = studyFormFill.getCclist();
        if(StringUtils.isNotEmpty(cclist) && !StringUtils.equals("[]", cclist)) {
            List<StudyFormFillCc> studyFormFillCcList = JSONUtil.toList(cclist, StudyFormFillCc.class);
            for (StudyFormFillCc studyFormFillCc : studyFormFillCcList) {
                baseMapper.updateCc(studyFormFillCc.getList(), studyFormFillCc.getCctj(), studyFormFillCc.getCcwz());
                for (String bh : studyFormFillCc.getList()) {
                    Sj sj = sjMap.get(bh);

                    // 稽查轨迹
                    LinkedHashMap<String, String> jcnrMap = new LinkedHashMap<>();
                    jcnrMap.put("存储位置", studyFormFillCc.getCcwz());
                    jcnrMap.put("存储条件", studyFormFillCc.getCctj());

                    LinkedHashMap<String, String> jcnrEnMap = new LinkedHashMap<>();
                    jcnrEnMap.put("Storage Location", studyFormFillCc.getCcwz());
                    jcnrEnMap.put("Storage Condition", studyFormFillCc.getCctj());

                    SjJcgj sjJcgj = sjJcgjService.genJcgj(sj.getId(), JcgjlxEnum.lc.getValue(), "存储", "Storage",
                            JcmcysEnum.green.getValue(), JctUtil.formatStr(jcnrMap), JctUtil.formatStr(jcnrEnMap), qmr);
                    jcgjList.add(sjJcgj);

                    // 台账
                    SjTz sjTz = sjTzService.genTz(sj.getId(), "存储", "Storage", sj.getKc(), sj.getKcdw(), null, qmr);
                    tzList.add(sjTz);
                }
            }
        }

        // 处置，库存全变为0
        String czlist = studyFormFill.getCzlist();
        if(StringUtils.isNotEmpty(czlist) && !StringUtils.equals("[]", czlist)) {
            List<StudyFormFillCz> studyFormFillCzList = JSONUtil.toList(czlist, StudyFormFillCz.class);
            for (StudyFormFillCz studyFormFillCz : studyFormFillCzList) {
                for (String bh : studyFormFillCz.getList()) {
                    Sj sj = sjMap.get(bh);

                    // 稽查轨迹
                    LinkedHashMap<String, String> jcnrMap = new LinkedHashMap<>();
                    jcnrMap.put("处置方式", studyFormFillCz.getCzfs());
                    jcnrMap.put("处置量", sj.getKc() + sj.getKcdw());

                    LinkedHashMap<String, String> jcnrEnMap = new LinkedHashMap<>();
                    jcnrEnMap.put("Dispose Method", studyFormFillCz.getCzfs());
                    jcnrEnMap.put("Amount", sj.getKc() + sj.getKcdw());

                    SjJcgj sjJcgj = sjJcgjService.genJcgj(sj.getId(), JcgjlxEnum.lc.getValue(), "处置", "Dispose",
                            JcmcysEnum.green.getValue(), JctUtil.formatStr(jcnrMap), JctUtil.formatStr(jcnrEnMap), qmr);
                    jcgjList.add(sjJcgj);


                    // 台账
                    SjTz sjTz = sjTzService.genTz(sj.getId(), "处置", "Dispose", sj.getKc(), sj.getKcdw(), null, qmr);
                    tzList.add(sjTz);
                }
                baseMapper.updateKcBatch(studyFormFillCz.getList(), "0");
            }
        }
        sjJcgjService.saveBatch(jcgjList);
        sjTzService.saveBatch(tzList);
        studySjService.saveBatch(studyId, sjList);
        System.out.println(System.currentTimeMillis());

    }

    @Override
    public void agreeGd(GspGdForm form) {
        SysUser qmr = sysUserService.selectUserById(form.getQmrId());
        sysUserService.checkPassword(qmr, form.getQmrmm(), false);
        if (form.getId() == null || form.getId().longValue() < 0) {
            throw new SecurityException("参数id不正确");
        }
        Sj sj = this.getById(form.getId());
        if (sj == null) {
            throw new SecurityException("试剂不存在或已删除");
        }
        if (!sj.getZjzt().equals(ZjztEnum.dgd.getValue())) {
            throw new SecurityException("试剂【" + sj.getMc() + "】不是待归档状态，不能操作");
        }
        sj.setZjzt(ZjztEnum.gd.getValue());
        this.updateById(sj);
        //稽查轨迹
        Map<String, String> formData = new LinkedHashMap<>();
        formData.put("备注", form.getRemark());

        Map<String, String> formDataEn = new LinkedHashMap<>();
        formDataEn.put("Comment", form.getRemark());
        sjJcgjService.saveJcgj(sj.getId(), JcgjlxEnum.lc.getValue(), "同意归档",  "Approve Archiving",
                JcmcysEnum.green.getValue(), JctUtil.formatStr(formData), JctUtil.formatStr(formDataEn));

        archiveLogService.saveInfo(ArchiveLogTypeEnum.sj, sj.getId(), sj.getMc(), sj.getBh(), sj.getNd() + sj.getNddw(), "同意归档");

        noticeService.save("试剂【"+sj.getMc()+"】同意归档",sj.getDasqrId(),getUrlQz());

    }

    @Override
    public void refuseGd(GspGdForm form) {
        SysUser qmr = sysUserService.selectUserById(form.getQmrId());
        sysUserService.checkPassword(qmr, form.getQmrmm(), false);
        if (form.getId() == null || form.getId().longValue() < 0) {
            throw new SecurityException("参数id不正确");
        }
        Sj sj = this.getById(form.getId());
        if (sj == null) {
            throw new SecurityException("试剂不存在或已删除");
        }
        if (!sj.getZjzt().equals(ZjztEnum.dgd.getValue())) {
            throw new SecurityException("试剂【" + sj.getMc() + "】不是待归档状态，不能操作");
        }
        sj.setZjzt(ZjztEnum.ysd.getValue());
        this.updateById(sj);
        //稽查轨迹
        Map<String, String> formData = new LinkedHashMap<>();
        formData.put("备注", form.getRemark());

        Map<String, String> formDataEn = new LinkedHashMap<>();
        formDataEn.put("Comment", form.getRemark());
        sjJcgjService.saveJcgj(sj.getId(), JcgjlxEnum.lc.getValue(), "拒绝归档",  "Reject Archiving",
                JcmcysEnum.green.getValue(), JctUtil.formatStr(formData), JctUtil.formatStr(formDataEn));

        archiveLogService.saveInfo(ArchiveLogTypeEnum.sj, sj.getId(), sj.getMc(), sj.getBh(), sj.getNd() + sj.getNddw(), "拒绝归档");

        noticeService.save("试剂【"+sj.getMc()+"】拒绝归档",sj.getDasqrId(),getUrlQz());

    }

    @Override
    public void agreeJd(GspGdForm form) {
        SysUser qmr = sysUserService.selectUserById(form.getQmrId());
        sysUserService.checkPassword(qmr, form.getQmrmm(), false);
        if (form.getId() == null || form.getId().longValue() < 0) {
            throw new SecurityException("参数id不正确");
        }
        Sj sj = this.getById(form.getId());
        if (sj == null) {
            throw new SecurityException("试剂不存在或已删除");
        }
        if (!sj.getZjzt().equals(ZjztEnum.djd.getValue())) {
            throw new SecurityException("试剂【" + sj.getMc() + "】不是待解档状态，不能操作");
        }
        sj.setZjzt(ZjztEnum.ysd.getValue());
        this.updateById(sj);
        //稽查轨迹
        Map<String, String> formData = new LinkedHashMap<>();
        formData.put("备注", form.getRemark());

        Map<String, String> formDataEn = new LinkedHashMap<>();
        formDataEn.put("Comment", form.getRemark());
        sjJcgjService.saveJcgj(sj.getId(), JcgjlxEnum.lc.getValue(), "同意解档",  "Approve De-archiving",
                JcmcysEnum.green.getValue(), JctUtil.formatStr(formData), JctUtil.formatStr(formDataEn));

        archiveLogService.saveInfo(ArchiveLogTypeEnum.sj, sj.getId(), sj.getMc(), sj.getBh(), sj.getNd() + sj.getNddw(), "同意解档");

        noticeService.save("试剂【"+sj.getMc()+"】同意解档",sj.getDasqrId(),getUrlQz());

    }

    @Override
    public void refuseJd(GspGdForm form) {
        SysUser qmr = sysUserService.selectUserById(form.getQmrId());
        sysUserService.checkPassword(qmr, form.getQmrmm(), false);
        if (form.getId() == null || form.getId().longValue() < 0) {
            throw new SecurityException("参数id不正确");
        }
        Sj sj = this.getById(form.getId());
        if (sj == null) {
            throw new SecurityException("试剂不存在或已删除");
        }
        if (!sj.getZjzt().equals(ZjztEnum.djd.getValue())) {
            throw new SecurityException("试剂【" + sj.getMc() + "】不是待解档状态，不能操作");
        }
        sj.setZjzt(ZjztEnum.gd.getValue());
        this.updateById(sj);
        //稽查轨迹
        Map<String, String> formData = new LinkedHashMap<>();
        formData.put("备注", form.getRemark());

        Map<String, String> formDataEn = new LinkedHashMap<>();
        formDataEn.put("Comment", form.getRemark());
        sjJcgjService.saveJcgj(sj.getId(), JcgjlxEnum.lc.getValue(), "拒绝解档",  "Reject De-archiving",
                JcmcysEnum.green.getValue(), JctUtil.formatStr(formData), JctUtil.formatStr(formDataEn));

        archiveLogService.saveInfo(ArchiveLogTypeEnum.sj, sj.getId(), sj.getMc(), sj.getBh(), sj.getNd() + sj.getNddw(), "拒绝解档");

        noticeService.save("试剂【"+sj.getMc()+"】拒绝解档",sj.getDasqrId(),getUrlQz());

    }

    @Override
    public void agreeJy(GspJyForm form) {
        SysUser qmr = sysUserService.selectUserById(form.getQmrId());
        sysUserService.checkPassword(qmr, form.getQmrmm(), false);
        if (form.getId() == null || form.getId().longValue() < 0) {
            throw new SecurityException("参数id不正确");
        }
        Sj sj = this.getById(form.getId());
        if (sj == null) {
            throw new SecurityException("试剂不存在或已删除");
        }
        if (!sj.getJyzt().equals(JyztEnum.djy.getValue())) {
            throw new SecurityException("试剂【" + sj.getMc() + "】不是待借阅状态，不能操作");
        }
        sj.setJyzt(JyztEnum.jyz.getValue());
        sj.setJyksrq(form.getStartDate());
        sj.setJyjsrq(form.getEndDate());
        this.updateById(sj);
        //稽查轨迹
        Map<String, String> formData = new LinkedHashMap<>();
        formData.put("备注", form.getRemark());

        Map<String, String> formDataEn = new LinkedHashMap<>();
        formDataEn.put("Comment", form.getRemark());
        sjJcgjService.saveJcgj(sj.getId(), JcgjlxEnum.lc.getValue(), "同意借阅",  "Approve Check-out",
                JcmcysEnum.green.getValue(), JctUtil.formatStr(formData), JctUtil.formatStr(formDataEn));

        archiveLogService.saveInfo(ArchiveLogTypeEnum.sj, sj.getId(), sj.getMc(), sj.getBh(), sj.getNd() + sj.getNddw(), "同意借阅");

        noticeService.save("试剂【"+sj.getMc()+"】同意借阅",sj.getDasqrId(),getUrlQz());

    }

    @Override
    public void refuseJy(GspJyForm form) {
        SysUser qmr = sysUserService.selectUserById(form.getQmrId());
        sysUserService.checkPassword(qmr, form.getQmrmm(), false);
        if (form.getId() == null || form.getId().longValue() < 0) {
            throw new SecurityException("参数id不正确");
        }
        Sj sj = this.getById(form.getId());
        if (sj == null) {
            throw new SecurityException("试剂不存在或已删除");
        }
        if (!sj.getJyzt().equals(JyztEnum.djy.getValue())) {
            throw new SecurityException("试剂【" + sj.getMc() + "】不是待借阅状态，不能操作");
        }
        sj.setJyzt(JyztEnum.wjy.getValue());
        this.updateById(sj);
        //稽查轨迹
        Map<String, String> formData = new LinkedHashMap<>();
        formData.put("备注", form.getRemark());

        Map<String, String> formDataEn = new LinkedHashMap<>();
        formDataEn.put("Comment", form.getRemark());
        sjJcgjService.saveJcgj(sj.getId(), JcgjlxEnum.lc.getValue(), "拒绝借阅",  "Reject Check-out",
                JcmcysEnum.green.getValue(), JctUtil.formatStr(formData), JctUtil.formatStr(formDataEn));

        archiveLogService.saveInfo(ArchiveLogTypeEnum.sj, sj.getId(), sj.getMc(), sj.getBh(), sj.getNd() + sj.getNddw(), "拒绝借阅");

        noticeService.save("试剂【"+sj.getMc()+"】拒绝借阅",sj.getDasqrId(),getUrlQz());

    }

    @Override
    public void archiveGh(GspGdForm form) {
        SysUser qmr = sysUserService.selectUserById(form.getQmrId());
        sysUserService.checkPassword(qmr, form.getQmrmm(), false);
        if (form.getId() == null || form.getId().longValue() < 0) {
            throw new SecurityException("参数id不正确");
        }
        Sj sj = this.getById(form.getId());
        if (sj == null) {
            throw new SecurityException("试剂不存在或已删除");
        }
        if (!sj.getJyzt().equals(JyztEnum.jyz.getValue())) {
            throw new SecurityException("试剂【" + sj.getMc() + "】不是借阅中状态，不能操作");
        }
        sj.setJyzt(JyztEnum.wjy.getValue());
        this.updateById(sj);
        //稽查轨迹
        Map<String, String> formData = new LinkedHashMap<>();
        formData.put("备注", form.getRemark());

        Map<String, String> formDataEn = new LinkedHashMap<>();
        formDataEn.put("Comment", form.getRemark());
        sjJcgjService.saveJcgj(sj.getId(), JcgjlxEnum.lc.getValue(), "确认归还",  "Check-out End Confirmation",
                JcmcysEnum.green.getValue(), JctUtil.formatStr(formData), JctUtil.formatStr(formDataEn));

        archiveLogService.saveInfo(ArchiveLogTypeEnum.sj, sj.getId(), sj.getMc(), sj.getBh(), sj.getNd() + sj.getNddw(), "确认归还");

    }

    /**
     * 获取通知的跳转url
     * @return
     */
    private String getUrlQz(){
        return  "/resource/reagent";
    }
}
