package com.ho.business.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.ho.business.common.BusiTool;
import com.ho.business.entity.*;
import com.ho.business.feignclient.UserFeignClient;
import com.ho.business.mapper.EarningsCalculateMapper;
import com.ho.business.mapper.ElecTemplateMapper;
import com.ho.business.mapper.ElecTemplateSubMapper;
import com.ho.business.mapper.IndustrialElecPriceMapper;
import com.ho.business.service.ElecPriceCurveService;
import com.ho.business.service.StationService;
import com.ho.business.vo.RegionData;
import com.ho.business.vo.req.elecPriceCurve.BatchDeleteReq;
import com.ho.business.vo.req.elecPriceCurve.ElecPriceTemplateReq;
import com.ho.business.vo.req.elecPriceCurve.ElecPriceTemplateReqVO;
import com.ho.business.vo.req.industrialElec.IndustrialElecPriceReqVo;
import com.ho.business.vo.resp.StationRespVO;
import com.ho.business.vo.resp.elecPriceCurve.ElecPriceTemplate;
import com.ho.business.vo.resp.elecPriceCurve.ElecPriceTemplateExcel;
import com.ho.common.tools.constant.CommonConstant;
import com.ho.common.tools.exception.BaseResponseCode;
import com.ho.common.tools.exception.BusinessException;
import com.ho.user.api.vo.req.SysSubDictVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 电价曲线模板设置实现
 * Author yule
 * Date 2023/4/19 14:30
 */
@Service
@Slf4j
public class ElecPriceCurveServiceImpl implements ElecPriceCurveService {

    public static final String TEMPLATE_NAME = "当月电网电价";

    private static final String ELEC_TYPE = "1";

    @Autowired
    StationService stationService;

    @Autowired
    ElecTemplateMapper elecTemplateMapper;

    @Autowired
    ElecTemplateSubMapper elecTemplateSubMapper;

    @Autowired
    EarningsCalculateMapper earningsCalculateMapper;

    @Autowired
    BusiTool busiTool;

    @Autowired
    UserFeignClient userFeignClient;

    @Autowired
    IndustrialElecPriceMapper industrialElecPriceMapper;

    private static Map<String, String> staticMap = new HashMap<>(0);

    public static final String DICT_TYPE = "electrovalence_type";

