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 cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kcim.common.constants.NumberConstant;
import com.kcim.common.exception.CostException;
import com.kcim.common.util.BeanUtil;
import com.kcim.common.util.ComputeDateUtils;
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.PatientItemImportEntity;
import com.kcim.common.util.excel.handler.ItemTypeHandler;
import com.kcim.dao.model.CostIncomeFile;
import com.kcim.dao.model.ImportPatientItem;
import com.kcim.dao.repository.ImportPatientItemRepository;
import com.kcim.service.CenterService;
import com.kcim.service.CostIncomeFileService;
import com.kcim.service.PatientItemImportService;
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.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.kcim.common.constants.Constant.CHARGE_ITEM_TYPE;

/**
 * @program: CostAccount
 * @description: 患者收费项目信息导入实现类
 * @author: Wang.YS
 * @create: 2023-10-19 14:18
 **/
@Service("PatientItemImportService")
@AllArgsConstructor
@Slf4j
public class PatientItemImportServiceImpl implements PatientItemImportService {
    ImportPatientItemRepository repository;

    CenterService centerService;

    CostIncomeGroupServiceImpl costIncomeGroupService;

    CostIncomeFileService costIncomeFileService;

    /**
     * 月度信息采集-人事成本数据导入-获取患者收费项目列表
     *
     * @param current        当前页
     * @param pageSize       页容量
     * @param computeDate    核算年月
     * @param itemType       项目类型
     * @param departmentName 科室列表
     * @param patientNo
     * @param filter
     * @return 导入列表
     */
    @Override
    public Object getPatientItemList(Integer current, Integer pageSize, String computeDate, String itemType, String departmentName, String patientNo, String filter) {
        Page<ImportPatientItem> page = repository.getPage(current, pageSize, computeDate, itemType, departmentName,patientNo,filter);
        List<ImportPatientItem> records = page.getRecords();
        if(!CollectionUtils.isEmpty(records)){
            return new PageUtils(records, Math.toIntExact(page.getTotal()),pageSize,current);
        }
        return new PageUtils(new ArrayList<>(), NumberConstant.ZERO,pageSize,current);
    }

