package com.jjt.elec.service.impl;

import com.jjt.common.utils.StringUtils;
import com.jjt.elec.domain.ElecPeriod;
import com.jjt.elec.domain.ElecPrice;
import com.jjt.elec.mapper.ElecPriceMapper;
import com.jjt.elec.service.IElecPeriodService;
import com.jjt.elec.service.IElecPriceService;
import javafx.util.Pair;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * 电费价格配置Service业务层处理
 *
 * @author wukai
 * @date 2025-03-14
 */
@Service
public class ElecPriceServiceImpl implements IElecPriceService {
    @Resource
    private ElecPriceMapper elecPriceMapper;
    @Resource
    private IElecPeriodService periodService;

    /**
     * 查询电费价格配置
     *
     * @param priceId 电费价格配置主键
     * @return 电费价格配置
     */
    @Override
    public ElecPrice selectElecPriceByPriceId(Long priceId) {
        return elecPriceMapper.selectElecPriceByPriceId(priceId);
    }

    /**
     * 查询电费价格配置列表
     *
     * @param elecPrice 电费价格配置
     * @return 电费价格配置
     */
    @Override
    public List<ElecPrice> selectElecPriceList(ElecPrice elecPrice) {
        return elecPriceMapper.selectElecPriceList(elecPrice);
    }

    /**
     * 新增电费价格配置
     *
     * @param elecPrice 电费价格配置
     * @return 结果
     */
    @Override
    public int insertElecPrice(ElecPrice elecPrice) {
        return elecPriceMapper.insertElecPrice(elecPrice);
    }

    /**
     * 修改电费价格配置
     *
     * @param elecPrice 电费价格配置
     * @return 结果
     */
    @Override
    public int updateElecPrice(ElecPrice elecPrice) {
        return elecPriceMapper.updateElecPrice(elecPrice);
    }

    /**
     * 批量删除电费价格配置
     *
     * @param priceIds 需要删除的电费价格配置主键
     * @return 结果
     */
    @Override
    public int deleteElecPriceByPriceIds(Long[] priceIds) {
        return elecPriceMapper.deleteElecPriceByPriceIds(priceIds);
    }

    /**
     * 删除电费价格配置信息
     *
     * @param priceId 电费价格配置主键
     * @return 结果
     */
    @Override
    public int deleteElecPriceByPriceId(Long priceId) {
        return elecPriceMapper.deleteElecPriceByPriceId(priceId);
    }

    /**
     * 根据时间获取时段价格列表
     * 0-23 表示电价
     * 100 工业水价
     * 210 低压蒸汽价
     * 220 中压蒸汽价
     *
     * @param localDate 时间，只取月份
     * @return 电价
     */
    @Override
    public Map<Integer, Pair<String, BigDecimal>> getPrice(LocalDate localDate) {
        ElecPeriod period = periodService.selectElecPeriodByPeriodId(1L);
        int year = localDate.getYear();
        int month = localDate.getMonthValue();
        ElecPrice priceObj = selectElecPriceByMonth(year, month);

        // 判断月份是春秋还是夏冬
        boolean isSummerAutumn = getNumbers(period.getSaMonths(), PeriodType.MONTH).contains(month);

        // 根据月份和时段获取价格
        Map<Integer, Pair<String, BigDecimal>> result;
        // 根据月份和时段获取价格
        if (isSummerAutumn) {
            result = getPriceByPeriod(period.getSaPeak(), period.getSaFlat(), period.getSaValley(), period.getSaSuperPeak(), priceObj);
        } else {
            result = getPriceByPeriod(period.getSwPeak(), period.getSwFlat(), period.getSwValley(), period.getSwSuperPeak(), priceObj);
        }
        result.put(100, new Pair<>("water", priceObj.getWaterPrice()));
        result.put(210, new Pair<>("lowStream", priceObj.getLowStreamPrice()));
        result.put(220, new Pair<>("midStream", priceObj.getMidStreamPrice()));
        return result;

    }

    /**
     * 根据时段获取价格
     */
    private Map<Integer, Pair<String, BigDecimal>> getPriceByPeriod(String peakPeriod, String flatPeriod, String valleyPeriod, String superPeakPeriod, ElecPrice priceObj) {
        Map<Integer, Pair<String, BigDecimal>> map = new HashMap<>();
        addPricesToMap(map, peakPeriod, priceObj.getPricePeak(), PeriodType.HOUR, "peak");
        addPricesToMap(map, flatPeriod, priceObj.getPriceFlat(), PeriodType.HOUR, "flat");
        addPricesToMap(map, valleyPeriod, priceObj.getPriceValley(), PeriodType.HOUR, "valley");
        addPricesToMap(map, superPeakPeriod, priceObj.getPriceSuperPeak(), PeriodType.HOUR, "superPeak");
        return map;
    }

    /**
     * 将指定时段的价格添加到Map中
     */
    private void addPricesToMap(Map<Integer, Pair<String, BigDecimal>> map, String period, BigDecimal price, PeriodType periodType, String type) {
        getNumbers(period, periodType).forEach(hour -> map.put(hour, new Pair<>(type, price)));
    }

    /**
     * 解析 1-8,9-11这种数据
     * 如果是月份,则包含头尾，如果是小时，则不包含尾部
     *
     * @param data 字符串
     * @param type 时段类型
     * @return 时段集合
     */
    private Set<Integer> getNumbers(String data, PeriodType type) {
        if (StringUtils.isEmpty(data)) {
            return Collections.emptySet();
        }

        return Arrays.stream(data.split(","))
                .flatMap(s -> {
                    String[] range = s.split("-");
                    if (range.length > 1) {
                        int start = Integer.parseInt(range[0]);
                        int end = Integer.parseInt(range[1]);
                        if (type == PeriodType.HOUR) {
                            end = end - 1;
                        }
                        return IntStream.rangeClosed(start, end).boxed();
                    } else {
                        return Stream.of(Integer.parseInt(range[0]));
                    }
                })
                .collect(Collectors.toSet());
    }

    /**
     * 根据年月获取价格
     *
     * @param year  年
     * @param month 月
     * @return 结果
     */
    @Override
    public ElecPrice selectElecPriceByMonth(int year, int month) {
        String monthStr = year + "-" + (month < 10 ? "0" + month : month);
        ElecPrice search = new ElecPrice();
        search.setPriceMonth(monthStr);
        List<ElecPrice> list = selectElecPriceList(search);
        ElecPrice elecPrice;
        if (list.size() == 0) {
            //如果未找到，则取最后一条记录
            list = selectElecPriceList(new ElecPrice());
            elecPrice = list.get(0);
            elecPrice.setPriceMonth(monthStr);
            elecPrice.setPriceId(null);
            insertElecPrice(elecPrice);
        } else {
            elecPrice = list.get(0);
        }
        return elecPrice;
    }

    enum PeriodType {
        /**
         * 月份
         */
        MONTH,
        /**
         * 小时
         */
        HOUR
    }
}
