package cn.common.service.impl;

import cn.common.common.constants.BaseConstant;
import cn.common.common.enums.ErrorCode;
import cn.common.common.utils.ValidationUtil;
import cn.common.common.utils.collection.CollectionUtils;
import cn.common.common.utils.common.BaseUtil;
import cn.common.common.utils.common.CheckParam;
import cn.common.common.exception.BusinessException;
import cn.common.interaction.helper.PageBuilder;
import cn.common.req.MedicalHistoryAddReq;
import cn.common.req.MedicalHistoryReq;
import cn.common.req.MedicalHistoryUpdateReq;
import cn.common.interaction.resp.page.Pagination;
import cn.common.resp.MedicalHistoryResp;
import cn.common.req.MedicalHistoryImportReq;
import cn.common.resp.MedicalHistoryExportResp;
import cn.common.repository.entity.MedicalHistory;
import cn.common.repository.repository.MedicalHistoryRepository;
import cn.common.service.AuthUserService;
import cn.common.service.MedicalHistoryService;
import cn.common.common.utils.ExportExcelHandler;
import cn.common.req.base.BaseDeleteReq;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import cn.common.common.utils.spring.SnowflakeIdWorker;
import com.google.common.collect.Lists;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import com.google.common.collect.Maps;
import java.util.Map;

/**
* @author Singer create by Singer email:singer-coder@qq.com
* @packageName cn.common.service
* @Description: 病历信息相关服务方法实现
* @date 2021-04-23
*/
@Service("medicalHistoryService")
@Slf4j
public class MedicalHistoryServiceImpl implements MedicalHistoryService {

    @Resource
    private MedicalHistoryRepository medicalHistoryRepository;

    @Resource
    private MapperFacade mapperFacade;

    @Resource
    private BaseConstant baseConstant;

    @Resource
    private AuthUserService authUserService;

    @Resource
    private HttpServletResponse response;

    @Resource
    private HttpServletRequest request;

    /**
    * 导出数据
    * @author: create by singer - Singer email:singer-coder@qq.com
    * @date 2022/3/21
    * @param pageReq
    * @return java.util.List
    */
    @Override
    public void exportData(MedicalHistoryReq pageReq){
        log.info(">>>>>>>>>>>>>>>>>数据导出Req {} <<<<<<<<<<<<<<<<", JSON.toJSONString(pageReq));
        //构建查询条件
        LambdaQueryWrapper<MedicalHistory> pageWrapper = new LambdaQueryWrapper<>();
        setPageCriteria(pageWrapper,pageReq);
        pageWrapper.orderBy(true,false,MedicalHistory::getCreateTime);
        List<MedicalHistory> pageList = medicalHistoryRepository.selectList(pageWrapper);
        if (CollectionUtils.isEmpty(pageList)) {
            return;
        }
        List<MedicalHistoryExportResp> respList =
            mapperFacade.mapAsList(pageList, MedicalHistoryExportResp.class);
        try {
            String fileName = "导出信息.xlsx";
            ExportExcelHandler.setExportResponse(response,fileName);
            ExcelWriter excelWriter = null;
            try {
                // 这里 需要指定写用哪个class去写
                excelWriter = EasyExcel.write(response.getOutputStream(), MedicalHistoryExportResp.class).build();
                // 这里注意 如果同一个sheet只要创建一次
                WriteSheet writeSheet = EasyExcel.writerSheet("sheet").build();
                excelWriter.write(respList,writeSheet);
            } finally {
                // 关闭流
                if (excelWriter != null) {
                    excelWriter.finish();
                }
            }
        } catch (Exception e) {
            log.error(">>>>>>>>>>>>>>>>>>>>>导出数据异常:{},{}<<<<<<<<<<<<<<<<<<<<<<",e.getMessage(),e);
            ExportExcelHandler.setExportErrorResponse(response);
            Map<String, String> map = Maps.newHashMap();
            try {
                response.getWriter().println(JSON.toJSONString(map));
            } catch (IOException ioException) {
                log.error(">>>>>>>>>>>>>>>>>导出数据发生异常:{},{}<<<<<<<<<<<<<<<<<",e.getMessage(),e);
                ioException.printStackTrace();
            }
        }
    }