    /**
     * 月度信息采集-人事成本数据导入-获取患者收费导入模版
     *
     * @param response 出参
     * @return 模版
     */
    @SneakyThrows
    @Override
    public Object exportPatientItem(HttpServletResponse response)  {
        try {
            //获取项目类别字典

            DictDataVo dict = centerService.getDict(CHARGE_ITEM_TYPE);
            List<DictDataVo> dataVoList = dict.getDataVoList();
            //配置excel 文件信息
            ExportParams params = new ExportParams();

            params.setTitle("说明：1、为了保证成功导入，请勿修改模板格式\n" +
                    "           2、住院号/门诊号为患者就诊的唯一标识\n" +
                    "           3、项目类别为下拉选择，只能填选项的内容");
            //设置导出样式
            params.setStyle(ExcelStyleUtil.class);
            params.setDictHandler(new ItemTypeHandler(dataVoList));
            params.setTitleHeight(Short.parseShort("15"));
            params.setHeaderHeight(10);

            //设置sheetName
            params.setSheetName("患者收费项目");
//            params.setHeaderColor();
//            params.setFreezeCol(2);
//            FileOutputStream outputStream = new FileOutputStream("E:\\患者项目导入模版.xlsx");

            Workbook workbook = ExcelExportUtil.exportExcel(params, PatientItemImportEntity.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();
        } catch (FileNotFoundException e) {
            throw new CostException(e.getMessage());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return response.getOutputStream();    }

    /**
     * 月度信息采集-人事成本数据导入-导入患者收费项目列表
     *
     * @param computeDate 核算年月
     * @param file        文件
     */
    @Override
    public void importPatientItem(String computeDate, 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<PatientItemImportEntity> handler = val ->{
                if(StringUtils.isEmpty(val.getVisitNo())){
                    return new ExcelVerifyHandlerResult(false,"住院号/门诊号不能为空");
                }
                return new ExcelVerifyHandlerResult(true);
            };
            params.setVerifyHandler(handler);
            // 标题占用多少行
            params.setTitleRows(1);
            // 头部属性占用多少行
            params.setHeadRows(1);
            DictDataVo dict = centerService.getDict(CHARGE_ITEM_TYPE);
            List<DictDataVo> dataVoList = dict.getDataVoList();
            Map<String,String> itemTypeMap = dataVoList.stream().collect(Collectors.toMap(DictDataVo::getCode, DictDataVo::getName, (a, b) -> b));

            params.setDictHandler(new ItemTypeHandler(dataVoList));
            List<PatientItemImportEntity> patientItemImportEntities  = ExcelImportUtil.importExcel(stream, PatientItemImportEntity.class,params);
            if(!CollectionUtils.isEmpty(patientItemImportEntities)){
                List<ImportPatientItem> saveList = new ArrayList<>();
                ImportPatientItem importPatientItem = new ImportPatientItem();
                importPatientItem.setHospId(UserContext.getHospId());
                importPatientItem.setComputeDate(computeDate);
                importPatientItem.setCreateTime(new Date());
                importPatientItem.setCreateUser(String.valueOf(UserContext.getCurrentUser().getId()));
                for (PatientItemImportEntity entity : patientItemImportEntities) {
                    ImportPatientItem patientItem = BeanUtil.convertObj(importPatientItem, ImportPatientItem.class);
                    patientItem.setVisitNo(entity.getVisitNo());
                    patientItem.setPatientNo(entity.getPatientNo());
                    patientItem.setName(entity.getName());
                    patientItem.setItemCode(entity.getItemCode());
                    patientItem.setItemName(entity.getItemName());
                    patientItem.setItemTypeCode(entity.getItemType());
                    patientItem.setOrderCode(entity.getOrderCode());
                    patientItem.setOrderName(entity.getOrderName());
                    patientItem.setItemType(itemTypeMap.get(entity.getItemType()));
                    patientItem.setOrderDepartmentCode(entity.getOrderDepartmentCode());
                    patientItem.setOrderDepartmentName(entity.getOrderDepartmentName());
                    patientItem.setOrderUserCode(entity.getOrderUserCode());
                    patientItem.setOrderUserName(entity.getOrderUserName());
                    patientItem.setExecuteDepartmentCode(entity.getExecuteDepartmentCode());
                    patientItem.setExecuteDepartmentName(entity.getExecuteDepartmentName());
                    patientItem.setExecuteUserCode(entity.getExecuteUserCode());
                    patientItem.setExecuteUserName(entity.getExecuteUserName());
                    patientItem.setNum(entity.getNum());
                    patientItem.setPrice(entity.getPrice());
                    patientItem.setAmount(entity.getAmount());
                    patientItem.setExecuteTime(entity.getExecuteTime());
                    saveList.add(patientItem);
                }
                // 文件上传
                String uploadFile = costIncomeGroupService.uploadFile(file);
                // 上传记录保存
                if (StrUtil.isBlank(uploadFile)) {
                    throw new CostException(500, "文件上传异常");
                }
                CostIncomeFile costIncomeFile = costIncomeFileService.saveFile(saveList.size(), file, UserContext.getHospId(), new ArrayList<>(), uploadFile, NumberConstant.SIX, ComputeDateUtils.getComputeYear(computeDate), ComputeDateUtils.getComputeMonth(computeDate));
                Long id = costIncomeFile.getId();

                if(!CollectionUtils.isEmpty(saveList)){
//                    check(computeDate);
                    saveList.forEach(f->f.setFileId(id));
                    repository.saveBatch(saveList,50);
                }
//                if(!CollectionUtils.isEmpty(saveList)){
//                    check(computeDate);
//                    repository.saveBatch(saveList,50);
//                }

            }

        }catch (Exception e){
            throw new RuntimeException(e);
        }


    }

    /**
     * 获取当前月度所有项目总金额
     *
     * @param computeDate    核算年月
     * @param itemType 项目类别
     * @param departmentName 科室名称
     * @return 总金额
     */
    @Override
    public Object getComputeTotal(String computeDate, String itemType, String departmentName) {
        List<ImportPatientItem> byComputeDate = repository.getByComputeDate(computeDate,itemType,departmentName);
        if(!CollectionUtils.isEmpty(byComputeDate)){
            BigDecimal total = new BigDecimal("0.00");
            for (ImportPatientItem patientItem : byComputeDate) {
                if(patientItem.getAmount()!= null){
                    total=total.add(patientItem.getAmount());
                }
            }
            return total;
        }
        return BigDecimal.ZERO;
    }

    @Override
    public void removePatientItem(String computeDate) {
        check(computeDate);
    }

    @Override
    public PageUtils getPatientItemPatientInfo(Integer current, Integer pageSize, String filter, String computeDate) {
        return repository.getPatientItemPatientInfo(current, pageSize, computeDate,filter);
    }

    /**
     * @param computeDate
     * @param fileId
     */
    @Override
    public void removePatientItemByFileId(String computeDate, Long fileId) {
        repository.removePatientItemByFileId(computeDate,fileId);

    }

    /**
     * @param computeDate
     * @param fileId
     */
    @Override
    public void reducingPatientItemByFileId(String computeDate, Long fileId) {
        repository.reducingPatientItemByFileId(computeDate,fileId);

    }

    private void check(String computeDate) {
        repository.removeByComputeDate(computeDate);
//        List<ImportPatientItem> byComputeDate = repository.getByComputeDate(computeDate);
//        if(!CollectionUtils.isEmpty(byComputeDate)){
//            for (ImportPatientItem patientItem : byComputeDate) {
//                patientItem.setDeleteTime(new Date());
//                patientItem.setDeleteUser(String.valueOf(UserContext.getCurrentUser().getId()));
//            }
//            repository.updateBatchById(byComputeDate);
//            List<Integer> collect = byComputeDate.stream().map(ImportPatientItem::getId).collect(Collectors.toList());
//            repository.removeBatchByIds(collect);
//
//        }
    }
}
