package com.xzzn.ems.service.impl;

import com.xzzn.common.constant.RedisKeyConstants;
import com.xzzn.common.core.redis.RedisCache;
import com.xzzn.common.utils.DateUtils;
import com.xzzn.common.utils.StringUtils;
import com.xzzn.ems.domain.EmsDailyChargeData;
import com.xzzn.ems.domain.EmsDailyEnergyData;
import com.xzzn.ems.domain.EmsEnergyPriceConfig;
import com.xzzn.ems.domain.EmsPriceTimeConfig;
import com.xzzn.ems.domain.vo.EnergyPriceTimeRange;
import com.xzzn.ems.domain.vo.EnergyPriceVo;
import com.xzzn.ems.mapper.EmsDailyChargeDataMapper;
import com.xzzn.ems.mapper.EmsDailyEnergyDataMapper;
import com.xzzn.ems.mapper.EmsEnergyPriceConfigMapper;
import com.xzzn.ems.mapper.EmsPriceTimeConfigMapper;
import com.xzzn.ems.service.IEmsEnergyPriceConfigService;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.Date;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 电价配置Service业务层处理
 *
 * @author xzzn
 * @date 2025-09-28
 */
@Service
public class EmsEnergyPriceConfigServiceImpl implements IEmsEnergyPriceConfigService
{
    @Autowired
    private EmsEnergyPriceConfigMapper emsEnergyPriceConfigMapper;
    @Autowired
    private EmsPriceTimeConfigMapper emsPriceTimeConfigMapper;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private EmsDailyChargeDataMapper emsDailyChargeDataMapper;
    @Autowired
    private EmsDailyEnergyDataMapper emsDailyEnergyDataMapper;

    /**
     * 查询电价配置
     *
     * @param id 电价配置主键
     * @return 电价配置
     */
    @Override
    public EnergyPriceVo selectEmsEnergyPriceConfigById(Long id)
    {
        EnergyPriceVo vo = new EnergyPriceVo();
        EmsEnergyPriceConfig priceConfig = emsEnergyPriceConfigMapper.selectEmsEnergyPriceConfigById(id);
        if(priceConfig != null) {
            BeanUtils.copyProperties(priceConfig,vo);
            // 时间范围
            if (priceConfig.getId() != null) {
                List<EnergyPriceTimeRange> priceVos = emsPriceTimeConfigMapper.getTimeRangeByPriceId(priceConfig.getId());
                vo.setRange(priceVos);
            }
        } else {
            return null;
        }
        return vo;
    }

    /**
     * 查询电价配置列表
     *
     * @return 电价配置
     */
    @Override
    public List<EnergyPriceVo> selectEmsEnergyPriceConfigList(String siteId,String startTime,String endTime)
    {
        List<EnergyPriceVo> responses = new ArrayList<>();
        // 根据时间截取年份
        String[] startTimeArr = startTime.split("-");
        int currentYear = Integer.valueOf(startTimeArr[0]);

        List<EmsEnergyPriceConfig> priceConfigs = emsEnergyPriceConfigMapper.getCurrentYearConfigList(siteId,currentYear);

        if (priceConfigs != null && priceConfigs.size() > 0) {
            for (EmsEnergyPriceConfig priceConfig : priceConfigs) {
                EnergyPriceVo  vo = new EnergyPriceVo();
                BeanUtils.copyProperties(priceConfig, vo);
                // 时间范围
                if (priceConfig.getId() != null) {
                    List<EnergyPriceTimeRange> priceVos = emsPriceTimeConfigMapper.getTimeRangeByPriceId(priceConfig.getId());
                    vo.setRange(priceVos);
                }
                responses.add(vo);
            }
        }

        return responses.stream()
                .sorted(Comparator.comparingInt((EnergyPriceVo vo) -> Integer.parseInt(vo.getMonth())).reversed())
                .collect(Collectors.toList());
    }

