package task

import (
	"context"
	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
	"github.com/go-nunu/nunu-layout-advanced/internal/repository"
	"github.com/go-nunu/nunu-layout-advanced/internal/service/api/gameShield"
	"go.uber.org/zap"
	"strconv"
	"time"
)

type GameShieldTask interface {
	CheckGameShield(ctx context.Context) error
	SyncAllExpireTimeFromHost(ctx context.Context) error
}

func NewGameShieldTask(
	task *Task,
	gameShieldRepo repository.GameShieldRepository,
	gameShieldBackendService gameShield.GameShieldBackendService,

) GameShieldTask {
	return &gameShieldTask{
		Task:                     task,
		gameShieldRepo:           gameShieldRepo,
		gameShieldBackendService: gameShieldBackendService,
	}
}

type gameShieldTask struct {
	*Task
	gameShieldRepo           repository.GameShieldRepository
	gameShieldBackendService gameShield.GameShieldBackendService
}

// 检查已过期的记录
func (t gameShieldTask) CheckExpiredGameShields(ctx context.Context) error {
	// 获取已过期的商品
	expiredShields, err := t.gameShieldRepo.GetExpiredGameShields(ctx)
	if err != nil {
		t.logger.Error("查询已过期的游戏盾失败", zap.Error(err))
		return err
	}

	t.logger.Info("找到已过期的游戏盾商品", zap.Int("数量", len(expiredShields)))

	// 遍历已过期的商品
	for _, shield := range expiredShields {
		t.logger.Info("已过期商品",
			zap.Int("ID", shield.Id),
			zap.Int("用户ID", shield.Uid),
			zap.String("商品", shield.AppName),
			zap.Time("过期时间", time.Unix(shield.ExpireTime, 0)))

		// 检查用户是否已续费（检查nextduedate字段）
		nextduedate, err := t.gameShieldRepo.GetGameShieldNextduedate(ctx, int64(shield.Uid), shield.HostId)
		if err != nil {
			t.logger.Error("获取nextduedate失败", zap.Int("用户ID", shield.Uid), zap.Error(err))
			continue
		}

		nextduedateTime, err := strconv.ParseInt(nextduedate, 10, 64)
		if err != nil {
			t.logger.Error("解析nextduedate失败", zap.Error(err))
			continue
		}

		currentTime := time.Now().Unix()
		renewed := nextduedateTime > currentTime

		if renewed {
			// 已过期但已续费，更新过期时间
			shield.ExpireTime = nextduedateTime
			if err := t.gameShieldRepo.UpdateGameShield(ctx, shield); err != nil {
				t.logger.Error("更新过期游戏盾的过期时间失败",
					zap.String("商品", shield.AppName),
					zap.Error(err))
				continue
			}
			// 更新蜗牛的过期时间
			if _, _, err := t.gameShieldBackendService.GameShieldBackend(ctx, &v1.GameShieldBackendArrayRequest{Uid: shield.Uid, HostId: shield.HostId, Items: nil}); err != nil {
				t.logger.Error("更新shd_game_shield_backend表失败", zap.Int("产品id:", shield.HostId), zap.Int("用户id:", shield.Uid), zap.String("商品名:", shield.AppName), zap.Error(err))
				continue
			}

			t.logger.Info("已过期商品续期成功",
				zap.Int("用户ID", shield.Uid),
				zap.String("商品", shield.AppName),
				zap.Time("新过期时间", time.Unix(nextduedateTime, 0)))
		} else {
			// 已过期且未续费，执行过期操作
			t.logger.Info("商品已过期且未续费",
				zap.Int("用户ID", shield.Uid),
				zap.String("商品", shield.AppName))

			// TODO: 添加您的过期处理逻辑，例如：
			// - 发送过期通知
			// - 禁用服务
			// - 标记记录状态
		}
	}

	return nil
}

