package main

import (
	"context"
	"fmt"
	"time"

	"bindbox-game/configs"
	"bindbox-game/internal/pkg/logger"
	"bindbox-game/internal/repository/mysql"
	"bindbox-game/internal/repository/mysql/dao"
	"bindbox-game/internal/repository/mysql/model"
	tcmodel "bindbox-game/internal/repository/mysql/task_center"
	tasksvc "bindbox-game/internal/service/task_center"
	"bindbox-game/internal/service/title"
	"bindbox-game/internal/service/user"

	"github.com/redis/go-redis/v9"
)

// IntegrationTest 运行集成测试流
func IntegrationTest(repo mysql.Repo) error {
	ctx := context.Background()
	cfg := configs.Get()

	// 1. 初始化日志（自定义）
	l, err := logger.NewCustomLogger(dao.Use(repo.GetDbW()))
	if err != nil {
		return fmt.Errorf("初始化日志失败: %v", err)
	}

	// 2. 初始化 Redis
	rdb := redis.NewClient(&redis.Options{
		Addr:     cfg.Redis.Addr,
		Password: cfg.Redis.Pass,
		DB:       cfg.Redis.DB,
	})
	if err := rdb.Ping(ctx).Err(); err != nil {
		return fmt.Errorf("连接 Redis 失败: %v", err)
	}

	// 3. 初始化依赖服务
	userSvc := user.New(l, repo)
	titleSvc := title.New(l, repo)
	taskSvc := tasksvc.New(l, repo, rdb, userSvc, titleSvc)

	// 3.5 清理缓存以确保能加载最新配置
	if err := rdb.Del(ctx, "task_center:active_tasks").Err(); err != nil {
		fmt.Printf("⚠️ 清理缓存失败: %v\n", err)
	}

	// 4. 选择一个测试用户和任务
	// ... (代码逻辑不变)
	userID := int64(8888)

	// 搜索一个首单任务（满足 lifetime 窗口，奖励为点数）
	var task tcmodel.Task
	db := repo.GetDbW()
	if err := db.Joins("JOIN task_center_task_tiers ON task_center_task_tiers.task_id = task_center_tasks.id").
		Joins("JOIN task_center_task_rewards ON task_center_task_rewards.task_id = task_center_tasks.id").
		Where("task_center_task_tiers.metric = ? AND task_center_task_tiers.window = ? AND task_center_task_rewards.reward_type = ?", "first_order", "lifetime", "points").
		First(&task).Error; err != nil {
		return fmt.Errorf("未找到符合条件的集成测试任务: %v", err)
	}

	fmt.Printf("--- 开始集成测试 ---\n")
	fmt.Printf("用户ID: %d, 任务ID: %d (%s)\n", userID, task.ID, task.Name)

	// 5. 创建一个模拟订单
	orderNo := fmt.Sprintf("TEST_ORDER_%d", time.Now().Unix())
	order := &model.Orders{
		UserID:       userID,
		OrderNo:      orderNo,
		TotalAmount:  100,
		ActualAmount: 100,
		Status:       2, // 已支付
		PaidAt:       time.Now(),
	}
	if err := db.Omit("cancelled_at").Create(order).Error; err != nil {
		return fmt.Errorf("创建测试订单失败: %v", err)
	}
	fmt.Printf("创建测试订单: %s (ID: %d)\n", orderNo, order.ID)

	// 6. 触发 OnOrderPaid
	fmt.Println("触发 OnOrderPaid 事件...")
	if err := taskSvc.OnOrderPaid(ctx, userID, order.ID); err != nil {
		return fmt.Errorf("OnOrderPaid 失败: %v", err)
	}

	// 7. 验证结果
	// A. 检查进度是否更新
	var progress tcmodel.UserTaskProgress
	if err := db.Where("user_id = ? AND task_id = ?", userID, task.ID).First(&progress).Error; err != nil {
		fmt.Printf("❌ 进度记录未找到: %v\n", err)
	} else {
		fmt.Printf("✅ 进度记录已更新: first_order=%d\n", progress.FirstOrder)
	}

	// B. 检查奖励日志
	time.Sleep(1 * time.Second)

	var eventLog tcmodel.TaskEventLog
	if err := db.Where("user_id = ? AND task_id = ?", userID, task.ID).Order("id desc").First(&eventLog).Error; err != nil {
		fmt.Printf("❌ 奖励日志未找到: %v\n", err)
	} else {
		fmt.Printf("✅ 奖励日志已找到: Status=%s, Result=%s\n", eventLog.Status, eventLog.Result)
		if eventLog.Status == "granted" {
			fmt.Printf("🎉 集成测试通过！奖励已成功发放。\n")
		} else {
			fmt.Printf("⚠️ 奖励发放状态异常: %s\n", eventLog.Status)
		}
	}

	return nil
}

