package com.lantone.daqe.facade;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lantone.common.api.CommonResult;
import com.lantone.common.enums.IsDeleteEnum;
import com.lantone.common.exception.Asserts;
import com.lantone.common.util.BeanUtil;
import com.lantone.common.util.DateUtil;
import com.lantone.common.util.ListUtil;
import com.lantone.common.util.StringUtil;
import com.lantone.common.util.SysUserUtils;
import com.lantone.daqe.dto.ExportImportDiseaseErrDTO;
import com.lantone.daqe.dto.GetDiseaseInfoByIdDTO;
import com.lantone.daqe.dto.GetDiseasePageDTO;
import com.lantone.daqe.dto.GetMatchingDiseasePageDTO;
import com.lantone.daqe.entity.DiseaseInfo;
import com.lantone.daqe.facade.base.DiseaseInfoFacade;
import com.lantone.daqe.service.impl.DiseaseInfoServiceImpl;
import com.lantone.daqe.util.ExcelUtils;
import com.lantone.daqe.vo.AddDiseaseVO;
import com.lantone.daqe.vo.DelDiseaseByIdVO;
import com.lantone.daqe.vo.GetDiseaseInfoByIdVO;
import com.lantone.daqe.vo.GetDiseasePageVO;
import com.lantone.daqe.vo.GetMatchingDiseasePageVO;
import com.lantone.daqe.vo.ImportDiseaseVO;
import com.lantone.daqe.vo.MatchingDiseaseVO;
import com.lantone.daqe.vo.UpDiseaseByIdVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * @Description: 诊断管理-业务处理类
 * @author: rengb
 * @time: 2021/7/20 12:39
 */
@Component
public class DiseaseManagementFacade {

    @Autowired
    private DiseaseInfoFacade diseaseInfoFacade;
    @Autowired
    private DiseaseInfoServiceImpl diseaseInfoServiceImpl;

    //医院诊断名称长度限制
    private int diseaseNameLength = 30;
    //ICD-10编码长度限制
    private int icd10Length = 30;

    public IPage<GetDiseasePageDTO> getDiseasePage(GetDiseasePageVO getDiseasePageVO) {
        Page<GetDiseasePageDTO> getDiseasePageDTOPage = new Page<>();

        QueryWrapper<DiseaseInfo> diseaseInfoQueryWrapper = new QueryWrapper<>();
        diseaseInfoQueryWrapper.eq(getDiseasePageVO.getHospitalId() != null, "hospital_id", getDiseasePageVO.getHospitalId());
        diseaseInfoQueryWrapper.like(StringUtil.isNotBlank(getDiseasePageVO.getName()), "name", getDiseasePageVO.getName());
        diseaseInfoQueryWrapper.like(StringUtil.isNotBlank(getDiseasePageVO.getStandard()), "standard", getDiseasePageVO.getStandard());
        diseaseInfoQueryWrapper.like(StringUtil.isNotBlank(getDiseasePageVO.getIcd10()), "icd10", getDiseasePageVO.getIcd10());
        if (StringUtil.isNotBlank(getDiseasePageVO.getIsMapping())) {
            if (getDiseasePageVO.getIsMapping().equals("0")) {
                diseaseInfoQueryWrapper.isNull("standard");
            } else if (getDiseasePageVO.getIsMapping().equals("1")) {
                diseaseInfoQueryWrapper.isNotNull("standard");
            }
        }
        Page<DiseaseInfo> diseaseInfoPage = new Page<>(getDiseasePageVO.getCurrent(), getDiseasePageVO.getSize());
        diseaseInfoFacade.page(diseaseInfoPage, diseaseInfoQueryWrapper);
        BeanUtil.copyProperties(diseaseInfoPage, getDiseasePageDTOPage);
        List<GetDiseasePageDTO> getDiseasePageDTOList = BeanUtil.listCopyTo(diseaseInfoPage.getRecords(), GetDiseasePageDTO.class);
        getDiseasePageDTOList.forEach(i -> {
            i.setIsMapping(StringUtil.isBlank(i.getStandard()) ? "未匹配" : "已匹配");
        });

        getDiseasePageDTOPage.setRecords(getDiseasePageDTOList);
        return getDiseasePageDTOPage;
    }

