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.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.ExportImportDrugErrDTO;
import com.lantone.daqe.dto.GetDrugByIdDTO;
import com.lantone.daqe.dto.GetDrugPageDTO;
import com.lantone.daqe.dto.GetMatchingDrugPageDTO;
import com.lantone.daqe.entity.DrugInfo;
import com.lantone.daqe.facade.base.DrugInfoFacade;
import com.lantone.daqe.service.impl.DrugInfoServiceImpl;
import com.lantone.daqe.util.ExcelUtils;
import com.lantone.daqe.vo.AddDrugVO;
import com.lantone.daqe.vo.DelDrugByIdVO;
import com.lantone.daqe.vo.GetDrugByIdVO;
import com.lantone.daqe.vo.GetDrugPageVO;
import com.lantone.daqe.vo.GetMatchingDrugPageVO;
import com.lantone.daqe.vo.ImportDrugVO;
import com.lantone.daqe.vo.MatchingDrugVO;
import com.lantone.daqe.vo.UpDrugByIdVO;
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 DrugManagementFacade {

    @Autowired
    private DrugInfoFacade drugInfoFacade;

    @Autowired
    private DrugInfoServiceImpl drugInfoServiceImpl;
    //医院药品名称长度
    private int drugNameLength = 30;
    //国药准字长度
    private int approvalNumLength = 30;

    public IPage<GetDrugPageDTO> getDrugPage(GetDrugPageVO getDrugPageVO) {
        Page<GetDrugPageDTO> getDrugPageDTOPage = new Page<>();

        QueryWrapper<DrugInfo> drugInfoQueryWrapper = new QueryWrapper<>();
        drugInfoQueryWrapper.eq(getDrugPageVO.getHospitalId() != null, "hospital_id", getDrugPageVO.getHospitalId());
        drugInfoQueryWrapper.like(StringUtil.isNotBlank(getDrugPageVO.getCode()), "code", getDrugPageVO.getCode());
        drugInfoQueryWrapper.like(StringUtil.isNotBlank(getDrugPageVO.getName()), "name", getDrugPageVO.getName());
        drugInfoQueryWrapper.like(StringUtil.isNotBlank(getDrugPageVO.getApprovalNum()), "approval_num", getDrugPageVO.getApprovalNum());
        drugInfoQueryWrapper.like(StringUtil.isNotBlank(getDrugPageVO.getStandard()), "standard", getDrugPageVO.getStandard());
        drugInfoQueryWrapper.like(StringUtil.isNotBlank(getDrugPageVO.getDosageForm()), "standard", getDrugPageVO.getDosageForm());
        if (StringUtil.isNotBlank(getDrugPageVO.getIsMapping())) {
            if (getDrugPageVO.getIsMapping().equals("0")) {
                drugInfoQueryWrapper.isNull("standard");
            } else if (getDrugPageVO.getIsMapping().equals("1")) {
                drugInfoQueryWrapper.isNotNull("standard");
            }
        }
        Page<DrugInfo> drugInfoPage = new Page<>(getDrugPageVO.getCurrent(), getDrugPageVO.getSize());
        drugInfoFacade.page(drugInfoPage, drugInfoQueryWrapper);
        BeanUtil.copyProperties(drugInfoPage, getDrugPageDTOPage);
        List<GetDrugPageDTO> getDrugPageDTOList = BeanUtil.listCopyTo(drugInfoPage.getRecords(), GetDrugPageDTO.class);
        getDrugPageDTOList.forEach(i -> {
            i.setIsMapping(StringUtil.isBlank(i.getStandard()) ? "未匹配" : "已匹配");
        });

        getDrugPageDTOPage.setRecords(getDrugPageDTOList);
        return getDrugPageDTOPage;
    }

    /**
     * 新增药品 业务处理
     *
     * @param addDrugVO
     * @return 是否新增成功
     */
    public boolean addDrug(AddDrugVO addDrugVO) {
        DrugInfo drugInfo = new DrugInfo();
        BeanUtil.copyProperties(addDrugVO, drugInfo);
        drugInfoFacade.assertIsExist(drugInfo);
        String currentUserId = SysUserUtils.getCurrentPrincipleIdStr();
        Date now = DateUtil.now();
        drugInfo.setCreator(currentUserId);
        drugInfo.setGmtCreate(now);
        drugInfo.setModifier(currentUserId);
        drugInfo.setGmtModified(now);
        return drugInfoFacade.save(drugInfo);
    }

    /**
     * 通过id修改药品
     *
     * @param upDrugByIdVO
     * @return 是否修改成功
     */
    public Boolean upDrugById(UpDrugByIdVO upDrugByIdVO) {
        if (drugInfoFacade.getById(upDrugByIdVO.getId()) == null) {
            Asserts.fail("该药品已被删除！");
        }
        DrugInfo drugInfo = new DrugInfo();
        BeanUtil.copyProperties(upDrugByIdVO, drugInfo);
        drugInfoFacade.assertIsExist(drugInfo);
        drugInfo.setModifier(SysUserUtils.getCurrentPrincipleIdStr());
        drugInfo.setGmtModified(DateUtil.now());
        return drugInfoFacade.updateById(drugInfo);
    }

    /**
     * 通过id删除药品
     *
     * @param delDrugByIdVO
     * @return 是否删除成功
     */
    public Boolean delDrugById(DelDrugByIdVO delDrugByIdVO) {
        return drugInfoFacade.removeByIds(delDrugByIdVO.getIds());
    }

    /**
     * 匹配药品信息
     *
     * @param matchingDrugVO
     * @Return java.lang.Boolean
     */
    public Boolean matchingDrug(MatchingDrugVO matchingDrugVO) {

        DrugInfo drugInfo = new DrugInfo();
        BeanUtils.copyProperties(matchingDrugVO, drugInfo);
        drugInfo.setStandard(matchingDrugVO.getStandard() + "_" + matchingDrugVO.getDosageForm());
        drugInfo.setModifier(SysUserUtils.getCurrentPrinciple() == null ? "0" : SysUserUtils.getCurrentPrinciple());
        drugInfo.setGmtModified(DateUtil.now());
        return drugInfoFacade.updateById(drugInfo);
    }

    /**
     * 药品匹配信息导入
     *
     * @param response
     * @param file
     * @Return void
     */
    public void importDrug(HttpServletResponse response, MultipartFile file) {

        List<ImportDrugVO> operationExcelVOS = ExcelUtils.importExcel(file, 0, 1, ImportDrugVO.class);
        if (ListUtil.isEmpty(operationExcelVOS)) {
            Asserts.fail("Excel文件为空");
        }
        Long hospitalId = SysUserUtils.getCurrentHospitalId();
        //数据规范校验
        List<ExportImportDrugErrDTO> errExports = new ArrayList<>();
        if (checkData(operationExcelVOS, errExports, hospitalId)) {
            String fileName = "药品匹配信息导入异常.xls";
            ExcelUtils.exportExcelUser(errExports, null, "sheet1", ExportImportDrugErrDTO.class, fileName, response);
        } else {
            //去重
            List<ImportDrugVO> temp = delRepeat(operationExcelVOS);
            //导入数据转换
            temp.stream().forEach(importDrugVO -> {
                DrugInfo drugInfo = new DrugInfo();
                BeanUtils.copyProperties(importDrugVO, drugInfo);
                drugInfo.setStandard(importDrugVO.getStandard() + "_" + importDrugVO.getDosageForm());
            });
            List<DrugInfo> insert = BeanUtil.listCopyTo(temp, DrugInfo.class);
            insert.stream().forEach(drugInfo -> {
                drugInfo.setHospitalId(hospitalId != null ? hospitalId : 0);
                drugInfo.setGmtCreate(DateUtil.now());
                drugInfo.setCreator(SysUserUtils.getCurrentPrincipleId() != null ? SysUserUtils.getCurrentPrincipleId() + "" : "0");
                drugInfo.setGmtModified(DateUtil.now());
            });
            boolean out = drugInfoServiceImpl.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 importDrugVOS 导入数据
     * @param errExports    导出异常
     * @Return java.lang.Boolean
     */
    private Boolean checkData(List<ImportDrugVO> importDrugVOS, List<ExportImportDrugErrDTO> errExports, Long hospitalId) {
        AtomicBoolean errorFlog = new AtomicBoolean(false);
        //获取数据库数据 判断医院药品名称和医院药品代码用于重复校验
        //        List<DrugInfo> drugInfos = drugInfoFacade.list(new QueryWrapper<DrugInfo>()
        //                .eq("hospital_id", hospitalId)
        //                .eq("is_deleted", IsDeleteEnum.N.getKey()));
        //        List<String> names = drugInfos.stream().map(DrugInfo::getName).collect(Collectors.toList());
        //        List<String> codes = drugInfos.stream().map(DrugInfo::getCode).collect(Collectors.toList());

        importDrugVOS.stream().forEach(importDrugVO -> {
            ExportImportDrugErrDTO exportImportDrugErrDTO = new ExportImportDrugErrDTO();
            BeanUtil.copyProperties(importDrugVO, exportImportDrugErrDTO);
            StringBuffer errMsg = new StringBuffer();
            //数据校验(非空和过长、库中已存在)
            //name
            if (StringUtil.isEmpty(importDrugVO.getName())) {
                errMsg.append("【医院药品名称】未填写").append(";");
                errorFlog.set(true);
            } else if (importDrugVO.getName().length() > drugNameLength) {
                errMsg.append("【医院诊断名称】过长").append(";");
                errorFlog.set(true);
            }

            //approvalNum
            if (StringUtil.isNotEmpty(importDrugVO.getApprovalNum())) {
                if (importDrugVO.getApprovalNum().length() > approvalNumLength) {
                    errMsg.append("【国药准字】过长").append(";");
                    errorFlog.set(true);
                }
            }
            exportImportDrugErrDTO.setErrMsg(errMsg.toString());
            errExports.add(exportImportDrugErrDTO);
        });
        return errorFlog.get();
    }

    /**
     * 去重
     *
     * @param importDrugVOS
     * @Return java.util.List<com.lantone.daqe.vo.ImportDrugVO>
     */
    private List<ImportDrugVO> delRepeat(List<ImportDrugVO> importDrugVOS) {

        //通过标准词去重
        LinkedHashMap<String, ImportDrugVO> tempMap = importDrugVOS.stream()
                .collect(Collectors.toMap(ImportDrugVO::getName, ImportDrugVO -> ImportDrugVO, (k1, k2) -> k1, LinkedHashMap::new));
        return tempMap.values().stream().collect(Collectors.toList());
    }

    /**
     * 获取药品匹配分页列表
     *
     * @param getMatchingDrugPageVO
     * @Return com.baomidou.mybatisplus.core.metadata.IPage<com.lantone.daqe.dto.GetMatchingDrugPageDTO>
     */
    public IPage<GetMatchingDrugPageDTO> getMatchingDrugPage(GetMatchingDrugPageVO getMatchingDrugPageVO) {

        List<GetMatchingDrugPageDTO> getMatchingDrugPageDTOList = new ArrayList<>();
        //数据整理组装
        IPage<GetMatchingDrugPageDTO> drugPages = drugInfoServiceImpl.getBaseMapper().getMatchingDrugPage(getMatchingDrugPageVO);
        for (GetMatchingDrugPageDTO drug : drugPages.getRecords()) {
            //目前先按照_切割
            drug.setDosageForm(drug.getStandard().split("_")[1]);
            getMatchingDrugPageDTOList.add(drug);
        }
        return drugPages.setRecords(getMatchingDrugPageDTOList);
    }

    /**
     * 已匹配药品信息查看
     *
     * @param getDrugByIdVO
     * @Return com.lantone.daqe.dto.GetDrugByIdDTO
     */
    public GetDrugByIdDTO getDrugById(GetDrugByIdVO getDrugByIdVO) {
        GetDrugByIdDTO out = new GetDrugByIdDTO();
        BeanUtil.copyProperties(drugInfoFacade.getById(getDrugByIdVO.getId()), out);
        //目前先按照_切割
        out.setDosageForm(out.getStandard().split("_")[1]);
        out.setIsMapping(StringUtil.isBlank(out.getStandard()) ? "未匹配" : "已匹配");
        return out;
    }
}