    /**
     * 新增电价配置
     *
     * @param priceVo 电价配置
     * @return 结果
     */
    @Override
    public int insertEmsEnergyPriceConfig(EnergyPriceVo priceVo)
    {
        String year = priceVo.getYear();
        String month = priceVo.getMonth();
        String siteId = priceVo.getSiteId();
        // 判断入参
        if(StringUtils.isEmpty(siteId) || StringUtils.isEmpty(year) || StringUtils.isEmpty(month)){
            return 0;
        }

        // 校验当前月电价设置是否已存在,不存在则新增，存在则更新
        EmsEnergyPriceConfig priceConfig = emsEnergyPriceConfigMapper.getConfigListByYearAndMonth(siteId,year,month);
        if (priceConfig != null){
            return 0;
        } else {
            priceConfig = new EmsEnergyPriceConfig();
        }
        BeanUtils.copyProperties(priceVo,priceConfig);
        priceConfig.setCreateTime(DateUtils.getNowDate());
        priceConfig.setUpdateTime(DateUtils.getNowDate());
        priceConfig.setCreateBy("system");
        priceConfig.setUpdateBy("system");
        emsEnergyPriceConfigMapper.insertOrUpdateEmsEnergyPriceConfig(priceConfig);

        batchInsetPriceTimeRange(priceVo,priceConfig.getId());

        // 判断是否当月电价，是则更新当月电价缓存
        int currentMonth = LocalDate.now().getMonthValue();
        if (currentMonth == Integer.parseInt(month)) {
            initCurrentMonthPrice();
        }

        return  1;
    }

    private int batchInsetPriceTimeRange(EnergyPriceVo priceVo, Long priceId) {
        List<EmsPriceTimeConfig> timeConfigs = new ArrayList<>();
        List<EnergyPriceTimeRange> rangeVos = priceVo.getRange();
        if (rangeVos != null && rangeVos.size() > 0) {
            for (EnergyPriceTimeRange rangeVo : rangeVos) {
                EmsPriceTimeConfig timeConfig = new EmsPriceTimeConfig();
                BeanUtils.copyProperties(rangeVo,timeConfig);
                timeConfig.setCreateTime(DateUtils.getNowDate());
                timeConfig.setUpdateTime(DateUtils.getNowDate());
                timeConfig.setCreateBy("system");
                timeConfig.setUpdateBy("system");
                timeConfig.setPriceId(priceId);
                timeConfigs.add(timeConfig);
            }
        }
        // 批量插入
        return emsPriceTimeConfigMapper.batchInsert(timeConfigs);
    }

    /**
     * 修改电价配置
     *
     * @param priceVo 电价配置
     * @return 结果
     */
    @Override
    public int updateEmsEnergyPriceConfig(EnergyPriceVo priceVo)
    {
        if (priceVo == null || priceVo.getId() == null) {
            return 0;
        }
        // 不存在
        EmsEnergyPriceConfig priceConfig = emsEnergyPriceConfigMapper.selectEmsEnergyPriceConfigById(priceVo.getId());
        if (priceConfig == null) {
            return 0;
        }

        // 存在更新
        BeanUtils.copyProperties(priceVo, priceConfig);
        priceConfig.setUpdateTime(DateUtils.getNowDate());
        priceConfig.setUpdateBy("system");
        emsEnergyPriceConfigMapper.updateEmsEnergyPriceConfig(priceConfig);

        // 时间配置，全删，全插入
        Long[] priceIds = {priceVo.getId()};
        emsPriceTimeConfigMapper.deleteTimeRangeByPriceId(priceIds);
        batchInsetPriceTimeRange(priceVo,priceConfig.getId());

        // 判断是否当月电价，是则更新当月电价缓存
        int currentMonth = LocalDate.now().getMonthValue();
        if (currentMonth == Integer.parseInt(priceVo.getMonth())) {
            initCurrentMonthPrice();
        }
        return  1;
    }

    /**
     * 批量删除电价配置
     *
     * @param ids 需要删除的电价配置主键
     * @return 结果
     */
    @Override
    public int deleteEmsEnergyPriceConfigByIds(Long[] ids)
    {
        // 先删时间配置
        emsPriceTimeConfigMapper.deleteTimeRangeByPriceId(ids);
        // 再删月电价
        emsEnergyPriceConfigMapper.deleteEmsEnergyPriceConfigByIds(ids);
        // 更新当月电价缓存
        initCurrentMonthPrice();
        return 1;
    }

    /**
     * 删除电价配置信息
     *
     * @param id 电价配置主键
     * @return 结果
     */
    @Override
    public int deleteEmsEnergyPriceConfigById(Long id)
    {
        return emsEnergyPriceConfigMapper.deleteEmsEnergyPriceConfigById(id);
    }

    /**
     * 初始化当月的电价存redis
     */
    @Override
    public void initCurrentMonthPrice() {
        // 获取当年和当月的电价
        int currentMonth = LocalDate.now().getMonthValue();
        int currentYear = LocalDate.now().getYear();

        List<EmsEnergyPriceConfig> siteIdConfig  = emsEnergyPriceConfigMapper.getAllSitePriceConfig(currentYear,currentMonth);
        if (siteIdConfig == null || siteIdConfig.size() == 0) {
            return;
        }
        for (EmsEnergyPriceConfig priceConfig : siteIdConfig) {
            EnergyPriceVo priceVo = new EnergyPriceVo();
            BeanUtils.copyProperties(priceConfig,priceVo);
            String siteId = priceConfig.getSiteId();
            List<EnergyPriceTimeRange> timeRanges = emsEnergyPriceConfigMapper.getTimeRangeByDate(siteId,currentYear,currentMonth);
            priceVo.setRange(timeRanges);
            String key = RedisKeyConstants.ENERGY_PRICE_TIME + siteId + "_" + currentYear + currentMonth;
            redisCache.setCacheObject(key,priceVo, 31, TimeUnit.DAYS);
        }

    }

