package orderLogic

import (
	"context"
	"encoding/json"
	"fmt"
	"strconv"
	"time"

	"github.com/perfect-panel/server/pkg/constant"

	"github.com/perfect-panel/server/pkg/logger"

	tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
	"github.com/google/uuid"
	"github.com/hibiken/asynq"
	"github.com/perfect-panel/server/internal/config"
	"github.com/perfect-panel/server/internal/logic/telegram"
	"github.com/perfect-panel/server/internal/model/order"
	"github.com/perfect-panel/server/internal/model/user"
	"github.com/perfect-panel/server/internal/svc"
	"github.com/perfect-panel/server/pkg/tool"
	"github.com/perfect-panel/server/pkg/uuidx"
	"github.com/perfect-panel/server/queue/types"
	"gorm.io/gorm"
)

const (
	Subscribe    = 1
	Renewal      = 2
	ResetTraffic = 3
	Recharge     = 4
)

type ActivateOrderLogic struct {
	svc *svc.ServiceContext
}

func NewActivateOrderLogic(svc *svc.ServiceContext) *ActivateOrderLogic {
	return &ActivateOrderLogic{
		svc: svc,
	}
}

func (l *ActivateOrderLogic) ProcessTask(ctx context.Context, task *asynq.Task) error {
	payload := types.ForthwithActivateOrderPayload{}
	if err := json.Unmarshal(task.Payload(), &payload); err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Unmarshal payload failed",
			logger.Field("error", err.Error()),
			logger.Field("payload", string(task.Payload())),
		)
		return nil
	}
	// Find order by order no
	orderInfo, err := l.svc.OrderModel.FindOneByOrderNo(ctx, payload.OrderNo)
	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Find order failed",
			logger.Field("error", err.Error()),
			logger.Field("order_no", payload.OrderNo),
		)
		return nil
	}
	// 1: Pending, 2: Paid, 3:Close, 4: Failed, 5:Finished
	if orderInfo.Status != 2 {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Order status error",
			logger.Field("order_no", orderInfo.OrderNo),
			logger.Field("status", orderInfo.Status),
		)
		return nil
	}
	switch orderInfo.Type {
	case Subscribe:
		err = l.NewPurchase(ctx, orderInfo)
	case Renewal:
		err = l.Renewal(ctx, orderInfo)
	case ResetTraffic:
		err = l.ResetTraffic(ctx, orderInfo)
	case Recharge:
		err = l.Recharge(ctx, orderInfo)
	default:
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Order type is invalid", logger.Field("type", orderInfo.Type))
		return nil
	}
	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Process task failed", logger.Field("error", err.Error()))
		return nil
	}
	// if coupon is not empty
	if orderInfo.Coupon != "" {
		// update coupon status
		err = l.svc.CouponModel.UpdateCount(ctx, orderInfo.Coupon)
		if err != nil {
			logger.WithContext(ctx).Error("[ActivateOrderLogic] Update coupon status failed",
				logger.Field("error", err.Error()),
				logger.Field("coupon", orderInfo.Coupon),
			)
		}
	}
	// update order status
	orderInfo.Status = 5
	err = l.svc.OrderModel.Update(ctx, orderInfo)
	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Update order status failed",
			logger.Field("error", err.Error()),
			logger.Field("order_no", orderInfo.OrderNo),
		)
	}

	return nil
}

