package com.ruoyi.web.modules.trading.support;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.modules.circulation.domain.BizTradeMarket;
import com.ruoyi.web.modules.circulation.mapper.BizTradeMarketMapper;
import com.ruoyi.web.modules.circulation.support.TradeMarketRules;
import com.ruoyi.web.modules.trading.domain.BizMarketDailyQuote;
import com.ruoyi.web.modules.trading.mapper.BizMarketDailyQuoteMapper;

/**
 * 日度行情入参校验。
 */
@Component
public class MarketDailyQuoteValidation
{
    @Autowired
    private BizTradeMarketMapper bizTradeMarketMapper;

    @Autowired
    private BizMarketDailyQuoteMapper bizMarketDailyQuoteMapper;

    public void validateListQuery(BizMarketDailyQuote query)
    {
        if (query == null)
        {
            return;
        }
        if (query.getBeginQuoteDate() != null && query.getEndQuoteDate() != null
                && query.getBeginQuoteDate().after(query.getEndQuoteDate()))
        {
            throw new ServiceException("结束日期不能早于开始日期");
        }
    }

    public void prepareAndValidateForSave(BizMarketDailyQuote row, Long excludeId)
    {
        if (row == null)
        {
            throw new ServiceException("行情数据不能为空");
        }
        applyDefaults(row);
        trimFields(row);
        validateQuoteDate(row.getQuoteDate());
        validateRegion(row);
        assertTradeMarketActive(row.getTradeMarketId());
        validateEnums(row);
        row.setAvgPrice(AvgPriceCalculator.calculate(row.getPriceMin(), row.getPriceMax()));
        if (row.getChangeFactorList() == null || row.getChangeFactorList().isEmpty())
        {
            row.setChangeFactorList(ChangeFactorsCodec.parseToList(row.getChangeFactors()));
        }
        row.setChangeFactors(ChangeFactorsCodec.encode(row.getChangeFactorList()));
        validateProbabilities(row.getProbRise(), row.getProbFlat(), row.getProbFall());
        validateOutboundAdvice(row.getOutboundAdvice());
        assertDimensionUnique(row, excludeId);
    }

    public static void validateProbabilities(BigDecimal rise, BigDecimal flat, BigDecimal fall)
    {
        if (!isProbPositive(rise) || !isProbPositive(flat) || !isProbPositive(fall))
        {
            throw new ServiceException("预测概率须为正数且不超过 100%");
        }
        BigDecimal sum = rise.add(flat).add(fall);
        BigDecimal diff = sum.subtract(MarketDailyQuoteRules.PROB_SUM_TARGET).abs();
        if (diff.compareTo(MarketDailyQuoteRules.PROB_SUM_TOLERANCE) > 0)
        {
            throw new ServiceException("看涨、看平、看跌概率之和须为 100%");
        }
    }

    private static boolean isProbPositive(BigDecimal v)
    {
        return v != null && v.compareTo(BigDecimal.ZERO) > 0 && v.compareTo(new BigDecimal("100")) <= 0;
    }

    private static void applyDefaults(BizMarketDailyQuote row)
    {
        if (row.getCattleGender() == null)
        {
            row.setCattleGender(MarketDailyQuoteRules.CATTLE_GENDER_BULL);
        }
        if (row.getPriceUnit() == null)
        {
            row.setPriceUnit(MarketDailyQuoteRules.PRICE_UNIT_PER_JIN);
        }
    }

    private static void trimFields(BizMarketDailyQuote row)
    {
        trim(row.getProvinceCode(), row::setProvinceCode);
        trim(row.getProvinceName(), row::setProvinceName);
        trim(row.getCityCode(), row::setCityCode);
        trim(row.getCityName(), row::setCityName);
        trim(row.getCountyCode(), row::setCountyCode);
        trim(row.getCountyName(), row::setCountyName);
        if (row.getOutboundAdvice() != null)
        {
            row.setOutboundAdvice(row.getOutboundAdvice().trim());
        }
    }