    /**
     * 新增诊断 业务处理
     *
     * @param addDiseaseVO
     * @return 是否新增成功
     */
    public Boolean addDisease(AddDiseaseVO addDiseaseVO) {
        DiseaseInfo diseaseInfo = new DiseaseInfo();
        BeanUtil.copyProperties(addDiseaseVO, diseaseInfo);
        diseaseInfoFacade.assertIsExist(diseaseInfo);
        String currentUserId = SysUserUtils.getCurrentPrincipleIdStr();
        Date now = DateUtil.now();
        diseaseInfo.setCreator(currentUserId);
        diseaseInfo.setGmtCreate(now);
        diseaseInfo.setModifier(currentUserId);
        diseaseInfo.setGmtModified(now);
        return diseaseInfoFacade.save(diseaseInfo);
    }

    /**
     * 通过id修改诊断
     *
     * @param upDiseaseByIdVO
     * @return 是否修改成功
     */
    public Boolean upDiseaseById(UpDiseaseByIdVO upDiseaseByIdVO) {
        if (diseaseInfoFacade.getById(upDiseaseByIdVO.getId()) == null) {
            Asserts.fail("该诊断已被删除！");
        }
        DiseaseInfo diseaseInfo = new DiseaseInfo();
        BeanUtil.copyProperties(upDiseaseByIdVO, diseaseInfo);
        diseaseInfoFacade.assertIsExist(diseaseInfo);
        diseaseInfo.setModifier(SysUserUtils.getCurrentPrincipleIdStr());
        diseaseInfo.setGmtModified(DateUtil.now());
        return diseaseInfoFacade.updateById(diseaseInfo);
    }

    /**
     * 通过id删除诊断
     *
     * @param delDiseaseByIdVO
     * @return 是否删除成功
     */
    public Boolean delDiseaseById(DelDiseaseByIdVO delDiseaseByIdVO) {
        return diseaseInfoFacade.removeByIds(delDiseaseByIdVO.getIds());
    }

    /**
     * 匹配诊断
     *
     * @param matchingDiseaseVO
     * @Return java.lang.Boolean
     */
    public Boolean matchingDisease(MatchingDiseaseVO matchingDiseaseVO) {

        DiseaseInfo diseaseInfo = new DiseaseInfo();
        BeanUtils.copyProperties(matchingDiseaseVO, diseaseInfo);
        diseaseInfo.setModifier(SysUserUtils.getCurrentPrinciple() == null ? "0" : SysUserUtils.getCurrentPrinciple());
        diseaseInfo.setGmtModified(DateUtil.now());
        return diseaseInfoFacade.updateById(diseaseInfo);
    }

