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

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import digital.laboratory.platform.common.core.constant.CommonConstants;
import digital.laboratory.platform.common.core.util.R;
import digital.laboratory.platform.common.feign.RemoteTemplate2htmlService;
import digital.laboratory.platform.entrustment.entity.*;
import digital.laboratory.platform.entrustment.handler.AppStartupRunner;
import digital.laboratory.platform.entrustment.mapper.SampleBoxMapper;
import digital.laboratory.platform.entrustment.service.*;
import digital.laboratory.platform.entrustment.vo.SampleBoxLiteVO;
import digital.laboratory.platform.entrustment.vo.SampleBoxVO;
import digital.laboratory.platform.sys.entity.entrustment.Sample;
import digital.laboratory.platform.sys.entity.entrustment.SampleBox;
import digital.laboratory.platform.sys.feign.RemoteSampleService;
import digital.laboratory.platform.sys.feign.RemoteUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 受理时检材重新包装的容器服务实现类
 *
 * @author Zhang Xiaolong created at  2022-07-06
 * @describe 受理时检材重新包装的容器服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SampleBoxServiceImpl extends ServiceImpl<SampleBoxMapper, SampleBox> implements SampleBoxService {
    private final EntrustmentIdentificationMaterialService entrustmentIdentificationMaterialService;
    private final SampleService sampleService;

    private final RemoteTemplate2htmlService remoteTemplate2htmlService;

    private final EntrustmentService entrustmentService;
    private final CaseEventService caseEventService;

    private final RemoteSampleService remoteSampleService;

    private final RemoteUserService remoteUserService;

    /**
     * ## 根据委托编码生成样本盒编码
     * 用于标识每一个样本盒。一个委托最多可以有99个样本盒子
     * <p>
     * ```
     * BZ <委托编码去掉前缀2个字符后剩下22位> <顺序号2位>
     * 例如:
     * BZ 6101022022100002000001 02
     * 合计 26 位
     * ```
     *
     * @param entrustmentNo
     * @return
     */
    @Override
    public String getNewBoxNoForEntrustment(String entrustmentNo) {
        String prefix = CommonConstants.CODE_PREFIX_SAMPLE_BOX + "E" + StrUtil.removePrefixIgnoreCase(entrustmentNo, CommonConstants.CODE_PREFIX_ENTRUSTMENT);

        int newCount = 1;

        // 根据前缀查询最大物证编码
        String maxno = baseMapper.getMaxBoxNo(prefix);
        if (maxno != null) {
            String strCount = StrUtil.removePrefix(maxno, prefix);
            try {
                int maxcount = Integer.parseUnsignedInt(strCount);
                newCount = maxcount + 1;
            } catch (NumberFormatException e) {
                // 如果后缀有非数字, 则无视之, 重头编码
                newCount = 1;
            }
        }

        String newCode = prefix + String.format("%02d", newCount);

        return newCode;
    }

    /**
     * ## 根据污水任务编码生成样本盒编码
     * 用于标识每一个样本盒。一个委托最多可以有9999个样本盒子
     * <p>
     * ```
     * BZ <污水任务编码去掉前缀2个字符后剩下7位> <顺序号4位>
     * 例如:
     * BZ 2022201 0002
     * 合计 13 位
     * ```
     *
     * @param sewageJobNo
     * @return
     */
    @Override
    public String getNewBoxNoForSewageJob(String sewageJobNo) {
        String prefix = CommonConstants.CODE_PREFIX_SAMPLE_BOX + "S" + StrUtil.removePrefixIgnoreCase(sewageJobNo, CommonConstants.CODE_PREFIX_SEWAGE_JOB);

        List<SampleBox> list = this.list(Wrappers.<SampleBox>query()
                .likeRight("box_no", prefix)        // LIKE '值%'
                .orderByDesc("box_no")
        );

        int newNo = 1;
        if ((list != null) && (list.size() > 0)) {
            SampleBox sjimMax = list.get(0);
            String strMaxNo = StrUtil.removePrefixIgnoreCase(sjimMax.getBoxNo(), prefix);
            try {
                int maxno = Integer.parseUnsignedInt(strMaxNo);
                newNo = maxno + 1;
            } catch (NumberFormatException e) {
                // 如果后缀有非数字, 则无视之, 重头编码
                newNo = 1;
            }
        }

        String newCode = prefix + String.format("%04d", newNo);

        return newCode;
    }

    @Override
    public String getNewBoxNoForOther(String newBoxNumber) {

        String prefix = CommonConstants.CODE_PREFIX_SAMPLE_BOX + newBoxNumber;

        List<SampleBox> list = this.list(Wrappers.<SampleBox>query()
                .likeRight("box_no", prefix)        // LIKE '值%'
                .orderByDesc("box_no")
        );

        int newNo = 1;
        if ((list != null) && (list.size() > 0)) {
            SampleBox sjimMax = list.get(0);
            String strMaxNo = StrUtil.removePrefixIgnoreCase(sjimMax.getBoxNo(), prefix);
            try {
                int maxno = Integer.parseUnsignedInt(strMaxNo);
                newNo = maxno + 1;
            } catch (NumberFormatException e) {
                // 如果后缀有非数字, 则无视之, 重头编码
                newNo = 1;
            }
        }

        String newCode = prefix + String.format("%04d", newNo);

        return newCode;

    }

    @Override
    public SampleBoxLiteVO getSampleBoxLiteVOById(String id) {
        SampleBox sb = this.getById(id);
        List<EntrustmentIdentificationMaterial> imlist = entrustmentIdentificationMaterialService.list(Wrappers.<EntrustmentIdentificationMaterial>query().eq("entrustment_id", sb.getEntrustmentId()));
        List<String> nolist = new ArrayList<String>();
        for (EntrustmentIdentificationMaterial im : imlist) {
            if (StrUtil.equalsIgnoreCase(im.getSample1BoxId(), sb.getId())) {
                nolist.add(im.getSample1No());
            }
            if (StrUtil.equalsIgnoreCase(im.getSample2BoxId(), sb.getId())) {
                nolist.add(im.getSample2No());
            }
        }
        SampleBoxLiteVO sv = new SampleBoxLiteVO(sb, nolist);

        return sv;
    }

    @Override
    public SampleBoxVO getSampleBoxVOById(String id) {
        SampleBox sb = this.getById(id);
        List<Sample> sampleList = sampleService.list(Wrappers.<Sample>query().eq("box_id", sb.getId()));
        SampleBoxVO sv = new SampleBoxVO(sb, sampleList);

        return sv;
    }

    @Override
    public String buildSampleBoxLabelContent(String id) throws Exception {
        SampleBox sampleBoxBean = this.getById(id);
        Map<String, Object> data = new HashMap<>();
        data.put("sampleBoxBean", sampleBoxBean);
        String templateFileName = AppStartupRunner.getCfg(CommonConstants.DLP_CODE_SAMPLE_BOX_LABEL);
        return remoteTemplate2htmlService.getHtml(templateFileName, data);
    }

    @Override
    public List<SampleBoxVO> getSampleBoxList(SampleBox sampleBox) {
        List<SampleBoxVO> list = new ArrayList<>();
        List<Sample> sampleList = new ArrayList<>();
        List<SampleBox> sampleBoxList = this.list(Wrappers.<SampleBox>query().eq("entrustment_id", sampleBox.getEntrustmentId()));

        sampleBoxList.forEach(item -> {
            int sampleCount = entrustmentIdentificationMaterialService.list(Wrappers.<EntrustmentIdentificationMaterial>query()
                    .eq("sample1_box_id", item.getId())
                    .or()
                    .eq("sample2_box_id", item.getId())).size();
            SampleBoxVO eg = new SampleBoxVO(item, sampleList);
            eg.setBoxSampleCount(sampleCount);
            list.add(eg);
        });
        return list;
    }

    @Override
    public String printBoxLabel(String id, Integer type) {
        SampleBox sampleBox = this.getById(id);
        if (!ObjUtil.isNotNull(sampleBox)) {
            throw new RuntimeException(String.format("没有查询到ID为%s的包装盒", id));
        }
        List<EntrustmentIdentificationMaterial> materialList = entrustmentIdentificationMaterialService.list(new LambdaQueryWrapper<EntrustmentIdentificationMaterial>()
                .eq(EntrustmentIdentificationMaterial::getSample1BoxId, id)
                .or()
                .eq(EntrustmentIdentificationMaterial::getSample2BoxId, id));

        if (materialList == null || materialList.size() == 0) {

            throw new RuntimeException(String.format("当前包装袋下并未加入检材，无法进行打印！"));
        }
        String acceptNo = materialList.get(0).getAcceptNo();
        String substring = acceptNo.substring(0, 9);
        Map<String, Object> data = new HashMap<>();
        Entrustment entrustment = entrustmentService.getById(sampleBox.getEntrustmentId());
        CaseEvent caseEvent = caseEventService.getById(materialList.get(0).getCaseId());
        data.put("sampleBox", sampleBox);
        data.put("acceptNo", substring);
        data.put("materialQuantity", materialList.size());
        data.put("caseEvent", caseEvent);
        data.put("entrustment", entrustment);
        String templateFileName = "";
        if (type == 0) {
            templateFileName = "(小)受理时打印的包装袋条码模板.vm";
        } else {
            templateFileName = "(大)受理时打印的包装袋条码模板.vm";
        }
        return remoteTemplate2htmlService.getHtml(templateFileName, data);
    }

    @Override
    public SampleBox controlsSampleBox(SampleBox sampleBox, Integer opCode) {
        //删除这个包装袋
        if (opCode == -1) {
            if (!StrUtil.isNotBlank(sampleBox.getId())) {
                throw new RuntimeException(String.format("没有找到ID为%s的包装袋", sampleBox.getId()));
            }
            R<List<String>> data = remoteSampleService.getSampleIdForBox(sampleBox.getId());
            List<String> stringList = data.getData();
            if (stringList!=null&&stringList.size()>0){
                throw new RuntimeException(String.format("这个包装袋下还有检材未被移除，无法删除！"));
            }
            this.removeById(sampleBox.getId());
        } else {
            //存在ID，修改这个包装袋
            if (StrUtil.isNotBlank(sampleBox.getId())) {
                this.updateById(sampleBox);
            }
            //没有ID，则需要创建一个包装袋
            else {
                sampleBox.setBoxNo(this.getNewBoxNoForOther(sampleBox.getBoxNo()));
                sampleBox.setId(this.getOrderIdBy16UUId());
                this.save(sampleBox);
            }
        }
        return sampleBox;
    }

    //其他系统打印包装袋条码
    @Override
    public String printLabelForOther(String boxId, Integer type) {

        SampleBox sampleBox = this.getById(boxId);

        if (sampleBox==null){
            throw new RuntimeException(String.format("没有查询到ID为%s的包装袋", boxId));
        }

        String source = "";

        switch (sampleBox.getSource()) {
            case "hairJob":
                source = "毛发任务";
                break;
            case "identificationMaterialAcceptance":
                source = "事件受理";
                break;
            case "featureAnalysis":
                source = "特征分析";
                break;
        }
        Map<String, Object> map = new HashMap<>();
        map.put("sampleBox", sampleBox);
        map.put("createTime", LocalDateTimeUtil.format(sampleBox.getCreateTime(), "yyyy-MM-dd"));
        map.put("materialQuantity", remoteSampleService.getSampleIdForBox(boxId).getData().size());
        map.put("userName", remoteUserService.innerGetById(sampleBox.getCreateBy()).getData().getName());
        map.put("source", source);

        String templateFileName = "";
        if (type == 0) {
            templateFileName = "(小)包装袋条码.vm";
        } else {
            templateFileName = "(大)包装袋条码.vm";
        }
        return remoteTemplate2htmlService.getHtml(templateFileName, map);
    }

    @Override
    public  String getOrderIdBy16UUId(){
        int hashCodeV = UUID.randomUUID().toString().hashCode();
        if(hashCodeV < 0) {//有可能是负数
            hashCodeV = - hashCodeV;
        }
        return String.format("%016d", hashCodeV);
    }
}