// NewPurchase New purchase
func (l *ActivateOrderLogic) NewPurchase(ctx context.Context, orderInfo *order.Order) error {
	var userInfo *user.User
	var err error
	if orderInfo.UserId != 0 {
		// find user by user id
		userInfo, err = l.svc.UserModel.FindOne(ctx, orderInfo.UserId)
		if err != nil {
			logger.WithContext(ctx).Error("[ActivateOrderLogic] Find user failed",
				logger.Field("error", err.Error()),
				logger.Field("user_id", orderInfo.UserId),
			)
			return err
		}
	} else {
		// If User ID is 0, it means that the order is a guest order, need to create a new user
		// query info with redis
		cacheKey := fmt.Sprintf(constant.TempOrderCacheKey, orderInfo.OrderNo)
		data, err := l.svc.Redis.Get(ctx, cacheKey).Result()
		if err != nil {
			logger.WithContext(ctx).Error("[ActivateOrderLogic] Get temp order cache failed",
				logger.Field("error", err.Error()),
				logger.Field("cache_key", cacheKey),
			)
			return err
		}
		var tempOrder constant.TemporaryOrderInfo
		if err = json.Unmarshal([]byte(data), &tempOrder); err != nil {
			logger.WithContext(ctx).Errorw("[ActivateOrderLogic] Unmarshal temp order failed",
				logger.Field("error", err.Error()),
			)
			return err
		}
		// create user

		userInfo = &user.User{
			Password: tool.EncodePassWord(tempOrder.Password),
			AuthMethods: []user.AuthMethods{
				{
					AuthType:       tempOrder.AuthType,
					AuthIdentifier: tempOrder.Identifier,
				},
			},
		}
		err = l.svc.UserModel.Transaction(ctx, func(tx *gorm.DB) error {
			// Save user information
			if err := tx.Save(userInfo).Error; err != nil {
				return err
			}
			// Generate ReferCode
			userInfo.ReferCode = uuidx.UserInviteCode(userInfo.Id)
			// Update ReferCode
			if err := tx.Model(&user.User{}).Where("id = ?", userInfo.Id).Update("refer_code", userInfo.ReferCode).Error; err != nil {
				return err
			}
			orderInfo.UserId = userInfo.Id
			return tx.Model(&order.Order{}).Where("order_no = ?", orderInfo.OrderNo).Update("user_id", userInfo.Id).Error
		})
		if err != nil {
			logger.WithContext(ctx).Error("[ActivateOrderLogic] Create user failed",
				logger.Field("error", err.Error()),
			)
			return err
		}

		if tempOrder.InviteCode != "" {
			// find referer by refer code
			referer, err := l.svc.UserModel.FindOneByReferCode(ctx, tempOrder.InviteCode)
			if err != nil {
				logger.WithContext(ctx).Error("[ActivateOrderLogic] Find referer failed",
					logger.Field("error", err.Error()),
					logger.Field("refer_code", tempOrder.InviteCode),
				)
			} else {
				userInfo.RefererId = referer.Id
				err = l.svc.UserModel.Update(ctx, userInfo)
				if err != nil {
					logger.WithContext(ctx).Error("[ActivateOrderLogic] Update user referer failed",
						logger.Field("error", err.Error()),
						logger.Field("user_id", userInfo.Id),
					)
				}
			}
		}

		logger.WithContext(ctx).Info("[ActivateOrderLogic] Create guest user success", logger.Field("user_id", userInfo.Id), logger.Field("Identifier", tempOrder.Identifier), logger.Field("AuthType", tempOrder.AuthType))
	}
	// find subscribe by id
	sub, err := l.svc.SubscribeModel.FindOne(ctx, orderInfo.SubscribeId)
	if err != nil {
		logger.WithContext(ctx).Errorw("[ActivateOrderLogic] Find subscribe failed",
			logger.Field("error", err.Error()),
			logger.Field("subscribe_id", orderInfo.SubscribeId),
		)
		return err
	}
	// create user subscribe
	now := time.Now()

	userSub := user.Subscribe{
		Id:          0,
		UserId:      orderInfo.UserId,
		OrderId:     orderInfo.Id,
		SubscribeId: orderInfo.SubscribeId,
		StartTime:   now,
		ExpireTime:  tool.AddTime(sub.UnitTime, orderInfo.Quantity, now),
		Traffic:     sub.Traffic,
		Download:    0,
		Upload:      0,
		Token:       uuidx.SubscribeToken(orderInfo.OrderNo),
		UUID:        uuid.New().String(),
		Status:      1,
	}
	err = l.svc.UserModel.InsertSubscribe(ctx, &userSub)

	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Insert user subscribe failed",
			logger.Field("error", err.Error()),
		)
		return err
	}
	// handler 	commission
	if userInfo.RefererId != 0 &&
		l.svc.Config.Invite.ReferralPercentage != 0 &&
		(!l.svc.Config.Invite.OnlyFirstPurchase || orderInfo.IsNew) {
		referer, err := l.svc.UserModel.FindOne(ctx, userInfo.RefererId)
		if err != nil {
			logger.WithContext(ctx).Error("[ActivateOrderLogic] Find referer failed",
				logger.Field("error", err.Error()),
				logger.Field("referer_id", userInfo.RefererId),
			)
			goto updateCache
		}
		// calculate commission
		amount := float64(orderInfo.Price) * (float64(l.svc.Config.Invite.ReferralPercentage) / 100)
		referer.Commission += int64(amount)
		err = l.svc.UserModel.Update(ctx, referer)
		if err != nil {
			logger.WithContext(ctx).Error("[ActivateOrderLogic] Update referer commission failed",
				logger.Field("error", err.Error()),
			)
			goto updateCache
		}
		// create commission log
		commissionLog := user.CommissionLog{
			UserId:  referer.Id,
			OrderNo: orderInfo.OrderNo,
			Amount:  int64(amount),
		}
		err = l.svc.UserModel.InsertCommissionLog(ctx, &commissionLog)
		if err != nil {
			logger.WithContext(ctx).Error("[ActivateOrderLogic] Insert commission log failed",
				logger.Field("error", err.Error()),
			)
		}
		err = l.svc.UserModel.UpdateUserCache(ctx, referer)
		if err != nil {
			logger.WithContext(ctx).Errorw("[ActivateOrderLogic] Update referer cache", logger.Field("error", err.Error()), logger.Field("user_id", referer.Id))
		}
	}