    /**
    * 数据导入
    * @author: create by singer - Singer email:singer-coder@qq.com
    * @date 2022/3/21
    * @param file 文件
    * @return
    */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void importData(MultipartFile file){
        try{
            List<MedicalHistoryImportReq> dataList = EasyExcel
                .read(file.getInputStream()).head(MedicalHistoryImportReq.class).sheet().doReadSync();
            if(CollectionUtils.isEmpty(dataList)){
                return;
            }
            //进行必要的字段校验
            ValidationUtil.validate(dataList);
            dataList.stream().forEach(item -> {
                MedicalHistory entity = mapperFacade.map(item, MedicalHistory.class);
                try {
                    String authUserId = authUserService.currentAuthUserId();
                    BaseUtil.setFieldValueNotNull(entity);
                    entity.setMedicalHistoryId(SnowflakeIdWorker.uniqueMainId());
                    entity.setOperatorId(authUserId);
                } catch (Exception e) {
                    log.error("导入->设置为空的属性失败 {} , {} ",e.getMessage(),e);
                }
                medicalHistoryRepository.insert(entity);
            });
        }catch (Exception e){
            log.info(">>>>>>>>>>导入数据出现异常:{},{}<<<<<<<<<",e.getMessage(),e);
            throw new BusinessException(ErrorCode.IMPORT_ERROR_CODE.getCode(),
                ErrorCode.IMPORT_ERROR_CODE.getMessage()+StrUtil.COLON+e.getMessage());
        }
    }

    /**
     * 新增
     * @author: create by singer - Singer email:singer-coder@qq.com
     * @date 2021/2/15
     * @param addReq 新增Req
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
        public void addItem(MedicalHistoryAddReq addReq){
        log.info(">>>>>>>>>>>>>>>>>新增Req {} <<<<<<<<<<<<<<<<", JSON.toJSONString(addReq));
        String authUserId = authUserService.currentAuthUserId();
        MedicalHistory entity = mapperFacade.map(addReq, MedicalHistory.class);
        try {
            BaseUtil.setFieldValueNotNull(entity);
        } catch (Exception e) {
            log.error("新增->设置为空的属性失败 {} , {} ",e.getMessage(),e);
            throw new BusinessException(ErrorCode.SET_EMPTY_FIELD_ERROR.getCode()
            ,ErrorCode.SET_EMPTY_FIELD_ERROR.getMessage());
        }
        entity.setMedicalHistoryId(SnowflakeIdWorker.uniqueMainId());
        entity.setOperatorId(authUserId);
        medicalHistoryRepository.insert(entity);
    }

    /**
     * 批量删除信息
     * @author: create by singer - Singer email:singer-coder@qq.com
     * @date 2021/2/2
     * @param req 需要被删除的信息
     */
    @Override
    public void batchDeleteItem(BaseDeleteReq req){
        List<String> mainIdList = req.getMainIdList();
        if(CollectionUtils.isEmpty(mainIdList)) {
            return;
        }
        List<MedicalHistory> entityList = medicalHistoryRepository.selectList(
            new LambdaQueryWrapper<MedicalHistory>().in(MedicalHistory::getMedicalHistoryId,mainIdList));
        entityList.stream().forEach(item -> {
            medicalHistoryRepository.deleteById(item);
        });
    }

    /**
    * 查询所有信息
    * @author: create by singer - Singer email:singer-coder@qq.com
    * @date 2022/3/13
    * @param
    * @return java.util.List
    */
    @Override
    public List<MedicalHistoryResp> queryAllMedicalHistory(){
        List<MedicalHistory> entityList = medicalHistoryRepository.selectList(new LambdaQueryWrapper<>());
            if(CollectionUtils.isEmpty(entityList)){
            return Lists.newArrayList();
        }
        return mapperFacade.mapAsList(entityList,MedicalHistoryResp.class);
    }