// CheckSoonExpiredGameShields 检查即将过期的记录并处理续费
func (t gameShieldTask) CheckSoonExpiredGameShields(ctx context.Context) error {
	// 获取7天内即将过期的商品
	soonExpiredShields, err := t.gameShieldRepo.GetSoonExpiredGameShields(ctx, 1)
	if err != nil {
		t.logger.Error("查询即将过期的游戏盾失败", zap.Error(err))
		return err
	}

	t.logger.Info("找到 %d 个即将过期的游戏盾商品", zap.Int("数量", len(soonExpiredShields)))

	// 遍历即将过期的商品
	for _, shield := range soonExpiredShields {
		t.logger.Info("即将过期商品",
			zap.Int("ID", shield.Id),
			zap.Int("用户ID", shield.Uid),
			zap.String("商品", shield.AppName),
			zap.Int("主机ID", shield.HostId),
			zap.Time("过期时间", time.Unix(shield.ExpireTime, 0)))
		currentTime := time.Now().Unix()
		// 检查用户是否已续费（检查nextduedate字段）
		nextduedate, err := t.gameShieldRepo.GetGameShieldNextduedate(ctx, int64(shield.Uid), shield.HostId)
		nextduedateTime, err := strconv.ParseInt(nextduedate, 10, 64)
		if err != nil {
			t.logger.Error("解析nextduedate失败", zap.Error(err))
			continue
		}
		renewed := nextduedateTime > currentTime

		if renewed {
			// 用户已续费，更新shd_game_shield表中的ExpireTime字段
			// 使用shd_host表中的nextduedate作为新的过期时间
			shield.ExpireTime = nextduedateTime

			if err := t.gameShieldRepo.UpdateGameShield(ctx, shield); err != nil {
				t.logger.Error("更新shd_game_shield表失败: %v", zap.Error(err))
				continue
			}

			// 更新蜗牛的过期时间
			if _, _, err := t.gameShieldBackendService.GameShieldBackend(ctx, &v1.GameShieldBackendArrayRequest{Uid: shield.Uid, HostId: shield.HostId, Items: nil}); err != nil {
				t.logger.Error("更新shd_game_shield_backend表失败", zap.Int("产品id:", shield.HostId), zap.Int("用户id:", shield.Uid), zap.String("商品名:", shield.AppName), zap.Error(err))
				continue
			}

			t.logger.Info("自动续期成功: ",
				zap.Int("用户ID", shield.Uid), zap.String("商品", shield.AppName), zap.Time("新过期时间", time.Unix(shield.ExpireTime, 0)))
		} else {
			// 用户未续费，可以发送提醒通知
			t.logger.Info("用户未续费:", zap.Int("用户ID", shield.Uid), zap.String("商品", shield.AppName), zap.Int("hostid", shield.HostId))
		}
	}

	return nil
}

// SyncAllExpireTimeFromHost 同步所有记录的过期时间
func (t gameShieldTask) SyncAllExpireTimeFromHost(ctx context.Context) error {
	// 获取所有游戏盾记录
	shields, err := t.gameShieldRepo.GetAllGameShield(ctx)
	if err != nil {
		t.logger.Error("查询所有游戏盾记录失败", zap.Error(err))
		return err
	}

	t.logger.Info("找到 %d 条游戏盾记录", zap.Int("数量", len(shields)))

	// 同步每条记录的过期时间
	for _, shield := range shields {
		if err := t.gameShieldRepo.SyncExpireTimeFromHostNextDueDate(ctx, shield.Uid, shield.HostId); err != nil {
			t.logger.Error("同步记录过期时间失败: %v", zap.Int("ID", shield.Id), zap.Error(err))
			continue
		}

		t.logger.Info("同步记录过期时间成功", zap.Int("ID", shield.Id))
	}

	return nil
}

// 综合处理已过期和即将过期的记录
func (t gameShieldTask) CheckGameShield(ctx context.Context) error {
	// 先检查已过期的记录
	if err := t.CheckExpiredGameShields(ctx); err != nil {
		return err
	}

	// 再检查即将过期的记录
	if err := t.CheckSoonExpiredGameShields(ctx); err != nil {
		return err
	}

	return nil
}
