package biz

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

func (this *VoucherBiz) alarm(ctx context.Context, order *bo.OrderBo, errMsg string) error {

	// 1小时 内 指定的批次号 发放 发生错误 预警
	c := vo.OrderConsumeFailAlarmKey.BuildCache([]string{order.ProductNo})

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

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

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

	cl := vo.OrderConsumeFailAlarmLockKey.BuildCache([]string{order.ProductNo})

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

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

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

		if len(cacheValue) > 0 {
			return nil // 有直接返回
		}

		// 通知
		title := fmt.Sprintf("券发放异常")
		if err = this.DingMixRepo.SendMarkdownMessage(ctx, title, alarmText(order, errMsg)); err != nil {
			return err
		}

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

		return nil
	})
}

func alarmText(order *bo.OrderBo, errMsg string) string {
	var card strings.Builder

	// 警示信息（简化版）
	card.WriteString("⚠️ **券发放异常** ⚠️\n\n")

	// 订单信息（通过引用和代码块模拟小字体）
	card.WriteString("> **订单信息：**\n\n")
	card.WriteString(fmt.Sprintf("> AppID: `%s`\n\n", order.AppID))
	card.WriteString(fmt.Sprintf("> OpenID: `%s`\n\n", order.Account))
	card.WriteString(fmt.Sprintf("> 批次号: `%s`\n\n", order.BatchNo))
	card.WriteString(fmt.Sprintf("> 活动号: `%s`\n\n", order.ProductNo))
	card.WriteString(fmt.Sprintf("> 订单号: `%s`\n\n", order.OrderNo))
	card.WriteString(fmt.Sprintf("> 招行订单号: `%s`\n", order.OutBizNo))
	card.WriteString("\n")

	// 报警原因（通过引用和代码块模拟小字体）
	card.WriteString("> **❗ 报警原因：**\n\n")
	card.WriteString(fmt.Sprintf("> `%s`\n", errMsg))

	return card.String()
}
