package com.kcim.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelVerifyHandlerResult;
import cn.afterturn.easypoi.handler.inter.IExcelVerifyHandler;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kcim.common.constants.Constant;
import com.kcim.common.constants.NumberConstant;
import com.kcim.common.exception.CostException;
import com.kcim.common.util.BeanUtil;
import com.kcim.common.util.PageUtils;
import com.kcim.common.util.UserContext;
import com.kcim.common.util.excel.ExcelStyleUtil;
import com.kcim.common.util.excel.entity.DrugImportEntity;
import com.kcim.common.util.excel.handler.DrugTypeHandler;
import com.kcim.dao.model.Drug;
import com.kcim.dao.model.OrderItemMap;
import com.kcim.dao.repository.DrugRepository;
import com.kcim.service.CenterService;
import com.kcim.service.DrugService;
import com.kcim.vo.DictDataVo;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: CostAccount
 * @description: 药品字典接口实现类
 * @author: Wang.YS
 * @create: 2023-11-03 15:38
 **/
@Service("DrugService")
@Slf4j
@AllArgsConstructor
public class DrugServiceImpl implements DrugService {

    DrugRepository repository;

    CenterService centerService;

    /**
     * 按分页获取药品字典
     * @param current 当前页
     * @param pageSize 页容量
     * @param name 药品名称
     * @param stop 是否停用 0启用 1停用 默认 0
     * @return 药品字典
     */
    @Override
    public Object getDrugList(Integer current, Integer pageSize, String name, Integer stop) {
        Page<Drug> page = repository.getPage(current, pageSize, name, stop);
        List<Drug> records = page.getRecords();
        if(CollectionUtils.isEmpty(records)){
            return new PageUtils(new ArrayList<>(), NumberConstant.ZERO,pageSize,current);
        }
        DictDataVo dict = centerService.getDict(Constant.DRUG_TYPE);
        List<DictDataVo> dataVoList = dict.getDataVoList();
        Map<String,String> dictMap = dataVoList.stream().collect(Collectors.toMap(DictDataVo::getCode, DictDataVo::getName, (a, b) -> b));
        records.forEach(record -> record.setTypeName(dictMap.get(record.getType())));
        return new PageUtils(records, Math.toIntExact(page.getTotal()),pageSize,current);
    }

    /**
     * 新增药品字典
     * @param request 入参
     */
    @Override
    public void addDrug(Drug request) {
        List<Drug> dictKcClasses = repository.getByCode(request.getCode());
        if(!CollectionUtils.isEmpty(dictKcClasses)){
            throw new CostException("当前药品代码已存在，请修改后再保存");
        }
        request.setHospId(UserContext.getCurrentLoginHospId());
        request.setCreateTime(new Date());
        request.setCreateUser(String.valueOf(UserContext.getCurrentUser().getId()));
        if(request.getStatus() != null &&request.getStatus().equals(NumberConstant.ONE)){
            Date stopTime = request.getStopTime();
            if(stopTime == null){
                throw new CostException("当前药品停用标志为停用，停用时间必填");
            }
        }else {
            request.setStatus(NumberConstant.ZERO);
        }
        repository.save(request);

    }

    /**
     * 编辑药品字典
     * @param request 入参
     */
    @Override
    public void editDrug(Drug request) {
        Integer id = request.getId();
        if(id ==null){
            throw new CostException("编辑药品时，主键必填");
        }
        Drug drug = repository.getById(id);
        Drug drugOne = repository.getOneByCode(request.getCode());
        if(Objects.nonNull(drug)){
            if(Objects.isNull(drugOne)||drugOne.getId().equals(id)){
                BeanUtil.convertObj(request,drug);
                drug.setUpdateTime(new Date());
                drug.setUpdateUser(String.valueOf(UserContext.getCurrentUser().getId()));
                if(drug.getStatus() != null &&drug.getStatus().equals(NumberConstant.ONE)){
                    Date stopTime = request.getStopTime();
                    if(stopTime == null){
                        throw new CostException("当前药品停用标志为停用，停用时间必填");
                    }
                }else {
                    drug.setStopTime(null);
                }
                repository.updateById(drug);
            }else {
                throw new CostException("当前药品代码已存在，请修改后再保存");

            }
        }

    }

    /**
     * 删除药品字典
     * @param id 主键
     */
    @Override
    public void deleteDrug(Integer id) {
        repository.deleteDrug(id);

    }