    @Override
    @Transactional
    public void add(ElecPriceTemplate elecPriceTemplate) {
        if( elecPriceTemplate == null || elecPriceTemplate.getList() == null || elecPriceTemplate.getList().size() == 0 ){
            throw new BusinessException(BaseResponseCode.ELEC_TEMPLATE_LIST_NON);
        }
        if( elecPriceTemplate.getIsEnable() == null ){
            elecPriceTemplate.setIsEnable(0);
        }
        //电站id不能为空
       if (elecPriceTemplate.getStationId() == null){
           throw new BusinessException(BaseResponseCode.PLEASE_SELECT_STATION);
       }
       /** todo: 模板名称不能为空 */
        if( elecPriceTemplate != null && ( elecPriceTemplate.getTemplateName() == null ||  elecPriceTemplate.getTemplateName().equals("")) ){
            throw new BusinessException(BaseResponseCode.TEMPALTE_NAME_NON);
        }
        //判断模板名称是否重复
        ElecTemplate template = elecTemplateMapper.selectByTemplateName(elecPriceTemplate.getTemplateName(), elecPriceTemplate.getStationId());
        if (template != null) {
            throw new BusinessException(BaseResponseCode.NON_REPETITIVE_TEMPLATE_NAME);
        }
        /**
         * 增加此处逻辑后,整个方法逻辑改成,如果开始和节数时间不互相涵盖的话可以启用多份
         */
        // 判断模板的起始时间是否有互相涵盖,如果互相涵盖了给出提示并终止操作
        if( elecPriceTemplate.getIsEnable() == 1){
            List<ElecTemplate> elecTemplates = elecTemplateMapper.queryTemplatesByStationId(elecPriceTemplate);
            if( elecTemplates != null && elecTemplates.size() > 0 ){
                throw new BusinessException(BaseResponseCode.ELEC_TEMPLATE_TIME_CLASH);
            }
        }
        if(elecPriceTemplate.getDiscount() != null){
            elecPriceTemplate.setDiscount(elecPriceTemplate.getDiscount());
        }

        //判断电价时间段 开始时间是否为00:00 结束时间为24:00
        List<ElecTemplateSub> list = elecPriceTemplate.getList();
        boolean beginFlag = false;
        boolean endFlag = false;
        for (ElecTemplateSub elecTemplateSub : list) {
            String beginTime = elecTemplateSub.getBeginTime();
            if (CommonConstant.BEGIN_MINUTES_DAY.equals(beginTime)) {
                beginFlag = true;
            }
            String endTime = elecTemplateSub.getEndTime();
            if (CommonConstant.END_DAY.equals(endTime) || CommonConstant.END_MINUTES_DAY.equals(endTime)) {
                endFlag = true;
            }
        }
        if (beginFlag && endFlag) {
            //新增模板数据
            //获取电价模板编号
            String templateNo = busiTool.getNextPriceTemplateId(CommonConstant.IdTypePriceTemplate);
            ElecTemplate elecTemplate = new ElecTemplate();
            BeanUtils.copyProperties(elecPriceTemplate, elecTemplate);
            elecTemplate.setTemplateNo(templateNo);
            elecTemplate.setCreateTime(new Date());
            elecTemplate.setUpdateTime(new Date());


            // 判断模板是否启用，如果是就修改别的模板为不启用
//            if( elecTemplate.getIsEnable() == 1){
//                elecTemplateMapper.updateIsEnabled(elecTemplate);
//            }
            elecTemplateMapper.insertSelective(elecTemplate);
            //新增电站数据
            list = list.stream().map(s -> {
                s.setPid(elecTemplate.getId());
                String type = s.getType();
                if (type.length() > 10){
                    throw new BusinessException(BaseResponseCode.TYPE_TOO_LONG);
                }
                BigDecimal price = s.getPrice();
                if( s.getPrice() == null ){
                    throw new BusinessException(BaseResponseCode.PRICE_IS_NULL);
                }
                if (price.compareTo(new BigDecimal(999999))  > 0){
                    throw new BusinessException(BaseResponseCode.PRICE_TOO_LONG);
                }
                return s;
            }).collect(Collectors.toList());
            elecTemplateSubMapper.insertList(list);
        } else {
            throw new BusinessException(BaseResponseCode.TIME_FORMAT_INCORRECT);
        }
    }

    @Override
    @Transactional
    public Map<String,Object> deleted(ElecPriceTemplateReq elecPriceTemplateReq) {
        Map<String,Object> result = new HashMap<>(0);
        result.put("code","200");
        result.put("msg","删除成功");
        int i = elecTemplateMapper.checkTemplate(elecPriceTemplateReq);
        if( i > 0 ){
            result.put("code","204");
            result.put("msg","模板已经启用不可删除！");
            return result;
        }
        //先删除模板数据
        elecTemplateMapper.deleteByPrimaryKey(elecPriceTemplateReq.getId());
        //再删除电价数据
        elecTemplateSubMapper.deletedByPid(elecPriceTemplateReq.getId());
        return result;
    }

