package com.ruoyi.web.modules.trading.service.impl;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.github.pagehelper.PageHelper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.modules.trading.domain.AppYakMarketQuoteRow;
import com.ruoyi.web.modules.trading.domain.BizMarketDailyQuote;
import com.ruoyi.web.modules.trading.domain.vo.AppYakMarketDailyListVo;
import com.ruoyi.web.modules.trading.domain.vo.AppYakMarketForecastVo;
import com.ruoyi.web.modules.trading.domain.vo.AppYakMarketStats7Vo;
import com.ruoyi.web.modules.trading.domain.vo.AppYakMarketTrendPointVo;
import com.ruoyi.web.modules.trading.domain.vo.AppYakMarketYesterdayVo;
import com.ruoyi.web.modules.trading.mapper.AppYakMarketQuoteMapper;
import com.ruoyi.web.modules.trading.service.IAppYakMarketService;
import com.ruoyi.web.modules.trading.support.MarketDailyQuoteLabelResolver;
import com.ruoyi.web.modules.trading.support.MarketDailyQuoteRules;
import com.ruoyi.web.modules.trading.support.YakMarketDateSupport;
import com.ruoyi.web.modules.trading.support.YakMarketLocationSupport;
import com.ruoyi.web.modules.trading.support.YakMarketStatsSupport;
import com.ruoyi.web.modules.trading.support.YakMarketTrendPredictor;

/**
 * 小程序牦牛行情。
 */
@Service
public class AppYakMarketServiceImpl implements IAppYakMarketService
{
    @Autowired
    private AppYakMarketQuoteMapper appYakMarketQuoteMapper;

    @Override
    public AppYakMarketYesterdayVo selectYesterdayQuote()
    {
        AppYakMarketQuoteRow row = appYakMarketQuoteMapper.selectByQuoteDate(
                YakMarketDateSupport.toSqlDate(YakMarketDateSupport.yesterday()));
        if (row == null)
        {
            return null;
        }
        AppYakMarketYesterdayVo vo = new AppYakMarketYesterdayVo();
        vo.setAvgPrice(row.getAvgPrice());
        vo.setQuoteDate(row.getQuoteDate());
        vo.setPriceUnit(row.getPriceUnit());
        vo.setPriceUnitName(priceUnitName(row.getPriceUnit()));
        return vo;
    }

    @Override
    public AppYakMarketStats7Vo selectStats7()
    {
        PageHelper.clearPage();
        LocalDate end = YakMarketDateSupport.yesterday();
        LocalDate begin = end.minusDays(6);
        List<AppYakMarketQuoteRow> rows = appYakMarketQuoteMapper.selectByQuoteDateRange(
                YakMarketDateSupport.toSqlDate(begin),
                YakMarketDateSupport.toSqlDate(end));
        return YakMarketStatsSupport.build(rows);
    }

    @Override
    public List<AppYakMarketTrendPointVo> selectTrend(int days)
    {
        PageHelper.clearPage();
        if (days != 7 && days != 30)
        {
            throw new IllegalArgumentException("走势天数仅支持 7 或 30");
        }
        LocalDate end = YakMarketDateSupport.yesterday();
        LocalDate begin = end.minusDays(days - 1L);
        List<AppYakMarketQuoteRow> rows = appYakMarketQuoteMapper.selectByQuoteDateRange(
                YakMarketDateSupport.toSqlDate(begin),
                YakMarketDateSupport.toSqlDate(end));
        if (rows == null || rows.isEmpty())
        {
            return Collections.emptyList();
        }
        List<AppYakMarketTrendPointVo> list = new ArrayList<>(rows.size());
        for (AppYakMarketQuoteRow row : rows)
        {
            AppYakMarketTrendPointVo point = new AppYakMarketTrendPointVo();
            point.setQuoteDate(row.getQuoteDate());
            point.setQuoteDateLabel(YakMarketDateSupport.chartDateLabel(row.getQuoteDate()));
            point.setAvgPrice(row.getAvgPrice());
            list.add(point);
        }
        return list;
    }

    @Override
    public AppYakMarketForecastVo selectForecast()
    {
        PageHelper.clearPage();
        AppYakMarketQuoteRow row = appYakMarketQuoteMapper.selectByQuoteDate(
                YakMarketDateSupport.toSqlDate(YakMarketDateSupport.yesterday()));
        if (row == null)
        {
            return null;
        }
        AppYakMarketForecastVo vo = new AppYakMarketForecastVo();
        vo.setProbRise(row.getProbRise());
        vo.setProbFlat(row.getProbFlat());
        vo.setProbFall(row.getProbFall());
        return vo;
    }

    @Override
    public List<AppYakMarketDailyListVo> selectDailyList()
    {
        List<AppYakMarketQuoteRow> rows = appYakMarketQuoteMapper.selectDailyList();
        if (rows == null || rows.isEmpty())
        {
            return Collections.emptyList();
        }
        return rows.stream().map(this::toDailyListVo).collect(Collectors.toList());
    }

    private AppYakMarketDailyListVo toDailyListVo(AppYakMarketQuoteRow row)
    {
        BizMarketDailyQuote labelSource = new BizMarketDailyQuote();
        labelSource.setSupplyStatus(row.getSupplyStatus());
        labelSource.setChangeFactors(row.getChangeFactors());
        labelSource.setPriceUnit(row.getPriceUnit());
        MarketDailyQuoteLabelResolver.enrich(labelSource);

        AppYakMarketDailyListVo vo = new AppYakMarketDailyListVo();
        vo.setId(row.getId());
        vo.setQuoteDate(row.getQuoteDate());
        vo.setTradeMarketName(row.getTradeMarketName());
        vo.setMarketLocation(YakMarketLocationSupport.build(row));
        vo.setPriceMin(row.getPriceMin());
        vo.setPriceMax(row.getPriceMax());
        vo.setPriceUnit(row.getPriceUnit());
        vo.setPriceUnitName(labelSource.getPriceUnitName());
        vo.setSupplyStatusName(labelSource.getSupplyStatusName());
        if (labelSource.getChangeFactorNames() != null && !labelSource.getChangeFactorNames().isEmpty())
        {
            vo.setChangeFactorsText(StringUtils.join(labelSource.getChangeFactorNames(), "、"));
        }
        vo.setTrendPrediction(YakMarketTrendPredictor.resolve(
                row.getProbRise(), row.getProbFlat(), row.getProbFall()));
        vo.setOutboundAdvice(row.getOutboundAdvice());
        return vo;
    }

    private static String priceUnitName(Integer unit)
    {
        if (unit == null)
        {
            return "";
        }
        return unit == MarketDailyQuoteRules.PRICE_UNIT_PER_HEAD ? "元/头" : "元/斤";
    }
}
