/*
 * 文 件 名:  PriceServiceImpl
 * 版    权:  华设设计集团股份有限公司
 * 描    述:  <描述>
 * 修 改 人:  lvwenbin
 * 修改时间:  2025/3/10
 * 跟踪单号:  <跟踪单号>
 * 修改单号:  <修改单号>
 * 修改内容:  <修改内容>
 */
package com.ruoyi.ems.service.impl;

import com.huashe.common.exception.Assert;
import com.huashe.common.exception.BusinessException;
import com.huashe.common.utils.DateUtils;
import com.ruoyi.ems.domain.ElecAttr;
import com.ruoyi.ems.domain.ElecGwPriceConfig;
import com.ruoyi.ems.domain.ElecPriceStrategy;
import com.ruoyi.ems.domain.ElecPriceStrategyHour;
import com.ruoyi.ems.model.Price;
import com.ruoyi.ems.service.IElecAttrService;
import com.ruoyi.ems.service.IElecPriceConfigService;
import com.ruoyi.ems.service.IElecPriceStrategyService;
import com.ruoyi.ems.service.IPriceService;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 价格服务
 * <功能详细描述>
 *
 * @author lvwenbin
 * @version [版本号, 2025/3/10]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Service
public class PriceServiceImpl implements IPriceService {
    private static final Logger log = LoggerFactory.getLogger(PriceServiceImpl.class);

    /**
     * 服务区用电属性服务
     */
    @Autowired
    private IElecAttrService elecAttrService;

    /**
     * 国网电价服务
     */
    @Autowired
    private IElecPriceConfigService elecPriceConfigService;

    /**
     * 电价策略
     */
    @Autowired
    private IElecPriceStrategyService elecPriceStrategyService;

    @Override
    public Price getElecHourPrice(String areaCode, Date date) {
        Price price = null;

        try {
            ElecAttr elecAttr = elecAttrService.getEffectiveByArea(areaCode);
            Assert.notNull(elecAttr, -1, "未查询到有效的用电属性信息");

            String priceCode = elecAttr.getPriceCode();
            Assert.notEmpty(priceCode, -1, "未配置电价策略");
            ElecGwPriceConfig priceConfig = elecPriceConfigService.selectGwElecPriceCfgByCode(priceCode);

            List<ElecPriceStrategy> strategyList = elecPriceStrategyService.selectList(new ElecPriceStrategy());
            strategyList.sort((o1, o2) -> o2.getPriority() - o1.getPriority());
            String time = DateUtils.dateToString(date, "HH:mm:ss");

            for (ElecPriceStrategy strategy : strategyList) {
                if (!dateMatch(strategy, date)) {
                    continue;
                }

                List<ElecPriceStrategyHour> hourList = strategy.getHourList();

                Integer hourType = getStrategyHourType(hourList, time);

                if (null != hourType) {
                    price = getPrice(hourType, priceCode, strategy.getStrategyCode(), priceConfig);
                    break;
                }
            }
        }
        catch (BusinessException e) {
            log.warn("获取电价失败，原因：{}", e.getMessage());
        }
        catch (Exception e) {
            log.error("获取电价失败", e);
        }

        return price;
    }

    private Price getPrice(Integer hourType, String priceCode, String strategyCode, ElecGwPriceConfig priceConfig) {
        Price price = null;

        switch (hourType) {
            case -2:
                price = new Price(priceCode, strategyCode, hourType, priceConfig.getDvPrice());
                break;
            case -1:
                price = new Price(priceCode, strategyCode, hourType, priceConfig.getvPrice());
                break;
            case 1:
                price = new Price(priceCode, strategyCode, hourType, priceConfig.getpPrice());
                break;
            case 2:
                price = new Price(priceCode, strategyCode, hourType, priceConfig.getCpPrice());
                break;
            default:
                price = new Price(priceCode, strategyCode, hourType, priceConfig.getOpPrice());
                break;
        }

        return price;
    }

    private Integer getStrategyHourType(List<ElecPriceStrategyHour> hourList, String time) {
        Integer hourType = null;

        for (ElecPriceStrategyHour hourCfg : hourList) {
            if (time.compareTo(hourCfg.getStartTime().toString()) >= 0
                && time.compareTo(hourCfg.getEndTime().toString()) <= 0) {
                hourType = hourCfg.getType();
                break;
            }
        }

        return hourType;
    }

    /**
     * 日期匹配重复规则
     *
     * @param strategy 策略
     * @param date     日期
     * @return 匹配结果
     */
    private boolean dateMatch(ElecPriceStrategy strategy, Date date) {
        boolean flag = false;
        String curMonth = DateUtils.dateToString(date, "MM");
        String[] execMonthArr = StringUtils.split(strategy.getExecMonth(), ",");

        // 优先匹配月份
        if (ArrayUtils.contains(execMonthArr, curMonth)) {
            if (strategy.getExecDateType() == 1 || strategy.getExecDateType() == 3 || strategy.getExecDateType() == 4) {
                throw new UnsupportedOperationException("不支持的日期重复类型");
            }
            else if (strategy.getExecDateType() == 2) {
                flag = true;
            }
            else if (strategy.getExecDateType() == 5 || strategy.getExecDateType() == 6) {
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(date);
                int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
                String[] array = StringUtils.split(strategy.getExecDate(), ",");
                flag = ArrayUtils.contains(array, String.valueOf(dayOfWeek));
            }
        }

        return flag;
    }
}