// InviteAndTaskIntegrationTest 运行邀请与任务全链路集成测试
func InviteAndTaskIntegrationTest(repo mysql.Repo) error {
	ctx := context.Background()
	cfg := configs.Get()
	db := repo.GetDbW()

	// 1. 初始化
	l, _ := logger.NewCustomLogger(dao.Use(db))
	rdb := redis.NewClient(&redis.Options{Addr: cfg.Redis.Addr, Password: cfg.Redis.Pass, DB: cfg.Redis.DB})
	userSvc := user.New(l, repo)
	titleSvc := title.New(l, repo)
	taskSvc := tasksvc.New(l, repo, rdb, userSvc, titleSvc)

	// 2. 准备角色
	inviterID := int64(9001)
	inviteeID := int64(9002)
	_ = ensureUserExists(repo, inviterID, "老司机(邀请者)")
	_ = ensureUserExists(repo, inviteeID, "萌新(被邀请者)")

	// 3. 建立邀请关系
	if err := ensureInviteRelationship(repo, inviterID, inviteeID); err != nil {
		return fmt.Errorf("建立邀请关系失败: %v", err)
	}

	// 4. 清理 Redis 缓存
	_ = rdb.Del(ctx, "task_center:active_tasks").Err()

	// 5. 查找测试任务
	var inviteTask tcmodel.Task
	if err := db.Joins("JOIN task_center_task_tiers ON task_center_task_tiers.task_id = task_center_tasks.id").
		Where("task_center_task_tiers.metric = ? AND task_center_task_tiers.window = ?", "invite_count", "lifetime").
		First(&inviteTask).Error; err != nil {
		return fmt.Errorf("未找到邀请任务: %v", err)
	}

	var firstOrderTask tcmodel.Task
	if err := db.Joins("JOIN task_center_task_tiers ON task_center_task_tiers.task_id = task_center_tasks.id").
		Where("task_center_task_tiers.metric = ? AND task_center_task_tiers.window = ?", "first_order", "lifetime").
		First(&firstOrderTask).Error; err != nil {
		return fmt.Errorf("未找到首单任务: %v", err)
	}

	fmt.Printf("--- 开始邀请全链路测试 ---\n")
	fmt.Printf("邀请人: %d, 被邀请人: %d\n", inviterID, inviteeID)

	// 6. 模拟邀请成功事件 (触发两次以确保达到默认阈值 2)
	fmt.Println("触发 OnInviteSuccess 事件 (第1次)...")
	if err := taskSvc.OnInviteSuccess(ctx, inviterID, inviteeID); err != nil {
		return fmt.Errorf("OnInviteSuccess 失败: %v", err)
	}
	fmt.Println("触发 OnInviteSuccess 事件 (第2次, 换个用户ID)...")
	if err := taskSvc.OnInviteSuccess(ctx, inviterID, 9999); err != nil {
		return fmt.Errorf("OnInviteSuccess 失败: %v", err)
	}

	// 7. 模拟被邀请者下单
	orderNo := fmt.Sprintf("INVITE_ORDER_%d", time.Now().Unix())
	order := &model.Orders{
		UserID:       inviteeID,
		OrderNo:      orderNo,
		TotalAmount:  100,
		ActualAmount: 100,
		Status:       2, // 已支付
		PaidAt:       time.Now(),
	}
	if err := db.Omit("cancelled_at").Create(order).Error; err != nil {
		return fmt.Errorf("创建被邀请者订单失败: %v", err)
	}
	fmt.Printf("被邀请者下单成功: %s (ID: %d)\n", orderNo, order.ID)

	fmt.Println("触发 OnOrderPaid 事件 (被邀请者)...")
	if err := taskSvc.OnOrderPaid(ctx, inviteeID, order.ID); err != nil {
		return fmt.Errorf("OnOrderPaid 失败: %v", err)
	}

	// 8. 验证
	time.Sleep(1 * time.Second)

	fmt.Println("\n--- 数据库进度核查 ---")
	var allProgress []tcmodel.UserTaskProgress
	db.Where("user_id IN (?)", []int64{inviterID, inviteeID}).Find(&allProgress)
	if len(allProgress) == 0 {
		fmt.Println("⚠️ 数据库中未找到任何进度记录！")
	}
	for _, p := range allProgress {
		userLabel := "邀请人"
		if p.UserID == inviteeID {
			userLabel = "被邀请人"
		}
		fmt.Printf("[%s] 用户:%d 任务:%d | Invite=%d, OrderCount=%d, FirstOrder=%d\n",
			userLabel, p.UserID, p.TaskID, p.InviteCount, p.OrderCount, p.FirstOrder)
	}

	fmt.Println("\n--- 奖励发放核查 ---")
	var logs []tcmodel.TaskEventLog
	db.Where("user_id IN (?) AND status = ?", []int64{inviterID, inviteeID}, "granted").Find(&logs)
	fmt.Printf("✅ 累计发放奖励次数: %d\n", len(logs))
	for _, l := range logs {
		fmt.Printf("  - 用户 %d 触发任务 %d 奖励 | Source:%s\n", l.UserID, l.TaskID, l.SourceType)
	}

	if len(logs) >= 2 {
		fmt.Println("\n🎉 邀请全链路集成测试通过！邀请人和被邀请人都获得了奖励。")
	} else {
		fmt.Printf("\n⚠️ 测试部分完成，奖励次数(%d)少于预期(2)\n", len(logs))
	}
	return nil
}

