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.entity.EmpTypeEntity;
import com.kcim.common.util.excel.handler.DrugTypeHandler;
import com.kcim.dao.model.Drug;
import com.kcim.dao.model.EmpCostMap;
import com.kcim.dao.model.EmpCostType;
import com.kcim.dao.model.dto.SysDepartment;
import com.kcim.dao.repository.EmpCostMapRepository;
import com.kcim.dao.repository.EmpCostTypeRepository;
import com.kcim.service.CenterService;
import com.kcim.service.EmpCostMapService;
import com.kcim.vo.DictDataVo;
import com.kcim.vo.UserInfoVO;
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.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
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;

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

/**
 * @program: CostAccount
 * @description: 人事分类人员对照接口实现类
 * @author: Wang.YS
 * @create: 2023-11-02 18:23
 **/
@Service("EmpCostMapService")
@Slf4j
@AllArgsConstructor
public class EmpCostMapServiceImpl implements EmpCostMapService {
    EmpCostTypeRepository empCostTypeRepository;

    EmpCostMapRepository repository;

    CenterService centerService;

    /**
     * 获取人事分类-人员对照信息
     *
     * @param current      当前页
     * @param pageSize     页容量
     * @param costTypeCode
     * @param filter       过滤条件
     * @return 对照信息
     */
    @Override
    public Object getEmpCostMap(Integer current, Integer pageSize, String costTypeCode, String filter) {
        Page<EmpCostMap> page = repository.getPage(current, pageSize, costTypeCode,filter);
        List<EmpCostMap> records = page.getRecords();
        if(CollectionUtils.isEmpty(records)){
            return new PageUtils(new ArrayList<>(), NumberConstant.ZERO,pageSize,current);
        }
        return new PageUtils(records, Math.toIntExact(page.getTotal()),pageSize,current);
    }