    public EnergyPriceVo getCurrentMonthPrice(String siteId) {
        EnergyPriceVo  priceVo = new EnergyPriceVo();
        // 获取当年和当月的电价
        int currentMonth = LocalDate.now().getMonthValue();
        int currentYear = LocalDate.now().getYear();

        EmsEnergyPriceConfig  priceConfig = emsEnergyPriceConfigMapper.getConfigListByYearAndMonth(siteId,String.valueOf(currentYear),String.valueOf(currentMonth));
        if (priceConfig != null) {
            BeanUtils.copyProperties(priceConfig,priceVo);
            List<EnergyPriceTimeRange> timeRanges = emsPriceTimeConfigMapper.getTimeRangeByPriceId(priceConfig.getId());
            priceVo.setRange(timeRanges);
        }
        return priceVo;
    }

    @Override
    public Map<String, BigDecimal> getDayRevenueMap(String siteId) {
        Map<String, BigDecimal> currentDayRevenue = new HashMap<>();
        // 默认0
        BigDecimal totalRevenue = BigDecimal.ZERO;
        BigDecimal dayRevenue = BigDecimal.ZERO;
        BigDecimal yesterdayRevenue = BigDecimal.ZERO;
        // 获取昨日数据
        Date yesterday = DateUtils.toDate(LocalDate.now().minusDays(1));
        EmsDailyChargeData yesterdayData = emsDailyChargeDataMapper.selectBySiteIdAndDateTime(siteId, yesterday);
        if (yesterdayData != null) {
            yesterdayRevenue = yesterdayData.getDayRevenue() ==  null ? BigDecimal.ZERO : yesterdayData.getDayRevenue();
        }

        // 当日实时数据
        String today = DateUtils.getDate();
        Map<String, BigDecimal> lastData = emsDailyEnergyDataMapper.getRealTimeRevenue(siteId);
        if (lastData != null) {
            totalRevenue = lastData.get("totalRevenue") == null ? BigDecimal.ZERO : lastData.get("totalRevenue");
        }

        EmsDailyEnergyData todayData = emsDailyEnergyDataMapper.getDataByDate(siteId,today);
        if (todayData != null) {
            // 获取当月电价
            int currentMonth = LocalDate.now().getMonthValue();
            int currentYear = LocalDate.now().getYear();
            EmsEnergyPriceConfig priceConfig = emsEnergyPriceConfigMapper.getConfigListByYearAndMonth(siteId, String.valueOf(currentYear), String.valueOf(currentMonth));
            if (priceConfig != null) {
                // 计算各个时段单独收益=（放电量-充电量）*电价,累加即当日实时收益
                BigDecimal peakRevenue = todayData.getPeakDischargeDiff().subtract(todayData.getPeakChargeDiff())
                        .multiply(priceConfig.getPeak() == null ? BigDecimal.ZERO : priceConfig.getPeak());
                BigDecimal highRevenue = todayData.getHighDischargeDiff().subtract(todayData.getHighChargeDiff())
                        .multiply(priceConfig.getHigh() == null ? BigDecimal.ZERO : priceConfig.getHigh());
                BigDecimal flatRevenue = todayData.getFlatDischargeDiff().subtract(todayData.getFlatChargeDiff())
                        .multiply(priceConfig.getFlat() == null ? BigDecimal.ZERO : priceConfig.getFlat());
                BigDecimal valleyRevenue = todayData.getValleyDischargeDiff().subtract(todayData.getValleyChargeDiff())
                        .multiply(priceConfig.getValley() == null ? BigDecimal.ZERO : priceConfig.getValley());
                dayRevenue = dayRevenue.add(peakRevenue).add(highRevenue).add(flatRevenue).add(valleyRevenue)
                        .setScale(4, RoundingMode.HALF_UP);
            }
        }
        currentDayRevenue.put("totalRevenue", totalRevenue);
        currentDayRevenue.put("dayRevenue", dayRevenue);
        currentDayRevenue.put("yesterdayRevenue", yesterdayRevenue);
        return  currentDayRevenue;
    }
}