updateCache:
	for _, id := range tool.StringToInt64Slice(sub.Server) {
		cacheKey := fmt.Sprintf("%s%d", config.ServerUserListCacheKey, id)
		err = l.svc.Redis.Del(ctx, cacheKey).Err()
		if err != nil {
			logger.WithContext(ctx).Error("[ActivateOrderLogic] Del server user list cache failed",
				logger.Field("error", err.Error()),
				logger.Field("cache_key", cacheKey),
			)
		}
	}
	data, err := l.svc.ServerModel.FindServerListByGroupIds(ctx, tool.StringToInt64Slice(sub.ServerGroup))
	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Find server list failed", logger.Field("error", err.Error()))
		return err
	}
	for _, item := range data {
		cacheKey := fmt.Sprintf("%s%d", config.ServerUserListCacheKey, item.Id)
		err = l.svc.Redis.Del(ctx, cacheKey).Err()
		if err != nil {
			logger.WithContext(ctx).Error("[ActivateOrderLogic] Del server user list cache failed",
				logger.Field("error", err.Error()),
				logger.Field("cache_key", cacheKey),
			)
		}
	}
	userTelegramChatId, ok := findTelegram(userInfo)

	// sendMessage To Telegram
	if ok {
		text, err := tool.RenderTemplateToString(telegram.PurchaseNotify, map[string]string{
			"OrderNo":       orderInfo.OrderNo,
			"SubscribeName": sub.Name,
			"OrderAmount":   fmt.Sprintf("%.2f", float64(orderInfo.Price)/100),
			"ExpireTime":    userSub.ExpireTime.Format("2006-01-02 15:04:05"),
		})
		if err != nil {
			logger.WithContext(ctx).Error("[ActivateOrderLogic] Render template failed",
				logger.Field("error", err.Error()),
			)
		}
		l.sendUserNotifyWithTelegram(userTelegramChatId, text)
	}
	// send message to admin
	text, err := tool.RenderTemplateToString(telegram.AdminOrderNotify, map[string]string{
		"OrderNo":       orderInfo.OrderNo,
		"TradeNo":       orderInfo.TradeNo,
		"SubscribeName": sub.Name,
		//"UserEmail":     userInfo.Email,
		"OrderAmount":   fmt.Sprintf("%.2f", float64(orderInfo.Price)/100),
		"OrderStatus":   "已支付",
		"OrderTime":     orderInfo.CreatedAt.Format("2006-01-02 15:04:05"),
		"PaymentMethod": orderInfo.Method,
	})
	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Render AdminOrderNotify template failed",
			logger.Field("error", err.Error()),
		)
	}
	l.sendAdminNotifyWithTelegram(ctx, text)
	logger.WithContext(ctx).Info("[ActivateOrderLogic] Insert user subscribe success")
	return nil
}

