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.kcim.common.constants.NumberConstant;
import com.kcim.common.exception.CostException;
import com.kcim.common.util.BeanUtil;
import com.kcim.common.util.UserContext;
import com.kcim.common.util.excel.ExcelStyleUtil;
import com.kcim.common.util.excel.entity.SpaceImportEntity;
import com.kcim.dao.model.Equipment;
import com.kcim.dao.model.Space;
import com.kcim.dao.repository.SpaceRepository;
import com.kcim.service.SpaceService;
import com.kcim.vo.CodeAndNameVO;
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.math.RoundingMode;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: CostAccount
 * @description:
 * @author: Wang.YS
 * @create: 2023-11-07 20:42
 **/
@Service("SpaceService")
@Slf4j
@AllArgsConstructor
public class SpaceServiceImpl implements SpaceService {
    SpaceRepository repository;


    /**
     * 获取空间成本列表
     * @param name 空间名称
     * @param type 是否停用 0启用 1停用 默认 0
     * @return 列表
     */
    @Override
    public Object getSpaceCostList(String name, Integer type) {
        List<Space> list = repository.getList(name, type);
        List<Space> parentList = repository.getParentList();
        if(CollectionUtils.isEmpty(parentList)){
            return new ArrayList<>();
        }
        if(CollectionUtils.isEmpty(list)){
            return new ArrayList<>();
        }
        Map<String, List<Space>> filterCollect = list.stream().collect(Collectors.groupingBy(Space::getParentCode));
        List<Space> parentCollect = filterCollect.get(NumberConstant.ZERO_S);
        filterCollect.remove(NumberConstant.ZERO_S);
        List<Space> removeList = new ArrayList<>();
        if(!StringUtils.isEmpty(name)){
            parentList.forEach(parent -> {
                if (!CollectionUtils.isEmpty(filterCollect.get(parent.getCode()))) {
                    parent.setChildList(setChildren(filterCollect.get(parent.getCode()),filterCollect));
                } else {
                    removeList.add(parent);
                }
            });
        }else{
            for (Space dictKcClass : parentList) {
                if (!CollectionUtils.isEmpty(filterCollect.get(dictKcClass.getCode()))) {
                    dictKcClass.setChildList(setChildren(filterCollect.get(dictKcClass.getCode()),filterCollect));
                }
            }
        }
        if(!CollectionUtils.isEmpty(removeList)){
            parentList.removeAll(removeList);
        }
        if(!CollectionUtils.isEmpty(parentCollect)){
            //检索条件查询的有父类
            if(CollectionUtils.isEmpty(parentList)){
                //查询条件为空 把父类加回去
                parentList.addAll(parentCollect);
            }else {
                //查询条件不为空 对比 最上层是否有 costItems 的父类 没有 加回去 有 不添加
                Map<String,Space> filterMap = parentCollect.stream().collect(Collectors.toMap(Space::getCode, item -> item, (a, b) -> b));
                List<Space> filterParent = new ArrayList<>();
                for(Space parent:parentList){
                    Space item = filterMap.get(parent.getCode());
                    if(Objects.nonNull(item)){
                        filterParent.add(item);
                    }
                }
                //去掉包含的 数据
                parentCollect.removeAll(filterParent);
                //剩下数据加回去
                if(!CollectionUtils.isEmpty(parentCollect)){
                    parentList.addAll(parentCollect);
                }
            }
        }
        return parentList;
    }
    public List<Space> setChildren(List<Space> spaces,Map<String, List<Space>> collect){
        for(Space space:spaces){
            if(!CollectionUtils.isEmpty(collect.get(space.getCode()))){
                space.setChildList(setChildren(collect.get(space.getCode()),collect));
            }
        }
        return spaces;
    }
    /**
     * 新增 空间成本
     * @param request 入参
     */
    @Override
    public void addSpaceCost(Space request) {
        List<Space> spaces = repository.getByCode(request.getCode());
        if(!CollectionUtils.isEmpty(spaces)){
            throw new CostException("当前空间成本代码【"+request.getCode()+"】已存在，请修改后再保存");
        }
        request.setHospId(UserContext.getHospId());
        request.setCreateTime(new Date());
        request.setCreateUser(String.valueOf(UserContext.getCurrentUser().getId()));
        if(request.getCode() != null&& request.getDepreciationYear() != null && request.getDepreciationYear().compareTo(BigDecimal.ZERO) != 0) {
            //计算每年折旧 每年折旧＝建置成本/折旧年限
            request.setCostPerYear(calculateCostPerYear(request.getCost(),request.getDepreciationYear()));
            //每分钟成本＝每年折旧/（365*24*60）
            request.setCostPerMinute(calculateCostPerMinute(request.getCostPerYear()));
        }
        if(request.getStatus() != null &&request.getStatus().equals(NumberConstant.ONE)){
            Date stopTime = request.getStopTime();
            if(stopTime == null){
                throw new CostException("当前空间成本停用标志为停用，停用时间必填");
            }
        }else {
            request.setStatus(NumberConstant.ZERO);
        }
        if(StringUtils.isEmpty(request.getParentCode())){
            request.setParentCode(NumberConstant.ZERO_S);
        }
        if(request.getType().equals(NumberConstant.ONE)){
            if(StringUtils.isEmpty(request.getParentCode())){
                throw new CostException("当前分类为子类，父类代码必填");
            }
        }
        repository.save(request);
    }