    @Override
    @Transactional
    public void update(ElecPriceTemplate elecPriceTemplate) {
        if( elecPriceTemplate == null || elecPriceTemplate.getList() == null || elecPriceTemplate.getList().size() == 0 ){
            throw new BusinessException(BaseResponseCode.ELEC_TEMPLATE_LIST_NON);
        }
        ElecTemplate elecTemplate = new ElecPriceTemplate();
        BeanUtils.copyProperties(elecPriceTemplate, elecTemplate);
        elecTemplate.setUpdateTime(new Date());

        /**
         * 校验编辑后是否与自己的模板重名
         */
        Integer count = elecTemplateMapper.checkTemplateName(elecTemplate);
        if( count > 0 ){
            throw new BusinessException(BaseResponseCode.NON_REPETITIVE_TEMPLATE_NAME);
        }
        /**
         * 如果模板为启用,那么就校验一下当前需要启用的模板有效时间是否与其他模板重叠,如果有则取消操作
         */
        if (elecTemplate.getIsEnable() == 1) {
            List<ElecTemplate> elecTemplates = elecTemplateMapper.queryTemplatesByStationId(elecPriceTemplate);
            if( elecTemplates != null && elecTemplates.size() > 0 ){
                throw new BusinessException(BaseResponseCode.ELEC_TEMPLATE_TIME_CLASH);
            }
        }
        if(elecPriceTemplate.getDiscount() != null){
            elecPriceTemplate.setDiscount(elecPriceTemplate.getDiscount()/100);
        }
        // 判断模板是否启用，如果是就修改别的模板为不启用
//        if( elecTemplate.getIsEnable() == 1){
//            elecTemplateMapper.updateIsEnabled(elecTemplate);
//        }
        //先修改模板数据
        elecTemplateMapper.updateByPrimaryKeySelective(elecTemplate);
        //先删除电价数据
        elecTemplateSubMapper.deletedByPid(elecPriceTemplate.getId());
        //在新增电价数据
        List<ElecTemplateSub> list = elecPriceTemplate.getList();
        for (ElecTemplateSub elecTemplateSub : list) {
            String type = elecTemplateSub.getType();
            if (type.length() > 10){
                throw new BusinessException(BaseResponseCode.TYPE_TOO_LONG);
            }
            if (elecTemplateSub.getPrice().compareTo(new BigDecimal(999999))  > 0){
                throw new BusinessException(BaseResponseCode.PRICE_TOO_LONG);
            }
            elecTemplateSub.setPid(elecPriceTemplate.getId());
        }
        elecTemplateSubMapper.insertList(list);
    }

    @Override
    public ElecPriceTemplate getOne(ElecPriceTemplateReq elecPriceTemplateReq) {
        ElecTemplate elecTemplate = elecTemplateMapper.selectByPrimaryKey(elecPriceTemplateReq.getId());
        if (elecTemplate == null) {
            throw new BusinessException(BaseResponseCode.ELEC_TEMPLATE_DOES_NOT_EXIST);
        }
        //创建返回值对象
        ElecPriceTemplate elecPriceTemplate = new ElecPriceTemplate();
        //查询电站
        Station station = stationService.selectById(elecTemplate.getStationId());
        if (station != null) {
            elecPriceTemplate.setStationName(station.getName());
        }
        //查询电价数据
        List<ElecTemplateSub> list = elecTemplateSubMapper.selectByPid(elecTemplate.getId());
        BeanUtils.copyProperties(elecTemplate, elecPriceTemplate);
        elecPriceTemplate.setList(list);
        return elecPriceTemplate;
    }

    @Override
    public List<ElecPriceTemplate> getAll(ElecPriceTemplateReqVO vo) {
        //根据条件查询模板
        List<ElecTemplate> elecTemplates = elecTemplateMapper.selectByInfo(vo);
        //电站id集合
        List<Integer> stationIds = elecTemplates.stream().map(ElecTemplate::getStationId).collect(Collectors.toList());
        //查询电站
        List<StationRespVO> stationRespVOS = stationService.selectByIds(stationIds,null);
        Map<Integer, List<StationRespVO>> stationMap = stationRespVOS.stream().collect(Collectors.groupingBy(StationRespVO::getId));
        //模板id的集合
        List<Integer> elecTemplateIds = elecTemplates.stream().map(ElecTemplate::getId).collect(Collectors.toList());
        List<ElecTemplateSub> ElecTemplateSubs = new ArrayList<>();
        if (!elecTemplateIds.isEmpty()) {
            //根据pid查询电价数据
            ElecTemplateSubs = elecTemplateSubMapper.selectByPids(elecTemplateIds);
        }
        //根据pid分组
        Map<Integer, List<ElecTemplateSub>> elecTemplateSubMap = ElecTemplateSubs.stream().filter(s -> !Objects.isNull(s.getPid())).collect(Collectors.groupingBy(ElecTemplateSub::getPid));
        //创建返回值集合
        List<ElecPriceTemplate> list = new ArrayList<>();
        for (ElecTemplate elecTemplate : elecTemplates) {
            //属性赋值
            ElecPriceTemplate elecPriceTemplate = new ElecPriceTemplate();
            BeanUtils.copyProperties(elecTemplate, elecPriceTemplate);
            //电站名称赋值
            List<StationRespVO> stationList = stationMap.get(elecTemplate.getStationId());
            if (stationList != null) {
                elecPriceTemplate.setStationName(stationList.get(0).getName());
            }
            //电价赋值
            elecPriceTemplate.setList(elecTemplateSubMap.get(elecTemplate.getId()));
            list.add(elecPriceTemplate);
        }
        return list;
    }