    /**
     * 导出药品字典模版
     * @param response 返回值
     * @return
     */
    @SneakyThrows
    @Override
    public Object exportDrug(HttpServletResponse response) {
        try {
            //配置excel 文件信息
            ExportParams params = new ExportParams();

            params.setTitle("说明：1、为了保证成功导入，请勿修改模板格式\n" +
                    "      2、项目类型填对应的药品类型名称，如：西药、成药、草药\n" +
                    "      3、停用字段为下拉选择字段，不可填写选项外的内容\n" +
                    "      4、停用字段为是时，必须填写对应的停用时间，格式：yyyy-MM-dd HH:mm:ss");
            DictDataVo dict = centerService.getDict(Constant.DRUG_TYPE);

            List<DictDataVo> dataVoList = dict.getDataVoList();
            //设置导出样式
            params.setStyle(ExcelStyleUtil.class);
            params.setDictHandler(new DrugTypeHandler(dataVoList));
            //设置sheetName
            params.setTitleHeight((short) 20);
            params.setSheetName("药品项目");
//            FileOutputStream outputStream = new FileOutputStream("E:\\药品字典模版.xlsx");
            Workbook workbook = ExcelExportUtil.exportExcel(params, DrugImportEntity.class,new ArrayList<>());
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/vnd.ms-excel");
            String fileName ="药品项目成本导入模版";
            response.setHeader("Content-Disposition",  URLEncoder.encode(fileName, "UTF-8"));
            workbook.write(response.getOutputStream());
//                workbook.write(outputStream);
//                outputStream.close();
            workbook.close();
            log.info("导出文件：{}",fileName);
        } catch (FileNotFoundException e) {
            throw new CostException(e.getMessage());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return response.getOutputStream();
    }

    /**
     * 导入药品字典
     * @param file excel 文件
     */
    @Override
    public void importDrug(MultipartFile file) {
        try {
            if (ObjectUtils.isEmpty(file) || file.getSize() == 0){
                throw new CostException("未获取到导入的excel文件内容");
            }
            log.info("接收到文件：{}",file.getOriginalFilename());
            // 参数1：文件流
            InputStream stream = file.getInputStream();
            // 参数2：导入类型
            ImportParams params = new ImportParams();
            //校验Excel 去掉空行
            params.setNeedVerify(true);
            IExcelVerifyHandler<DrugImportEntity> handler = val ->{
                if(StringUtils.isEmpty(val.getCode())){
                    return new ExcelVerifyHandlerResult(false,"药品项目代码不能为空");
                }
                if(StringUtils.isEmpty(val.getName())){
                    return new ExcelVerifyHandlerResult(false,"药品名称不能为空");
                }
                return new ExcelVerifyHandlerResult(true);
            };
            params.setVerifyHandler(handler);
            // 标题占用多少行
            params.setTitleRows(1);
            // 头部属性占用多少行
            params.setHeadRows(1);
            DictDataVo dict = centerService.getDict(Constant.DRUG_TYPE);

            List<DictDataVo> dataVoList = dict.getDataVoList();
            //设置导出样式
            params.setDictHandler(new DrugTypeHandler(dataVoList));
            List<DrugImportEntity> drugImportEntities  = ExcelImportUtil.importExcel(stream, DrugImportEntity.class,params);
            if(!CollectionUtils.isEmpty(drugImportEntities)){
                List<Drug> saveList = new ArrayList<>();
                Drug drugCost =new Drug();
                drugCost.setHospId(UserContext.getHospId());
                drugCost.setCreateTime(new Date());
                drugCost.setCreateUser(String.valueOf(UserContext.getCurrentUser().getId()));
                for (DrugImportEntity entity : drugImportEntities) {
                    Drug drug = BeanUtil.convertObj(drugCost, Drug.class);
                    drug.setCode(entity.getCode());
                    drug.setName(entity.getName());
                    drug.setType(entity.getType());
                    drug.setStatus(entity.getStatus());
//                    drug.setStopTime(DateUtils.StringToDate(entity.getStopTime(), DateStyleEnum.YYYY_MM_DD_HH_MM_SS));
                    drug.setStopTime(entity.getStopTime());

                    drug.setPrice(entity.getPrice());
                    drug.setCost(entity.getCost());
                    saveList.add(drug);
                }
                if(!CollectionUtils.isEmpty(saveList)){
                    check();
                    repository.saveBatch(saveList,50);
                }
            }
        } catch (Exception e) {
            throw new CostException(e.getMessage());
        }
    }

    @Override
    public Object getDrugType() {
        DictDataVo dict = centerService.getDict(Constant.DRUG_TYPE);

        return dict.getDataVoList();
    }

    @Override
    public List<OrderItemMap> getItemDict(String name) {
        List<Drug> list = repository.getList(name);
        if(CollectionUtils.isEmpty(list)){
            return new ArrayList<>();
        }
        List<OrderItemMap> returnList = new ArrayList<>();
        for (Drug drug : list) {
            OrderItemMap orderItemMap = new OrderItemMap();
            orderItemMap.setItemCode(drug.getCode());
            orderItemMap.setItemName(drug.getName());
            orderItemMap.setItemType(String.valueOf(NumberConstant.ONE));
            returnList.add(orderItemMap);
        }
        return returnList;
    }

    private void check() {
        List<Drug> list = repository.getList();
        if(!CollectionUtils.isEmpty(list)){
            repository.removeList(list);
        }
    }
}