    /**
     * 新增 增量
     * @param request 入参
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public void addEmpCostMap(List<EmpCostMap> request) {
        if(CollectionUtils.isEmpty(request)){
            log.error("未找到需要保存的人事分类-人员信息");
            throw new CostException("未找到需要保存的人事分类-人员信息");
        }

        for (EmpCostMap empCostMap : request) {
            empCostMap.setHospId(UserContext.getHospId());
            empCostMap.setCreateUser(String.valueOf(UserContext.getCurrentUser().getId()));
            empCostMap.setCreateTime(new Date());
        }
        repository.saveBatch(request);
    }

    /**
     *
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public void updateEmpMap() {
        List<UserInfoVO> userInfo = centerService.getCenterUserInfo(null);
        DictDataVo centerDict = centerService.getCenterDict(Constant.POSITION);
        List<DictDataVo> dataVoList = centerDict.getDataVoList();
        Map<String,String> positionMap = dataVoList.stream().collect(Collectors.toMap(DictDataVo::getCode, DictDataVo::getName, (a, b) -> b));
        Map<Long,UserInfoVO> mapUser = userInfo.stream().collect(Collectors.toMap(UserInfoVO::getUserId, infoVO -> infoVO, (a, b) -> b));
//        List<SysDepartment> departmentFilter = centerService.getDepartmentFilter(null);
//        Map<Integer,String> departmentMap = new HashMap<>();
//        for (SysDepartment sysDepartment : departmentFilter) {
//            departmentMap.put(sysDepartment.getId(), sysDepartment.getCode());
//        }

        List<EmpCostMap> list = repository.getList();
        for (EmpCostMap empCostMap : list) {
            Long userId = empCostMap.getUserId();
            UserInfoVO infoVO = mapUser.get(userId);
            empCostMap.setAccount(infoVO.getAccount());
            empCostMap.setName(infoVO.getName());
            empCostMap.setDepartmentCode(infoVO.getDepartmentId());
            empCostMap.setDepartmentName(infoVO.getDepartmentName());
            empCostMap.setPosition(infoVO.getPosition());
            empCostMap.setPositionName(positionMap.get(infoVO.getPosition()));
        }
        repository.updateBatchById(list);
    }

    /**
     * 删除人员对照信息
     * @param id 主键
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public void deleteEmpCostMap(Integer id) {
        repository.deleteEmpCostMap(Collections.singletonList(id));
    }

    /**
     * 批量删除人员对照信息
     * @param id 主键数组
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public void batchDeleteEmpCostMap(List<Integer> id) {
        repository.deleteEmpCostMap(id);

    }

    /**
     * 获取中台人员信息 并与已对照人员进行对比  去除已对照人员
     * @return 未对照人员
     */
    @Override
    public Object getEmpInfo(String costType) {
        List<UserInfoVO> userInfo = centerService.getCenterUserInfo(null);
        DictDataVo centerDict = centerService.getCenterDict(Constant.POSITION);
        List<DictDataVo> dataVoList = centerDict.getDataVoList();
        Map<String,String> positionMap = dataVoList.stream().collect(Collectors.toMap(DictDataVo::getCode, DictDataVo::getName, (a, b) -> b));
        Map<Long,UserInfoVO> mapUser = userInfo.stream().collect(Collectors.toMap(UserInfoVO::getId, infoVO -> infoVO, (a, b) -> b));
        List<EmpCostMap> list = repository.getList();
        if(!CollectionUtils.isEmpty(list)){
            List<Long> collect = list.stream().map(EmpCostMap::getUserId).collect(Collectors.toList());
            List<UserInfoVO> removeInfo = collect.stream().map(mapUser::get).collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(removeInfo)){
                userInfo.removeAll(removeInfo);
            }
        }
        userInfo.forEach(infoVO -> infoVO.setPositionName(positionMap.get(infoVO.getPosition())));
        return userInfo;
    }

    /**
     * @param response
     * @return
     */
    @SneakyThrows
    @Override
    public Object exportEmpType(HttpServletResponse response) {
        try {
            //配置excel 文件信息
            ExportParams params = new ExportParams();

            params.setTitle("说明：1、为了保证成功导入，请勿修改模板格式");

            //设置导出样式
            params.setStyle(ExcelStyleUtil.class);
            //设置sheetName
            params.setTitleHeight((short) 20);
            params.setSheetName("人事分类");
//            FileOutputStream outputStream = new FileOutputStream("E:\\药品字典模版.xlsx");
            Workbook workbook = ExcelExportUtil.exportExcel(params, EmpTypeEntity.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
     */
    @Override
    public void importEmpType(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);
            // 标题占用多少行
            params.setTitleRows(1);
            // 头部属性占用多少行
            params.setHeadRows(1);

            List<EmpTypeEntity> importExcel  = ExcelImportUtil.importExcel(stream, EmpTypeEntity.class,params);
            if(!CollectionUtils.isEmpty(importExcel)){
                List<EmpCostType> saveEmpType = new ArrayList<>();
                List<EmpCostMap> saveEmpCostMap = new ArrayList<>();
                EmpCostType empCostType1 = new EmpCostType();
                EmpCostMap empCostMap1 = new EmpCostMap();
                empCostType1.setHospId(UserContext.getHospId());
                empCostType1.setCreateTime(new Date());
                empCostType1.setCreateUser(String.valueOf(UserContext.getCurrentUser().getId()));

                empCostMap1.setHospId(UserContext.getHospId());
                empCostMap1.setCreateTime(new Date());
                empCostMap1.setCreateUser(String.valueOf(UserContext.getCurrentUser().getId()));

                for (EmpTypeEntity empTypeEntity : importExcel) {
                    EmpCostType empCostType = BeanUtil.convertObj(empCostType1, EmpCostType.class);
                    EmpCostMap empCostMap = BeanUtil.convertObj(empCostMap1, EmpCostMap.class);

                    empCostType.setCostTypeCode(empTypeEntity.getEmpTypeCode());
                    empCostType.setCostTypeName(empTypeEntity.getEmpTypeName());
                    empCostType.setComputeType(NumberConstant.ZERO_S);
                    empCostType.setComputeTypeName("无");
                    saveEmpType.add(empCostType);
                    empCostMap.setCostTypeCode(empCostType.getCostTypeCode());
                    empCostMap.setPositionName(empTypeEntity.getPositionName());
                    empCostMap.setPosition(empTypeEntity.getPositionCode());
                    empCostMap.setAccount(empTypeEntity.getAccount());
                    empCostMap.setName(empTypeEntity.getName());
                    empCostMap.setUserId(Long.valueOf(empTypeEntity.getUserId()));
                    empCostMap.setDepartmentCode(empTypeEntity.getDepartmentCode());
                    empCostMap.setDepartmentName(empTypeEntity.getDepartmentName());
                    saveEmpCostMap.add(empCostMap);
                }

                if(!CollectionUtils.isEmpty(saveEmpType)){
                    List<EmpCostType> collect = saveEmpType.stream().distinct().collect(Collectors.toList());
                    check();
                    empCostTypeRepository.saveBatch(collect);
                    if(!CollectionUtils.isEmpty(saveEmpCostMap)){
                        repository.saveBatch(saveEmpCostMap);
                    }
                }
            }
        } catch (Exception e) {
            throw new CostException(e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public void generateEmpType() {
        DictDataVo centerDict = centerService.getCenterDict(PERSONNEL_CATEGORY);
        if(Objects.isNull(centerDict)){
            throw new CostException("未找到【人员类别】字典");
        }
        List<DictDataVo> dataVoList = centerDict.getDataVoList();
        if(CollectionUtils.isEmpty(dataVoList)){
            throw new CostException("未找到【人员类别】字典");
        }
        DictDataVo centerPositionDict = centerService.getCenterDict(Constant.POSITION);
        List<DictDataVo> positionDataVoList = centerPositionDict.getDataVoList();
        Map<String,String> positionMap = positionDataVoList.stream().collect(Collectors.toMap(DictDataVo::getCode, DictDataVo::getName, (a, b) -> b));


//        Map<String,String> empTypeMap = dataVoList.stream().collect(Collectors.toMap(DictDataVo::getCode, DictDataVo::getName, (a, b) -> b));

        //获取人员信息
        List<UserInfoVO> centerUserInfo = centerService.getCenterUserInfo(null);
        if(CollectionUtils.isEmpty(centerUserInfo)){
            throw new CostException("未找到人员信息");
        }
        //去除人员类别为空的数据
        List<UserInfoVO> collect = centerUserInfo.stream().filter(f -> !StringUtils.isEmpty(f.getUserCate())).collect(Collectors.toList());
        Map<String, List<UserInfoVO>> userCateGroup = new HashMap<>();
        if(!CollectionUtils.isEmpty(collect)){
            userCateGroup = collect.stream().collect(Collectors.groupingBy(UserInfoVO::getUserCate));

        }

        List<EmpCostType> saveEmpType = new ArrayList<>();
        List<EmpCostMap> saveEmpCostMap = new ArrayList<>();
        EmpCostType empCostType1 = new EmpCostType();
        EmpCostMap empCostMap1 = new EmpCostMap();
        empCostType1.setHospId(UserContext.getHospId());
        empCostType1.setCreateTime(new Date());
        empCostType1.setCreateUser(String.valueOf(UserContext.getCurrentUser().getId()));
        empCostMap1.setHospId(UserContext.getHospId());
        empCostMap1.setCreateTime(new Date());
        empCostMap1.setCreateUser(String.valueOf(UserContext.getCurrentUser().getId()));
        for (DictDataVo vo : dataVoList) {
            EmpCostType empCostType = BeanUtil.convertObj(empCostType1, EmpCostType.class);
            empCostType.setCostTypeCode(vo.getCode());
            empCostType.setCostTypeName(vo.getName());
            empCostType.setComputeType(NumberConstant.ZERO_S);
            empCostType.setComputeTypeName("无");
            saveEmpType.add(empCostType);
            if(!CollectionUtils.isEmpty(userCateGroup)){
                List<UserInfoVO> userInfoVOS = userCateGroup.get(vo.getCode());
                if(!CollectionUtils.isEmpty(userInfoVOS)){
                    for (UserInfoVO userInfoVO : userInfoVOS) {
                        EmpCostMap empCostMap = BeanUtil.convertObj(empCostMap1, EmpCostMap.class);
                        empCostMap.setCostTypeCode(vo.getCode());
                        String position = userInfoVO.getPosition();
                        if(!StringUtils.isEmpty(position)){
                            empCostMap.setPositionName(positionMap.get(userInfoVO.getPosition()));
                            empCostMap.setPosition(position);
                        }
                        empCostMap.setAccount(userInfoVO.getAccount());
                        empCostMap.setName(userInfoVO.getName());
                        if(userInfoVO.getUserId()==null){
                            empCostMap.setUserId(userInfoVO.getId());
                        }else {
                            empCostMap.setUserId(userInfoVO.getUserId());
                        }
                        empCostMap.setDepartmentCode(userInfoVO.getDepartmentId());
                        empCostMap.setDepartmentName(userInfoVO.getDepartmentName());
                        saveEmpCostMap.add(empCostMap);
                    }
                }

            }
        }
        if(!CollectionUtils.isEmpty(saveEmpType)){
            check();
            empCostTypeRepository.saveBatch(saveEmpType);
            if(!CollectionUtils.isEmpty(saveEmpCostMap)){
                repository.saveBatch(saveEmpCostMap);
            }
        }
    }

    private void check() {
        List<EmpCostMap> empType = repository.getList();
        List<EmpCostType> empCostType = empCostTypeRepository.getList();

        if(!CollectionUtils.isEmpty(empType)){
            repository.removeList(empType);
        }
        if(!CollectionUtils.isEmpty(empCostType)){
            empCostTypeRepository.removeList(empCostType);
        }
    }
}