    /**
     * 医院诊断标准词匹配信息导入
     *
     * @param file 导入文件
     * @Return java.lang.String
     */
    public void importDisease(HttpServletResponse response, MultipartFile file) {
        List<ImportDiseaseVO> diagnoseExcelVOS = ExcelUtils.importExcel(file, 0, 1, ImportDiseaseVO.class);
        if (ListUtil.isEmpty(diagnoseExcelVOS)) {
            Asserts.fail("Excel文件为空");
        }
        Long hospitalId = SysUserUtils.getCurrentHospitalId();
        //数据规范校验
        List<ExportImportDiseaseErrDTO> errExports = new ArrayList<>();
        if (checkData(diagnoseExcelVOS, errExports, hospitalId)) {
            String fileName = "诊断标准词匹配信息导入异常.xls";
            ExcelUtils.exportExcelUser(errExports, null, "sheet1", ExportImportDiseaseErrDTO.class, fileName, response);
        } else {
            //去重
            List<ImportDiseaseVO> temp = delRepeat(diagnoseExcelVOS);
            //导入
            List<DiseaseInfo> insert = BeanUtil.listCopyTo(temp, DiseaseInfo.class);
            //拼装 医院id、创建时间、更新时间
            insert.stream().forEach(diseaseInfo -> {
                diseaseInfo.setHospitalId(hospitalId != null ? hospitalId : 0);
                diseaseInfo.setGmtCreate(DateUtil.now());
                diseaseInfo.setCreator(SysUserUtils.getCurrentPrincipleId() != null ? SysUserUtils.getCurrentPrincipleId() + "" : "0");
                diseaseInfo.setGmtModified(DateUtil.now());
            });
            boolean out = diseaseInfoServiceImpl.saveBatch(insert);
            CommonResult<String> outMsg = null;
            response.setContentType("text/html;charset=utf-8");
            if (out) {
                outMsg = CommonResult.success(String.format("模板成功导入%s条数据", insert.size()));
                try {
                    response.getWriter().println(JSONObject.toJSONString(outMsg));
                    response.flushBuffer();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                Asserts.fail("数据插入失败");
            }
        }

    }

    /**
     * 数据校验
     *
     * @param diagnoseExcelVOS 导入数据
     * @param errExports       导出异常
     * @Return java.lang.Boolean
     */
    private Boolean checkData(List<ImportDiseaseVO> diagnoseExcelVOS, List<ExportImportDiseaseErrDTO> errExports, Long hospitalId) {
        AtomicBoolean errorFlog = new AtomicBoolean(false);
        //获取数据库数据 判断医院诊断名称和ICD-10编码值用于重复校验
        List<DiseaseInfo> diseaseInfos = diseaseInfoFacade.list(new QueryWrapper<DiseaseInfo>()
                .eq(hospitalId != null, "hospital_id", hospitalId)
                .eq("is_deleted", IsDeleteEnum.N.getKey()));
        List<String> diseaseNames = diseaseInfos.stream().map(DiseaseInfo::getName).collect(Collectors.toList());
        List<String> icd10s = diseaseInfos.stream().map(DiseaseInfo::getIcd10).collect(Collectors.toList());
        diagnoseExcelVOS.stream().forEach(importDiseaseVO -> {
            ExportImportDiseaseErrDTO exportImportDiseaseErrDTO = new ExportImportDiseaseErrDTO();
            BeanUtil.copyProperties(importDiseaseVO, exportImportDiseaseErrDTO);
            StringBuffer errMsg = new StringBuffer();
            //数据校验(非空和过长、库中已存在)
            //name
            if (StringUtil.isEmpty(importDiseaseVO.getName())) {
                errMsg.append("【医院诊断名称】未填写").append(";");
                errorFlog.set(true);
            } else if (importDiseaseVO.getName().length() > diseaseNameLength) {
                errMsg.append("【医院诊断名称】过长").append(";");
                errorFlog.set(true);
            } else if (diseaseNames.contains(importDiseaseVO.getName())) {
                errMsg.append("该诊断已存在，无法重复导入。").append(";");
                errorFlog.set(true);
            }

            //icd10
            if (StringUtil.isNotEmpty(importDiseaseVO.getIcd10())) {
                if (importDiseaseVO.getIcd10().length() > icd10Length) {
                    errMsg.append("【ICD-10编码】过长").append(";");
                    errorFlog.set(true);
                } else if (icd10s.contains(importDiseaseVO.getIcd10())) {
                    errMsg.append("该ICD-10编码已存在，无法重复导入。").append(";");
                    errorFlog.set(true);
                }
            }
            exportImportDiseaseErrDTO.setErrMsg(errMsg.toString());
            errExports.add(exportImportDiseaseErrDTO);

        });
        return errorFlog.get();
    }

    /**
     * 通过医院诊断名称去重
     *
     * @param diagnoseExcelVOS
     * @Return java.util.List<com.lantone.daqe.vo.ImportDiseaseVO>
     */
    private List<ImportDiseaseVO> delRepeat(List<ImportDiseaseVO> diagnoseExcelVOS) {

        //通过医院诊断名称去重
        LinkedHashMap<String, ImportDiseaseVO> tempMap = diagnoseExcelVOS.stream()
                .collect(Collectors.toMap(ImportDiseaseVO::getName, ImportDiseaseVO -> ImportDiseaseVO, (k1, k2) -> k1, LinkedHashMap::new));
        return tempMap.values().stream().collect(Collectors.toList());
    }

    /**
     * 匹配诊断信息列表
     *
     * @param getMatchingDiseasePageVO
     * @Return com.baomidou.mybatisplus.core.metadata.IPage<com.lantone.daqe.dto.GetMatchingDiseasePageDTO>
     */
    public IPage<GetMatchingDiseasePageDTO> getMatchingDiseasePage(GetMatchingDiseasePageVO getMatchingDiseasePageVO) {

        return diseaseInfoFacade.getBaseMapper().getMatchingDiseasePage(getMatchingDiseasePageVO);
    }

    /**
     * 已匹配信息查看
     *
     * @param getDiseaseInfoByIdVO
     * @Return com.lantone.daqe.dto.GetDiseaseInfoByIdDTO
     */
    public GetDiseaseInfoByIdDTO getDiseaseInfoById(GetDiseaseInfoByIdVO getDiseaseInfoByIdVO) {
        GetDiseaseInfoByIdDTO out = new GetDiseaseInfoByIdDTO();
        BeanUtils.copyProperties(diseaseInfoFacade.getById(getDiseaseInfoByIdVO.getId()), out);
        out.setIsMapping(StringUtil.isBlank(out.getStandard()) ? "未匹配" : "已匹配");
        return out;
    }
}