// 模拟创建用户的方法（如果不存在）
func ensureUserExists(repo mysql.Repo, userID int64, nickname string) error {
	db := repo.GetDbW()
	var user model.Users
	if err := db.Where("id = ?", userID).First(&user).Error; err != nil {
		user = model.Users{
			ID:         userID,
			Nickname:   nickname,
			Avatar:     "http://example.com/a.png",
			Status:     1,
			InviteCode: fmt.Sprintf("CODE%d", userID),
		}
		if err := db.Create(&user).Error; err != nil {
			return err
		}
		fmt.Printf("已确保测试用户存在: %d (%s)\n", userID, nickname)
	}
	return nil
}

// 建立邀请关系
func ensureInviteRelationship(repo mysql.Repo, inviterID, inviteeID int64) error {
	db := repo.GetDbW()
	var rel model.UserInvites
	if err := db.Where("invitee_id = ?", inviteeID).First(&rel).Error; err != nil {
		rel = model.UserInvites{
			InviterID:  inviterID,
			InviteeID:  inviteeID,
			InviteCode: fmt.Sprintf("CODE%d", inviterID),
		}
		return db.Omit("rewarded_at").Create(&rel).Error
	}
	// 如果已存在但邀请人不对，修正它
	if rel.InviterID != inviterID {
		return db.Model(&rel).Update("inviter_id", inviterID).Error
	}
	return nil
}