    @Override
    public void importExcel(List<ElecPriceTemplateExcel> excelList) {
        //获取全部模板名称集合
        Set<String> templateNameSet = excelList.stream().map(ElecPriceTemplateExcel::getTemplateName).collect(Collectors.toSet());
        //根据模板名称进行分组
        Map<String, List<ElecPriceTemplateExcel>> excelMap = excelList.stream().collect(Collectors.groupingBy(ElecPriceTemplateExcel::getTemplateName));
        List<ElecPriceTemplate> elecPriceTemplates = new ArrayList<>();
        //组装为存储的对象
        for (String templateName : templateNameSet) {
            //穿件需要存储对象
            ElecPriceTemplate elecPriceTemplate = new ElecPriceTemplate();
            List<ElecPriceTemplateExcel> elecPriceTemplateExcels = excelMap.get(templateName);
            BeanUtils.copyProperties(elecPriceTemplateExcels.get(0), elecPriceTemplate);
            if (CommonConstant.IS_ENABLE.equals(elecPriceTemplateExcels.get(0).getIsEnable())) {
                elecPriceTemplate.setIsEnable(CommonConstant.ONE);
            } else if (CommonConstant.NOT_IS_ENABlE.equals(elecPriceTemplateExcels.get(0).getIsEnable())) {
                elecPriceTemplate.setIsEnable(CommonConstant.ZERO);
            }
            //创建需要存储的电价对象集合
            List<ElecTemplateSub> elecTemplateSubs = new ArrayList<>();
            for (ElecPriceTemplateExcel elecPriceTemplateExcel : elecPriceTemplateExcels) {
                ElecTemplateSub elecTemplateSub = new ElecTemplateSub();
                BeanUtils.copyProperties(elecPriceTemplateExcel, elecTemplateSub);
                elecTemplateSub.setPrice(new BigDecimal(elecPriceTemplateExcel.getPrice()));
                elecTemplateSubs.add(elecTemplateSub);
            }
            elecPriceTemplate.setList(elecTemplateSubs);

            elecPriceTemplate.setElecType(ELEC_TYPE);
            elecPriceTemplates.add(elecPriceTemplate);
        }
        for (ElecPriceTemplate elecPriceTemplate : elecPriceTemplates) {
            add(elecPriceTemplate);
        }
        System.out.println();
    }

    @Override
    @Transactional
    public void batchDelete(BatchDeleteReq elecPriceTemplateReq) {
        List<Integer> ids = elecPriceTemplateReq.getIds();
        if (ids != null && !ids.isEmpty()) {
            elecTemplateMapper.deleteByIds(ids);
            elecTemplateSubMapper.deletedByPids(ids);
        }
    }

    @Override
    public List<ElecPriceTemplate> getListByIds(BatchDeleteReq batchDeleteReq) {
        List<Integer> ids = batchDeleteReq.getIds();
        //判断入参是否为空
        if (ids == null || ids.isEmpty()) {
            throw new BusinessException(BaseResponseCode.NON_DATA);
        }
        ElecPriceTemplateReqVO query = new ElecPriceTemplateReqVO();
        query.setIds(ids);
        List<ElecPriceTemplate> list = getAll(query);
        return list;
    }

