package rate

import (
	"context"
	"fmt"
	"strconv"
	"strings"

	"gitea.timerzz.com/kedaya_haitao/common/pkg/subscribe"
	"gitea.timerzz.com/kedaya_haitao/common/structs/storage"
	"gitea.timerzz.com/kedaya_haitao/common/structs/utils"
	"github.com/golang/glog"
	"github.com/redis/go-redis/v9"
	"golang.org/x/sync/errgroup"
)

type Controller struct {
	ctx       context.Context
	storage   *storage.Storage
	subscribe *subscribe.Server
}

func NewController(ctx context.Context, storage *storage.Storage, rdb *redis.Client) *Controller {
	return &Controller{
		storage:   storage,
		subscribe: subscribe.NewServer(ctx, rdb),
	}
}

func (c *Controller) Run() error {
	c.subscribe.SetErrorHandle(func(err error) {
		glog.Error(err)
	})
	if err := c.subscribe.Subscribe(utils.ProfitRate_Channel, c.Rate); err != nil {
		return fmt.Errorf("订阅失败:%v", err)
	}
	c.subscribe.Run()
	return nil
}

// 处理接受到的信息
func (c *Controller) Rate(ctx context.Context, idString string) error {
	var ids = strings.Split(idString, ",")
	var wg errgroup.Group
	for _, id := range ids {
		var i = id
		wg.Go(func() error {
			return c.rate(ctx, i)
		})
	}
	return wg.Wait()
}

// 处理接收到的信息
func (c *Controller) rate(ctx context.Context, idString string) error {
	i, _ := strconv.Atoi(idString)
	if i <= 0 {
		return fmt.Errorf("接收到的id不正确:%s", idString)
	}
	id := uint(i)
	article, err := c.storage.Article().Get(storage.NewGetArticleQuery().SetID(id))
	if err != nil {
		return fmt.Errorf("获取商品 id: %d, 失败:%v", id, err)
	}
	// 拿到最低成本价和最低售价
	var cost, sell float64
	//检查能不能购买,只要有一个供应商能买,就认为能购买
	var available bool

	for _, provider := range article.Providers {
		final := provider.Cost.FinalPrice
		if final > 0 && (final < cost || cost == 0) && !provider.Exclude {
			if available && !provider.Available {
				// 上个最低价供应商能买,这个供应商不能买,那么即使现在的供应商价格更低,也不使用
				continue
			}
			cost = final
		}
		available = available || provider.Available
	}

	for _, seller := range article.Sellers {
		final := seller.Sell.FinalPrice
		if final > 0 && (final < sell || sell == 0) && !seller.Exclude {
			sell = final
		}
	}
	// 成本和售价没有改动,不保存,直接返回
	if cost == article.CostPrice && sell == article.SellPrice {
		return nil
	}
	// 到这里说明成本和售价有变动
	article.CostPrice = Decimal(cost)
	article.SellPrice = Decimal(sell)
	article.Available = available
	if cost > 0 {
		article.Rate = Decimal((article.SellPrice - article.CostPrice) * 100 / article.CostPrice)
	}
	article.GrossProfit = Decimal(article.SellPrice - article.CostPrice)
	// 保存更新
	return c.storage.Article().Update(article, "cost_price", "sell_price", "available", "updated_at", "rate")
}

func Decimal(num float64) float64 {
	num, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", num), 64)
	return num
}