    /**
     * 编辑空间成本
     * @param request 入参
     */
    @Override
    public void editSpaceCost(Space request) {
        Integer id = request.getId();
        if(id ==null){
            throw new CostException("编辑空间成本时，主键必填");
        }
        Space space = repository.getById(id);
        Space spaceOne = repository.getOneByCode(request.getCode());

        if(Objects.nonNull(space)){
            if(Objects.isNull(spaceOne)||spaceOne.getId().equals(id)){
                BeanUtil.convertObj(request,space);
                space.setUpdateTime(new Date());
                space.setUpdateUser(String.valueOf(UserContext.getCurrentUser().getId()));
                if(space.getCode() != null&& space.getDepreciationYear() != null && space.getDepreciationYear().compareTo(BigDecimal.ZERO) != 0) {
                    //计算每年折旧 每年折旧＝建置成本/折旧年限
                    space.setCostPerYear(calculateCostPerYear(space.getCost(),space.getDepreciationYear()));
                    //每分钟成本＝每年折旧/（365*24*60）
                    space.setCostPerMinute(calculateCostPerMinute(space.getCostPerYear()));
                }
                if(space.getStatus() != null &&space.getStatus().equals(NumberConstant.ONE)){
                    Date stopTime = request.getStopTime();
                    if(stopTime == null){
                        throw new CostException("当前空间成本停用标志为停用，停用时间必填");
                    }
                }else {
                    space.setStopTime(null);
                }
                if(request.getType().equals(NumberConstant.ONE)){
                    if(StringUtils.isEmpty(request.getParentCode())){
                        throw new CostException("当前分类为子类，父类代码必填");
                    }
                }
                repository.updateById(space);
            }else {
                throw new CostException("当前空间成本代码【"+request.getCode()+"】已存在，请修改后再保存");
            }
        }
    }

    /**
     * 删除空间成本
     * @param id 主键
     */
    @Override
    public void deleteSpaceCost(Integer id) {
        repository.deleteSpaceCost(id);

    }