// Renewal Renewal
func (l *ActivateOrderLogic) Renewal(ctx context.Context, orderInfo *order.Order) error {
	// find user by user id
	userInfo, err := l.svc.UserModel.FindOne(ctx, orderInfo.UserId)
	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Find user failed",
			logger.Field("error", err.Error()),
			logger.Field("user_id", orderInfo.UserId),
		)
		return err
	}
	// find user subscribe by subscribe token
	userSub, err := l.svc.UserModel.FindOneSubscribeByToken(ctx, orderInfo.SubscribeToken)
	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Find user subscribe failed",
			logger.Field("error", err.Error()),
			logger.Field("order_id", orderInfo.Id),
		)
		return err
	}
	// find subscribe by id
	sub, err := l.svc.SubscribeModel.FindOne(ctx, orderInfo.SubscribeId)
	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Find subscribe failed",
			logger.Field("error", err.Error()),
			logger.Field("subscribe_id", orderInfo.SubscribeId),
			logger.Field("order_id", orderInfo.Id),
		)
		return err
	}
	now := time.Now()
	if userSub.ExpireTime.Before(now) {
		userSub.ExpireTime = now
	}

	// Check whether traffic reset on renewal is enabled
	if sub.RenewalReset != nil && *sub.RenewalReset {
		userSub.Download = 0
		userSub.Upload = 0
	}
	if userSub.FinishedAt != nil {
		userSub.FinishedAt = nil
	}

	userSub.ExpireTime = tool.AddTime(sub.UnitTime, orderInfo.Quantity, userSub.ExpireTime)
	userSub.Status = 1
	// update user subscribe
	err = l.svc.UserModel.UpdateSubscribe(ctx, userSub)
	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Update user subscribe failed",
			logger.Field("error", err.Error()),
		)
		return err
	}
	// handler 	commission
	if userInfo.RefererId != 0 &&
		l.svc.Config.Invite.ReferralPercentage != 0 &&
		!l.svc.Config.Invite.OnlyFirstPurchase {
		referer, err := l.svc.UserModel.FindOne(ctx, userInfo.RefererId)
		if err != nil {
			logger.WithContext(ctx).Error("[ActivateOrderLogic] Find referer failed",
				logger.Field("error", err.Error()),
				logger.Field("referer_id", userInfo.RefererId),
			)
			goto sendMessage
		}
		// calculate commission
		amount := float64(orderInfo.Price) * (float64(l.svc.Config.Invite.ReferralPercentage) / 100)
		referer.Commission += int64(amount)
		err = l.svc.UserModel.Update(ctx, referer)
		if err != nil {
			logger.WithContext(ctx).Error("[ActivateOrderLogic] Update referer commission failed",
				logger.Field("error", err.Error()),
			)
			goto sendMessage
		}
		// create commission log
		commissionLog := user.CommissionLog{
			UserId:  referer.Id,
			OrderNo: orderInfo.OrderNo,
			Amount:  int64(amount),
		}
		err = l.svc.UserModel.InsertCommissionLog(ctx, &commissionLog)
		if err != nil {
			logger.WithContext(ctx).Error("[ActivateOrderLogic] Insert commission log failed",
				logger.Field("error", err.Error()),
			)
		}
		err = l.svc.UserModel.UpdateUserCache(ctx, referer)
		if err != nil {
			logger.WithContext(ctx).Errorw("[ActivateOrderLogic] Update referer cache", logger.Field("error", err.Error()), logger.Field("user_id", referer.Id))
		}
	}