    @Override
    public ElecPriceTemplate addSearch(Integer stationId) {
        ElecPriceTemplate elecPriceTemplate = new ElecPriceTemplate();
        Station station = stationService.selectById(stationId);
        // 如果电站就是空就直接return
        if( station == null ){
            return new ElecPriceTemplate();
        }
        Date thisDate = new Date();
        // 取当前时间的格式化字符串日期,确定当前时间正在使用的国网模板是哪一个
        String date = DateUtil.format(thisDate, "yyyy-MM");
        // 获取当月第一天和最后一天
        DateTime beginTime = DateUtil.beginOfMonth(DateUtil.date());
        DateTime endTime = DateUtil.endOfMonth(DateUtil.date());
        // 国网电价可能出现用省,市,区,县各级别电价的,如果是县级那么县的判断为区+县拼接的字符串
        IndustrialElecPriceReqVo vo = new IndustrialElecPriceReqVo();
        vo.setExecutionTime(date);
        if ( station.getVoltageLevel() != null ) {
            vo.setVoltageLevel(station.getVoltageLevel());
        }
        if ( station.getCustomerType() != null ) {
            vo.setCustomerType(station.getCustomerType());
        }
        if ( station.getElectricityType() != null ) {
            vo.setElectricityType(station.getElectricityType());
        }
        RegionData regionData = earningsCalculateMapper.queryRegionDataByDistrict(station.getDistrict(),station.getCity(),station.getProvince());
        Integer regionId = this.getRegionId(regionData);
        vo.setRegionId(regionId);
        IndustrialElecPrice byCondition = industrialElecPriceMapper.findByCondition(vo);
        List<ElecTemplateSub> earningsCalculateSubs = processElecTemplateSubDatas(byCondition);
        elecPriceTemplate.setList(earningsCalculateSubs);
        // 保存一些模板的默认数据
        elecPriceTemplate.setTemplateName(TEMPLATE_NAME);
        elecPriceTemplate.setIsEnable(1);
        elecPriceTemplate.setTemplateType(0);
        elecPriceTemplate.setElecType("1");
        // 有效期开始时间
        elecPriceTemplate.setValidityStartTime(beginTime);
        // 有效期结束时间
        elecPriceTemplate.setValidityEndTime(endTime);
        elecPriceTemplate.setStationId(stationId);
        return elecPriceTemplate;
    }

    private Integer getRegionId(RegionData regionData){
        // 根据regionID来判断使用什么电价,如果更小级别地区有的,就用最小级别的
        Integer regionId = 0;
        if( regionData != null ){
            // 此处利用程序的执行顺序,按照省-市-区的顺序来获取regionId,最终需要使用的是最小级别的regionId,请勿轻易修改,如果要修改请确认逻辑
            if( regionData.getProvinceRegionId() != null ){
                regionId = regionData.getProvinceRegionId();
            }
            if( regionData.getCityRegionId() != null ){
                regionId = regionData.getCityRegionId();
            }
            if( regionData.getDistrictRegionId() != null ){
                regionId = regionData.getDistrictRegionId();
            }
        }
        return regionId;
    }