    /**
     * 分页查询
     * @author: create by singer - Singer email:singer-coder@qq.com
     * @date 2021/2/15
     * @param  pageReq 分页查询Req
     * @return Pagination
     */
    @Override
    public Pagination<MedicalHistoryResp> queryByPage(
        MedicalHistoryReq pageReq){
        log.info(">>>>>>>>>>>>>>>>>分页查询Req {} <<<<<<<<<<<<<<<<", JSON.toJSONString(pageReq));
        //构建查询条件
        LambdaQueryWrapper<MedicalHistory> pageWrapper = new LambdaQueryWrapper<>();
        setPageCriteria(pageWrapper,pageReq);
        pageWrapper.orderBy(true,false,MedicalHistory::getCreateTime);
        //开始分页
        Page<Object> page = PageHelper.startPage(pageReq.getCurrentPage(), pageReq.getItemsPerPage());
        List<MedicalHistory> pageList = medicalHistoryRepository.selectList(pageWrapper);
        if (CollectionUtils.isEmpty(pageList)) {
            return PageBuilder.buildPageResult(page,new ArrayList<>());
        }
        List<MedicalHistoryResp> respList =
            mapperFacade.mapAsList(pageList, MedicalHistoryResp.class);
        Integer startIndex = (pageReq.getItemsPerPage() * pageReq.getCurrentPage()) - pageReq.getItemsPerPage() + 1;
        AtomicInteger idBeginIndex = new AtomicInteger(startIndex);
            respList.stream().forEach(item -> {
                item.setId(Integer.valueOf(idBeginIndex.getAndIncrement()).longValue());
        });
        return PageBuilder.buildPageResult(page,respList);
    }

    /**
     * 设置分页条件
     * @author: create by singer - Singer email:singer-coder@qq.com
     * @date 2021/5/31
     * @param pageWrapper 查询条件
     * @param pageReq 分页插件
     * @return
     */
    private void setPageCriteria(LambdaQueryWrapper<MedicalHistory> pageWrapper, MedicalHistoryReq pageReq){

         if(!CheckParam.isNull(pageReq.getAuthUserId())){
             pageWrapper.eq(MedicalHistory::getAuthUserId,"%"+pageReq.getAuthUserId());
         }

         if(!CheckParam.isNull(pageReq.getUserName())){
             pageWrapper.like(MedicalHistory::getUserName,"%"+pageReq.getUserName());
         }

         if(!CheckParam.isNull(pageReq.getGender())){
             pageWrapper.eq(MedicalHistory::getGender,"%"+pageReq.getGender());
         }

         if(!CheckParam.isNull(pageReq.getAge())){
             pageWrapper.eq(MedicalHistory::getAge,"%"+pageReq.getAge());
         }

         if(!CheckParam.isNull(pageReq.getMarriage())){
             pageWrapper.eq(MedicalHistory::getMarriage,"%"+pageReq.getMarriage());
         }

         if(!CheckParam.isNull(pageReq.getNation())){
             pageWrapper.like(MedicalHistory::getNation,"%"+pageReq.getNation());
         }

         if(!CheckParam.isNull(pageReq.getOccupation())){
             pageWrapper.like(MedicalHistory::getOccupation,"%"+pageReq.getOccupation());
         }

         if(!CheckParam.isNull(pageReq.getBirthPlace())){
             pageWrapper.like(MedicalHistory::getBirthPlace,"%"+pageReq.getBirthPlace());
         }

         if(!CheckParam.isNull(pageReq.getPresentAddress())){
             pageWrapper.like(MedicalHistory::getPresentAddress,"%"+pageReq.getPresentAddress());
         }

         if(!CheckParam.isNull(pageReq.getWorkUnit())){
             pageWrapper.like(MedicalHistory::getWorkUnit,"%"+pageReq.getWorkUnit());
         }

         if(!CheckParam.isNull(pageReq.getIdCardNum())){
             pageWrapper.like(MedicalHistory::getIdCardNum,"%"+pageReq.getIdCardNum());
         }

         if(!CheckParam.isNull(pageReq.getPhoneNum())){
             pageWrapper.like(MedicalHistory::getPhoneNum,"%"+pageReq.getPhoneNum());
         }

         if(!CheckParam.isNull(pageReq.getBeginTime())){
             pageWrapper.ge(MedicalHistory::getCreateTime,pageReq.getBeginTime());
         }

         if(!CheckParam.isNull(pageReq.getEndTime())){
             pageWrapper.le(MedicalHistory::getCreateTime,pageReq.getEndTime());
         }

         if(!CheckParam.isNull(pageReq.getAllergicCondition())){
             pageWrapper.like(MedicalHistory::getAllergicCondition,"%"+pageReq.getAllergicCondition());
         }

         if(!CheckParam.isNull(pageReq.getHistoryNarrative())){
             pageWrapper.like(MedicalHistory::getHistoryNarrative,"%"+pageReq.getHistoryNarrative());
         }
    }

