package biz

import (
	"context"
	"fmt"
	"github.com/redis/go-redis/v9"
	err2 "voucher/api/err"
	"voucher/internal/biz/bo"
	"voucher/internal/biz/vo"
	"voucher/internal/pkg/lock"
)

// RegisterTag 注册通知标签 stock.MchId 批次创建商户, stock.BatchNo 商品批次号
func (this *VoucherBiz) RegisterTag(ctx context.Context, productNo string) error {

	stock, err := this.ProductRepo.GetByProductNo(ctx, productNo)
	if err != nil {
		return err
	}

	return this.registerNotifyTag(ctx, stock.MchId, stock.BatchNo)
}

func (v *VoucherBiz) registerNotifyTag(ctx context.Context, stockCreatorMchID, stockID string) error {

	c := vo.WechatNotifyRegisterTagCacheKey.BuildCache([]string{v.bc.WechatNotifyMQ.Tag, stockCreatorMchID, stockID})

	_, err := v.rdb.Rdb.Get(ctx, c.Key).Result()

	if err == nil {
		// 缓存存在，直接返回
		return nil
	}

	if err != redis.Nil {
		return fmt.Errorf(fmt.Sprintf("获取redis缓存%s异常:%v", c.Key, err))
	}

	cl := vo.WechatNotifyRegisterTagCacheLockKey.BuildCache([]string{v.bc.WechatNotifyMQ.Tag, stockCreatorMchID, stockID})

	return lock.NewMutex(v.rdb.Rdb, cl.TTL).Lock(ctx, cl.Key, func(ctx context.Context) error {
		// 二次获取，判定处理，以免获取锁后又执行了一次

		cacheValue, err3 := v.rdb.Rdb.Get(ctx, c.Key).Result()

		if err3 != nil && err3 != redis.Nil {
			return fmt.Errorf(fmt.Sprintf("二次获取redis缓存%s异常:%v", c.Key, err))
		}

		if cacheValue != "" {
			return nil // 有直接返回
		}

		wechatNotifyTag, err3 := v.WechatNotifyRegisterTagRepo.GetByStockIdAndMchId(ctx, stockCreatorMchID, stockID)
		if err3 != nil && !err2.IsDbNotFound(err3) {
			return err3
		}

		if wechatNotifyTag != nil {
			if wechatNotifyTag.Tag != v.bc.WechatNotifyMQ.Tag {
				return fmt.Errorf("tag不一致，请检查tag配置:%s", wechatNotifyTag.Tag)
			}

			if wechatNotifyTag.Status.IsSuccess() {
				return v.setCache(ctx, c, wechatNotifyTag)
			}
		} else {
			wechatNotifyTag, err3 = v.createWechatNotifyRegisterTag(ctx, stockCreatorMchID, stockID)
			if err3 != nil {
				return err3
			}
		}

		if err = v.WechatCpnRepo.RegisterNotifyTag(ctx, stockID); err != nil {

			return v.WechatNotifyRegisterTagRepo.Fail(ctx, wechatNotifyTag.ID, err.Error())
		}

		if err = v.WechatNotifyRegisterTagRepo.Success(ctx, wechatNotifyTag.ID); err != nil {
			return err
		}

		return v.setCache(ctx, c, wechatNotifyTag)
	})
}

func (v *VoucherBiz) createWechatNotifyRegisterTag(ctx context.Context, stockCreatorMchID, stockID string) (*bo.WechatNotifyRegisterTagBo, error) {
	return v.WechatNotifyRegisterTagRepo.Create(ctx, &bo.WechatNotifyRegisterTagBo{
		StockID:           stockID,
		StockCreatorMchID: stockCreatorMchID,
		Tag:               v.bc.WechatNotifyMQ.Tag,
	})
}

func (v *VoucherBiz) setCache(ctx context.Context, c *vo.Cache, wechatNotifyTag *bo.WechatNotifyRegisterTagBo) error {

	if err := v.rdb.Rdb.Set(ctx, c.Key, wechatNotifyTag.Tag, c.TTL).Err(); err != nil {
		return fmt.Errorf(fmt.Sprintf("设置redis缓存%s异常:%v", c.Key, err))
	}

	return nil
}