    /**
     * 导出空间成本模版
     * @param response 出参
     * @return 出参
     */
    @SneakyThrows
    @Override
    public Object exportSpaceCost(HttpServletResponse response) {
        try {
            //配置excel 文件信息
            ExportParams params = new ExportParams();

            params.setTitle("说明：1、为了保证成功导入，请勿修改模板格式\n" +
                    "      2、没有父级时，父级空间编码填0\n" +
                    "      3、停用字段为下拉选择字段，不可填写选项外的内容\n" +
                    "      4、停用字段为是时，必须填写对应的停用时间，格式：yyyy-MM-dd HH:mm:ss");
            //设置导出样式
            params.setStyle(ExcelStyleUtil.class);
            //设置sheetName
            params.setTitleHeight((short) 20);
            params.setSheetName("空间成本项目");
//            FileOutputStream outputStream = new FileOutputStream("E:\\空间成本项目导入模版.xlsx");
            Workbook workbook = ExcelExportUtil.exportExcel(params, SpaceImportEntity.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 importSpaceCost(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<SpaceImportEntity> 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);
            List<SpaceImportEntity> spaceImportEntities  = ExcelImportUtil.importExcel(stream, SpaceImportEntity.class,params);
            if(!CollectionUtils.isEmpty(spaceImportEntities)){
                List<Space> saveList = new ArrayList<>();
                Space spaceCost =new Space();
                spaceCost.setHospId(UserContext.getHospId());
                spaceCost.setCreateTime(new Date());
                spaceCost.setCreateUser(String.valueOf(UserContext.getCurrentUser().getId()));
                for (SpaceImportEntity entity : spaceImportEntities) {
                    Space space = BeanUtil.convertObj(spaceCost, Space.class);
                    space.setCode(entity.getCode());
                    space.setName(entity.getName());
                    Integer status = entity.getStatus();
                    if(status == null){
                        space.setStatus(NumberConstant.ZERO);
                    }else {
                        space.setStatus(entity.getStatus());
                    }
                    space.setStopTime(entity.getStopTime());
                    space.setCost(entity.getCost());
                    space.setParentCode(entity.getParentCode());
                    space.setType(Integer.valueOf(entity.getType()));
                    space.setVolume(entity.getVolume());
                    space.setDepreciationYear(entity.getDepreciationYear());
                    if(space.getCost() != null&& space.getDepreciationYear() != null && space.getDepreciationYear().compareTo(BigDecimal.ZERO) != 0){
                        //计算每年折旧 每年折旧＝采购价格/折旧年限
                        space.setCostPerYear(calculateCostPerYear(space.getCost(),space.getDepreciationYear()));
                        //每分钟成本＝每年折旧/（365*24*60）
                        space.setCostPerMinute(calculateCostPerMinute(space.getCostPerYear()));
                    }else {
                        space.setCostPerYear(BigDecimal.ZERO);
                        space.setCostPerMinute(BigDecimal.ZERO);
                    }
                    saveList.add(space);
                }
                if(!CollectionUtils.isEmpty(saveList)){
                    check();
                    repository.saveBatch(saveList,50);
                }
            }
        } catch (Exception e) {
            throw new CostException(e.getMessage());
        }
    }

    @Override
    public List<CodeAndNameVO> getItemDict() {
        List<Space> list = repository.getList();

        if(!CollectionUtils.isEmpty(list)){
            List<CodeAndNameVO> returnList = new ArrayList<>();
            for (Space type : list) {
                CodeAndNameVO vo = new CodeAndNameVO();
                vo.setCode(type.getCode());
                vo.setName(type.getName());
                returnList.add(vo);
            }
            //添加全部
            CodeAndNameVO vo = new CodeAndNameVO();
            vo.setCode(NumberConstant.ZERO_S);
            vo.setName("全部");
            returnList.add(vo);
            return returnList;
        }
        return new ArrayList<>();    }

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

    private BigDecimal calculateCostPerYear(BigDecimal price, BigDecimal depreciationYear){
        return price.divide(depreciationYear, 4, RoundingMode.HALF_UP);

    }
    private BigDecimal calculateCostPerMinute(BigDecimal costYear){
        int minute = 365 * 24 * 60;

        return costYear.divide(BigDecimal.valueOf(minute), 4, RoundingMode.HALF_UP);

    }
}
