package logic

import (
	"errors"
	"fmt"
	"fusenapi/model/gmodel"
	"fusenapi/utils/auth"
	"fusenapi/utils/basic"
	"fusenapi/utils/format"
	"fusenapi/utils/step_price"
	"gorm.io/gorm"
	"sort"
	"strings"

	"context"

	"fusenapi/server/product/internal/svc"
	"fusenapi/server/product/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetPriceByPidLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewGetPriceByPidLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetPriceByPidLogic {
	return &GetPriceByPidLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetPriceByPidLogic) GetPriceByPid(req *types.GetPriceByPidReq, userinfo *auth.UserInfo) (resp *basic.Response) {
	req.Pid = strings.Trim(req.Pid, " ")
	if req.Pid == "" {
		return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "err param:pid is empty")
	}
	//获取产品信息(只是获取id)
	productInfo, err := l.svcCtx.AllModels.FsProduct.FindOneBySn(l.ctx, req.Pid, "id")
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the product is not exists")
		}
		logx.Error(err)
		return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product info")
	}
	//查询产品价格
	priceList, err := l.svcCtx.AllModels.FsProductPrice.GetPriceListByProductIds(l.ctx, []int64{productInfo.Id})
	if err != nil {
		logx.Error(err)
		return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get price list")
	}
	if len(priceList) == 0 {
		return resp.SetStatusWithMessage(basic.CodeOK, "success:price list is empty")
	}
	//处理价格信息
	mapRsp := make(map[string]*types.GetPriceByPidRsp)
	for _, priceInfo := range priceList {
		stepNumSlice, err := format.StrSlicToIntSlice(strings.Split(*priceInfo.StepNum, ","))
		if err != nil {
			return resp.SetStatusWithMessage(basic.CodeServiceErr, fmt.Sprintf("failed to parse step num,price_id=%d", priceInfo.Id))
		}
		stepPriceSlice, err := format.StrSlicToIntSlice(strings.Split(*priceInfo.StepPrice, ","))
		if err != nil {
			return resp.SetStatusWithMessage(basic.CodeServiceErr, fmt.Sprintf("failed to parse step price,id = %d", priceInfo.Id))
		}
		if len(stepPriceSlice) == 0 || len(stepNumSlice) == 0 {
			return resp.SetStatusWithMessage(basic.CodeServiceErr, "number of step num or step price is zero")
		}
		lenStepNum := len(stepNumSlice)
		itemList := make([]types.PriceItem, 0, 10)
		tmpMinBuyNum := *priceInfo.MinBuyNum
		for tmpMinBuyNum < (int64(stepNumSlice[lenStepNum-1]) + 5) {
			itemList = append(itemList, types.PriceItem{
				Num:      tmpMinBuyNum,
				TotalNum: tmpMinBuyNum * (*priceInfo.EachBoxNum),
				Price:    step_price.GetCentStepPrice(int(tmpMinBuyNum), stepNumSlice, stepPriceSlice),
			})
			tmpMinBuyNum++
		}
		//组装阶梯数量范围价格
		stepRange := l.dealWithStepRange(stepNumSlice, stepPriceSlice, priceInfo)
		//排序(必须放在其他逻辑之后)
		sort.Ints(stepPriceSlice)
		minPrice := float64(stepPriceSlice[0]) / 100
		maxPrice := float64(stepPriceSlice[len(stepPriceSlice)-1]) / 100
		mapKey := l.getSizePriceMapKey(*priceInfo.SizeId)
		mapRsp[mapKey] = &types.GetPriceByPidRsp{
			Items:     itemList,
			MinPrice:  minPrice,
			MaxPrice:  maxPrice,
			StepRange: stepRange,
		}
	}
	return resp.SetStatusWithMessage(basic.CodeOK, "success", mapRsp)
}

// 组装阶梯价格范围
func (l *GetPriceByPidLogic) dealWithStepRange(stepNumSlice, stepPriceSlice []int, priceInfo gmodel.FsProductPrice) []types.StepRange {
	//要求写死不影响前端展示
	return []types.StepRange{
		{
			Begin: 1000,
			End:   2999,
			Price: 0.23,
		},
		{
			Begin: 3000,
			End:   4999,
			Price: 0.2,
		},
		{
			Begin: 5000,
			End:   -1,
			Price: 0.1,
		},
	}
	//下面是正常的
	lenStepNum := len(stepNumSlice)
	lenStepPrice := len(stepPriceSlice)
	stepListRsp := make([]types.StepRange, 0, lenStepNum)
	//只有一个阶梯价格
	if lenStepPrice == 1 {
		stepListRsp = append(stepListRsp, types.StepRange{
			Begin: *priceInfo.MinBuyNum * (*priceInfo.EachBoxNum),
			End:   -1,
			Price: float64(stepPriceSlice[0]) / 100,
		})
		return stepListRsp
	}
	begin := int64(0)
	end := int64(0)
	for numKey, stepNum := range stepNumSlice {
		//先取最后一个
		tmpPrice := float64(stepPriceSlice[lenStepPrice-1]) / 100
		//如果同下标下面有价格
		if numKey < lenStepPrice {
			tmpPrice = float64(stepPriceSlice[numKey]) / 100
		}
		begin = int64(stepNum) * (*priceInfo.EachBoxNum)
		//不是最后一个
		if numKey < lenStepNum-1 {
			nextBegin := int64(stepNumSlice[numKey+1]) * (*priceInfo.EachBoxNum)
			end = nextBegin - 1
		} else {
			end = -1
		}
		stepListRsp = append(stepListRsp, types.StepRange{
			Begin: begin,
			End:   end,
			Price: tmpPrice,
		})
	}
	return stepListRsp
}

// 获取mapKey
func (l *GetPriceByPidLogic) getSizePriceMapKey(sizeId int64) string {
	return fmt.Sprintf("_%d", sizeId)
}