sendMessage:
	userTelegramChatId, ok := findTelegram(userInfo)
	// SendMessage To Telegram
	if ok {
		text, err := tool.RenderTemplateToString(telegram.RenewalNotify, map[string]string{
			"OrderNo":       orderInfo.OrderNo,
			"SubscribeName": sub.Name,
			"OrderAmount":   fmt.Sprintf("%.2f", float64(orderInfo.Price)/100),
			"ExpireTime":    userSub.ExpireTime.Format("2006-01-02 15:04:05"),
		})
		if err != nil {
			logger.WithContext(ctx).Error("[ActivateOrderLogic] Render template failed",
				logger.Field("error", err.Error()),
			)
		}
		l.sendUserNotifyWithTelegram(userTelegramChatId, text)
	}

	// send message to admin
	text, err := tool.RenderTemplateToString(telegram.AdminOrderNotify, map[string]string{
		"OrderNo":       orderInfo.OrderNo,
		"TradeNo":       orderInfo.TradeNo,
		"SubscribeName": sub.Name,
		//"UserEmail":     userInfo.Email,
		"OrderAmount":   fmt.Sprintf("%.2f", float64(orderInfo.Price)/100),
		"OrderStatus":   "已支付",
		"OrderTime":     orderInfo.CreatedAt.Format("2006-01-02 15:04:05"),
		"PaymentMethod": orderInfo.Method,
	})
	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Render AdminOrderNotify template failed",
			logger.Field("error", err.Error()),
		)
	}
	l.sendAdminNotifyWithTelegram(ctx, text)
	return nil
}

// ResetTraffic Reset traffic
func (l *ActivateOrderLogic) ResetTraffic(ctx context.Context, orderInfo *order.Order) error {
	// find user by user id
	userInfo, err := l.svc.UserModel.FindOne(ctx, orderInfo.UserId)
	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Find user failed",
			logger.Field("error", err.Error()),
			logger.Field("user_id", orderInfo.UserId),
		)
		return err
	}
	// Generate a Subscribe Token through orderNo
	// find user subscribe by subscribe token
	userSub, err := l.svc.UserModel.FindOneSubscribeByToken(ctx, orderInfo.SubscribeToken)
	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Find user subscribe failed",
			logger.Field("error", err.Error()),
			logger.Field("order_id", orderInfo.Id),
		)
		return err
	}
	userSub.Download = 0
	userSub.Upload = 0
	userSub.Status = 1
	// update user subscribe
	err = l.svc.UserModel.UpdateSubscribe(ctx, userSub)
	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Update user subscribe failed",
			logger.Field("error", err.Error()),
		)
		return err
	}
	sub, err := l.svc.SubscribeModel.FindOne(ctx, userSub.SubscribeId)
	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Find subscribe failed",
			logger.Field("error", err.Error()),
			logger.Field("subscribe_id", userSub.SubscribeId),
		)
		return err
	}
	userTelegramChatId, ok := findTelegram(userInfo)
	// SendMessage To Telegram
	if ok {
		text, err := tool.RenderTemplateToString(telegram.ResetTrafficNotify, map[string]string{
			"OrderNo":       orderInfo.OrderNo,
			"SubscribeName": sub.Name,
			"ResetTime":     time.Now().Format("2006-01-02 15:04:05"),
			"ExpireTime":    userSub.ExpireTime.Format("2006-01-02 15:04:05"),
		})
		if err != nil {
			logger.WithContext(ctx).Error("[ActivateOrderLogic] Render template failed",
				logger.Field("error", err.Error()),
			)
		}
		l.sendUserNotifyWithTelegram(userTelegramChatId, text)
	}

	// send message to admin
	text, err := tool.RenderTemplateToString(telegram.AdminOrderNotify, map[string]string{
		"OrderNo":       orderInfo.OrderNo,
		"TradeNo":       orderInfo.TradeNo,
		"SubscribeName": "流量重置",
		"OrderAmount":   fmt.Sprintf("%.2f", float64(orderInfo.Price)/100),
		"OrderStatus":   "已支付",
		"OrderTime":     orderInfo.CreatedAt.Format("2006-01-02 15:04:05"),
		"PaymentMethod": orderInfo.Method,
	})
	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Render AdminOrderNotify template failed",
			logger.Field("error", err.Error()),
		)
	}
	l.sendAdminNotifyWithTelegram(ctx, text)
	return nil
}