    private static void trim(String value, java.util.function.Consumer<String> setter)
    {
        if (value == null)
        {
            return;
        }
        setter.accept(value.trim());
    }

    private static void validateQuoteDate(Date quoteDate)
    {
        if (quoteDate == null)
        {
            throw new ServiceException("请选择行情日期");
        }
        LocalDate today = LocalDate.now();
        LocalDate d = quoteDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        if (d.isAfter(today))
        {
            throw new ServiceException("行情日期不能晚于今天");
        }
    }

    private static void validateRegion(BizMarketDailyQuote row)
    {
        if (StringUtils.isEmpty(row.getProvinceCode()) || StringUtils.isEmpty(row.getProvinceName())
                || StringUtils.isEmpty(row.getCityCode()) || StringUtils.isEmpty(row.getCityName())
                || StringUtils.isEmpty(row.getCountyCode()) || StringUtils.isEmpty(row.getCountyName()))
        {
            throw new ServiceException("请选择完整的产地（省/市/县）");
        }
    }

    private void assertTradeMarketActive(Long tradeMarketId)
    {
        if (tradeMarketId == null)
        {
            throw new ServiceException("请选择渠道");
        }
        BizTradeMarket market = bizTradeMarketMapper.selectBizTradeMarketById(tradeMarketId);
        if (market == null)
        {
            throw new ServiceException("交易市场不存在或已删除");
        }
        if (market.getOperateStatus() == null
                || market.getOperateStatus() != TradeMarketRules.OPERATE_STATUS_NORMAL)
        {
            throw new ServiceException("所选交易市场未处于正常运营状态");
        }
    }

    private static void validateEnums(BizMarketDailyQuote row)
    {
        if (!MarketDailyQuoteRules.isCattleGenderValid(row.getCattleGender()))
        {
            throw new ServiceException("公母选项无效");
        }
        if (!MarketDailyQuoteRules.isPriceUnitValid(row.getPriceUnit()))
        {
            throw new ServiceException("价格单位无效");
        }
        if (!MarketDailyQuoteRules.isWeightGradeValid(row.getWeightGrade())
                || !MarketDailyQuoteRules.isGrowthStageValid(row.getGrowthStage())
                || !MarketDailyQuoteRules.isAgeMonthGradeValid(row.getAgeMonthGrade())
                || !MarketDailyQuoteRules.isFatGradeValid(row.getFatGrade()))
        {
            throw new ServiceException("品类维度选项无效");
        }
        if (!MarketDailyQuoteRules.isSupplyStatusValid(row.getSupplyStatus()))
        {
            throw new ServiceException("请选择出栏情况");
        }
    }

    private static void validateOutboundAdvice(String advice)
    {
        if (StringUtils.isEmpty(advice))
        {
            throw new ServiceException("请填写出栏建议");
        }
        if (advice.length() > MarketDailyQuoteRules.MAX_OUTBOUND_ADVICE_LEN)
        {
            throw new ServiceException("出栏建议不能超过 500 字");
        }
    }

    private void assertDimensionUnique(BizMarketDailyQuote row, Long excludeId)
    {
        int count = bizMarketDailyQuoteMapper.countDuplicateDimension(
                row.getQuoteDate(),
                row.getCountyCode(),
                row.getTradeMarketId(),
                row.getCattleGender(),
                MarketDailyQuoteRules.normalizeNullableDim(row.getWeightGrade()),
                MarketDailyQuoteRules.normalizeNullableDim(row.getGrowthStage()),
                MarketDailyQuoteRules.normalizeNullableDim(row.getAgeMonthGrade()),
                MarketDailyQuoteRules.normalizeNullableDim(row.getFatGrade()),
                excludeId);
        if (count > 0)
        {
            throw new ServiceException("该维度组合当日行情已存在");
        }
    }
}