    private List<ElecTemplateSub> processElecTemplateSubDatas(IndustrialElecPrice condition){
        List<ElecTemplateSub> earningsCalculateSubs = new ArrayList<>(0);
        // 先判断内存是否已经有了,如果没有则查询一次放进内存
        if( staticMap.size() == 0 ){
            SysSubDictVO vo = new SysSubDictVO();
            vo.setType(DICT_TYPE);
            staticMap = userFeignClient.getSysSubDict(vo);
        }
        if( condition != null  ){
            // 尖
            if( condition.getSpikePrice() != null && !"".equals(condition.getSpikePrice()) && condition.getSpikePriceInterval() != null && !"".equals(condition.getSpikePriceInterval())){
                String spikePriceInterval = condition.getSpikePriceInterval();
                String spikePriceName = staticMap.get("1") != null ? staticMap.get("1") : "尖峰时段";
                BigDecimal spikePrice = condition.getSpikePrice();
                List<ElecTemplateSub> list = this.splitInterval(spikePriceInterval, spikePriceName, spikePrice);
                earningsCalculateSubs.addAll(list);
            }
            // 峰
            if( condition.getPeakPrice() != null && !"".equals(condition.getPeakPrice()) && condition.getPeakPriceInterval() != null && !"".equals(condition.getPeakPriceInterval())){
                String peakPriceInterval = condition.getPeakPriceInterval();
                String peakPriceName = staticMap.get("2") != null ? staticMap.get("2") : "高峰时段";
                BigDecimal peakPrice = condition.getPeakPrice();
                List<ElecTemplateSub> list = this.splitInterval(peakPriceInterval, peakPriceName, peakPrice);
                earningsCalculateSubs.addAll(list);
            }
            // 平
            if( condition.getRegularPrice() != null && !"".equals(condition.getRegularPrice()) && condition.getRegularPriceInterval() != null && !"".equals(condition.getRegularPriceInterval())){
                String regularPriceInterval = condition.getRegularPriceInterval();
                String regularPriceName = staticMap.get("3") != null ? staticMap.get("3") : "平时段";
                BigDecimal regularPrice = condition.getRegularPrice();
                List<ElecTemplateSub> list = this.splitInterval(regularPriceInterval, regularPriceName, regularPrice);
                earningsCalculateSubs.addAll(list);
            }
            // 谷
            if( condition.getLowValleyPrice() != null && !"".equals(condition.getLowValleyPrice()) && condition.getLowValleyPriceInterval() != null && !"".equals(condition.getLowValleyPriceInterval())){
                String lowValleyPriceInterval = condition.getLowValleyPriceInterval();
                String lowValleyPriceName = staticMap.get("4") != null ? staticMap.get("4") : "低谷时段";
                BigDecimal lowValleyPrice = condition.getLowValleyPrice();
                List<ElecTemplateSub> list = this.splitInterval(lowValleyPriceInterval, lowValleyPriceName, lowValleyPrice);
                earningsCalculateSubs.addAll(list);
            }
            // 深谷
            if( condition.getDeepValleyPrice() != null && !"".equals(condition.getDeepValleyPrice()) && condition.getDeepValleyPriceInterval() != null && !"".equals(condition.getDeepValleyPriceInterval())){
                String deepValleyPriceInterval = condition.getDeepValleyPriceInterval();
                String deepValleyPriceName = staticMap.get("5") != null ? staticMap.get("5") : "深谷时段";
                BigDecimal deepValleyPrice = condition.getDeepValleyPrice();
                List<ElecTemplateSub> list = this.splitInterval(deepValleyPriceInterval, deepValleyPriceName, deepValleyPrice);
                earningsCalculateSubs.addAll(list);
            }
        }
        /** todo: 对得到的最终结果进行排序并返回 */
        this.sortList(earningsCalculateSubs);
        return earningsCalculateSubs;
    }

    /**
     * @param interval
     * @param name
     * @param price
     * @return
     */
    private List<ElecTemplateSub> splitInterval(String interval, String name,BigDecimal price){
        List<ElecTemplateSub> list = new ArrayList<>(0);
        String[] split = interval.split(",");
        Arrays.stream(split).forEach(s->{
            ElecTemplateSub sub = new ElecTemplateSub();
            String startTime = s.substring(0,s.indexOf("-"));
            String endTime = s.substring(s.indexOf("-")+1,s.length());
            sub.setBeginTime(startTime);
            sub.setEndTime(endTime);
            sub.setType(name);
            sub.setPrice(price);
            list.add(sub);
        });
        return list;
    }

    /**
     * 对集合进行排序
     * @param elecTemplateSubs
     */
    private void sortList(List<ElecTemplateSub> elecTemplateSubs){
        Collections.sort(elecTemplateSubs, new Comparator<ElecTemplateSub>() {
            @Override
            public int compare(ElecTemplateSub p1, ElecTemplateSub p2) {
                String[] time1 = p1.getBeginTime().split(":");
                String[] time2 = p2.getBeginTime().split(":");
                int hour1 = Integer.parseInt(time1[0]);
                int minute1 = Integer.parseInt(time1[1]);
                int hour2 = Integer.parseInt(time2[0]);
                int minute2 = Integer.parseInt(time2[1]);
                return (hour1 * 60 + minute1) - (hour2 * 60 + minute2);
            }
        });
    }
}