// Recharge Recharge to user
func (l *ActivateOrderLogic) Recharge(ctx context.Context, orderInfo *order.Order) error {
	// find user by user id
	userInfo, err := l.svc.UserModel.FindOne(ctx, orderInfo.UserId)
	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Find user failed",
			logger.Field("error", err.Error()),
			logger.Field("user_id", orderInfo.UserId),
		)
		return err
	}
	userInfo.Balance += orderInfo.Price
	// update user
	err = l.svc.DB.Transaction(func(tx *gorm.DB) error {
		err = l.svc.UserModel.Update(ctx, userInfo, tx)
		if err != nil {
			logger.WithContext(ctx).Error("[ActivateOrderLogic] Update user failed",
				logger.Field("error", err.Error()),
			)
			return err
		}
		// Create Balance Log
		balanceLog := user.BalanceLog{
			UserId:  orderInfo.UserId,
			Amount:  orderInfo.Price,
			Type:    1,
			OrderId: orderInfo.Id,
			Balance: userInfo.Balance,
		}
		err = l.svc.UserModel.InsertBalanceLog(ctx, &balanceLog, tx)
		if err != nil {
			logger.WithContext(ctx).Error("[ActivateOrderLogic] Insert balance log failed",
				logger.Field("error", err.Error()),
			)
			return err
		}

		return nil
	})
	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Database transaction failed",
			logger.Field("error", err.Error()),
		)
		return err
	}
	userTelegramChatId, ok := findTelegram(userInfo)
	// SendMessage To Telegram
	if ok {
		text, err := tool.RenderTemplateToString(telegram.RechargeNotify, map[string]string{
			"OrderAmount":   fmt.Sprintf("%.2f", float64(orderInfo.Price)/100),
			"PaymentMethod": orderInfo.Method,
			"Time":          orderInfo.CreatedAt.Format("2006-01-02 15:04:05"),
			"Balance":       fmt.Sprintf("%.2f", float64(userInfo.Balance)/100),
		})
		if err != nil {
			logger.WithContext(ctx).Error("[ActivateOrderLogic] Render template failed",
				logger.Field("error", err.Error()),
			)
		}
		l.sendUserNotifyWithTelegram(userTelegramChatId, text)
	}
	// send message to admin
	text, err := tool.RenderTemplateToString(telegram.AdminOrderNotify, map[string]string{
		"OrderNo":       orderInfo.OrderNo,
		"TradeNo":       orderInfo.TradeNo,
		"OrderAmount":   fmt.Sprintf("%.2f", float64(orderInfo.Price)/100),
		"SubscribeName": "余额充值",
		"OrderStatus":   "已支付",
		"OrderTime":     orderInfo.CreatedAt.Format("2006-01-02 15:04:05"),
		"PaymentMethod": orderInfo.Method,
	})
	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Render AdminOrderNotify template failed",
			logger.Field("error", err.Error()),
		)
	}
	l.sendAdminNotifyWithTelegram(ctx, text)
	return nil
}

// sendUserNotifyWithTelegram send message to user
func (l *ActivateOrderLogic) sendUserNotifyWithTelegram(chatId int64, text string) {
	msg := tgbotapi.NewMessage(chatId, text)
	msg.ParseMode = "markdown"
	_, err := l.svc.TelegramBot.Send(msg)
	if err != nil {
		logger.Error("[ActivateOrderLogic] Send telegram user message failed",
			logger.Field("error", err.Error()),
		)
	}
}

// sendAdminNotifyWithTelegram send message to admin
func (l *ActivateOrderLogic) sendAdminNotifyWithTelegram(ctx context.Context, text string) {
	admins, err := l.svc.UserModel.QueryAdminUsers(ctx)
	if err != nil {
		logger.WithContext(ctx).Error("[ActivateOrderLogic] Query admin users failed",
			logger.Field("error", err.Error()),
		)
		return
	}
	for _, admin := range admins {
		telegramId, ok := findTelegram(admin)
		if !ok {
			continue
		}
		msg := tgbotapi.NewMessage(telegramId, text)
		msg.ParseMode = "markdown"
		_, err := l.svc.TelegramBot.Send(msg)
		if err != nil {
			logger.WithContext(ctx).Error("[ActivateOrderLogic] Send telegram admin message failed",
				logger.Field("error", err.Error()),
			)
		}
	}
}

// findTelegram find user telegram id
func findTelegram(u *user.User) (int64, bool) {
	for _, item := range u.AuthMethods {
		if item.AuthType == "telegram" {
			// string to int64
			parseInt, err := strconv.ParseInt(item.AuthIdentifier, 10, 64)
			if err != nil {
				return 0, false
			}
			return parseInt, true
		}

	}
	return 0, false
}