    /**
     * 更新
     * @author: create by singer - Singer email:singer-coder@qq.com
     * @date 2021/4/2
     * @param updateReq 更新请求参数
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void updateItem(MedicalHistoryUpdateReq updateReq){
        log.info(">>>>>>>>>>>>>>>>>更新请求参数 {} <<<<<<<<<<<<<<<<", JSON.toJSONString(updateReq));
        String mainId = updateReq.getMedicalHistoryId();
        MedicalHistory result = medicalHistoryRepository.selectOne(new LambdaQueryWrapper<MedicalHistory>()
                    .eq(MedicalHistory::getMedicalHistoryId,mainId));
        if (CheckParam.isNull(result)) {
            return;
        }
        setNeedUpdateItem(result,updateReq);
        medicalHistoryRepository.updateById(result);
    }

    /**
     * 设置需要更新的字段
     * @author: create by singer - Singer email:singer-coder@qq.com
     * @date 2021/3/30
     * @param updateReq 更新参数
     * @param entity 产业
     */
    private void setNeedUpdateItem(MedicalHistory entity,
        MedicalHistoryUpdateReq updateReq){
        if(!CheckParam.isNull(updateReq.getAuthUserId())){
            entity.setAuthUserId(updateReq.getAuthUserId());
        }
        if(!CheckParam.isNull(updateReq.getUserName())){
            entity.setUserName(updateReq.getUserName());
        }
        if(!CheckParam.isNull(updateReq.getGender())){
            entity.setGender(updateReq.getGender());
        }
        if(!CheckParam.isNull(updateReq.getAge())){
            entity.setAge(updateReq.getAge());
        }
        if(!CheckParam.isNull(updateReq.getMarriage())){
            entity.setMarriage(updateReq.getMarriage());
        }
        if(!CheckParam.isNull(updateReq.getNation())){
            entity.setNation(updateReq.getNation());
        }
        if(!CheckParam.isNull(updateReq.getOccupation())){
            entity.setOccupation(updateReq.getOccupation());
        }
        if(!CheckParam.isNull(updateReq.getBirthPlace())){
            entity.setBirthPlace(updateReq.getBirthPlace());
        }
        if(!CheckParam.isNull(updateReq.getPresentAddress())){
            entity.setPresentAddress(updateReq.getPresentAddress());
        }
        if(!CheckParam.isNull(updateReq.getWorkUnit())){
            entity.setWorkUnit(updateReq.getWorkUnit());
        }
        if(!CheckParam.isNull(updateReq.getIdCardNum())){
            entity.setIdCardNum(updateReq.getIdCardNum());
        }
        if(!CheckParam.isNull(updateReq.getPhoneNum())){
            entity.setPhoneNum(updateReq.getPhoneNum());
        }
        if(!CheckParam.isNull(updateReq.getAdmittedTime())){
            entity.setAdmittedTime(updateReq.getAdmittedTime());
        }
        if(!CheckParam.isNull(updateReq.getRecordTime())){
            entity.setRecordTime(updateReq.getRecordTime());
        }
        if(!CheckParam.isNull(updateReq.getAllergicCondition())){
            entity.setAllergicCondition(updateReq.getAllergicCondition());
        }
        if(!CheckParam.isNull(updateReq.getHistoryNarrative())){
            entity.setHistoryNarrative(updateReq.getHistoryNarrative());
        }
    }
}
