package mysql

import (
	"context"
	"testing"

	mysqldriver "github.com/go-sql-driver/mysql"
	"hyapp/internal/testutil/mysqlschema"
	"hyapp/pkg/appcode"
	"hyapp/pkg/xerr"
	robotdomain "hyapp/services/robot-service/internal/domain/robot"
)

func TestMigrateLegacyGameRobotsCopiesOnceIntoRobotDatabase(t *testing.T) {
	caller := mysqlschema.CallerFile(t, 1)
	legacy := mysqlschema.New(t, mysqlschema.Config{
		InitDBPath:     mysqlschema.InitDBPath(t, caller, "../../../../game-service/deploy/mysql/initdb/001_game_service.sql"),
		DatabasePrefix: "hy_game_legacy_test",
	})
	robot := mysqlschema.New(t, mysqlschema.Config{
		InitDBPath:     mysqlschema.InitDBPath(t, caller, "../../../deploy/mysql/initdb/001_robot_service.sql"),
		DatabasePrefix: "hy_robot_test",
	})
	legacyDSN, err := mysqldriver.ParseDSN(legacy.DSN)
	if err != nil {
		t.Fatalf("parse legacy dsn failed: %v", err)
	}
	ctx := appcode.WithContext(context.Background(), "lalu")
	nowMS := int64(1781200000000)
	if _, err := legacy.DB.ExecContext(ctx,
		`INSERT INTO game_self_game_robots (
		   app_code, game_id, user_id, status, created_by_admin_id, created_at_ms, updated_at_ms, last_used_at_ms, used_count
		 ) VALUES
		   (?, 'dice', ?, 'disabled', 7, ?, ?, 11, 1),
		   (?, 'rock', ?, 'active', 7, ?, ?, 22, 2),
		   (?, 'dice', ?, 'disabled', 8, ?, ?, 33, 3)`,
		"lalu", int64(101), nowMS, nowMS+1,
		"lalu", int64(101), nowMS+2, nowMS+3,
		"lalu", int64(202), nowMS+4, nowMS+5,
	); err != nil {
		t.Fatalf("seed legacy robots failed: %v", err)
	}

	repo, err := Open(ctx, robot.DSN)
	if err != nil {
		t.Fatalf("open robot repo failed: %v", err)
	}
	t.Cleanup(func() { _ = repo.Close() })

	result, err := repo.MigrateLegacyGameRobots(ctx, legacyDSN.DBName)
	if err != nil {
		t.Fatalf("migrate legacy robots failed: %v", err)
	}
	if !result.Applied || !result.SourceFound || result.MigratedRows != 2 {
		t.Fatalf("migration result mismatch: %+v", result)
	}
	items, _, err := repo.ListGameRobots(ctx, "lalu", "rock", "", 20, "")
	if err != nil {
		t.Fatalf("list migrated robots failed: %v", err)
	}
	if len(items) != 2 {
		t.Fatalf("migrated robots length = %d, want 2: %+v", len(items), items)
	}
	if items[0].UserID != 101 || items[0].Status != robotdomain.StatusActive || items[0].UsedCount != 2 || items[0].LastUsedAtMS != 22 {
		t.Fatalf("active aggregated robot mismatch: %+v", items[0])
	}
	if items[1].UserID != 202 || items[1].Status != robotdomain.StatusDisabled || items[1].UsedCount != 3 || items[1].LastUsedAtMS != 33 {
		t.Fatalf("disabled migrated robot mismatch: %+v", items[1])
	}

	if _, err := legacy.DB.ExecContext(ctx,
		`INSERT INTO game_self_game_robots (
		   app_code, game_id, user_id, status, created_by_admin_id, created_at_ms, updated_at_ms, last_used_at_ms, used_count
		 ) VALUES (?, 'dice', ?, 'active', 9, ?, ?, 44, 4)`,
		"lalu", int64(303), nowMS+6, nowMS+7,
	); err != nil {
		t.Fatalf("seed post-migration legacy robot failed: %v", err)
	}
	result, err = repo.MigrateLegacyGameRobots(ctx, legacyDSN.DBName)
	if err != nil {
		t.Fatalf("rerun legacy migration failed: %v", err)
	}
	if result.Applied {
		t.Fatalf("migration must be one-shot after marker, got %+v", result)
	}
	items, _, err = repo.ListGameRobots(ctx, "lalu", "dice", "", 20, "")
	if err != nil {
		t.Fatalf("list after migration rerun failed: %v", err)
	}
	if len(items) != 2 {
		t.Fatalf("rerun must not import new legacy rows, got %+v", items)
	}
}

func TestPickGameRobotUsesRobotTableAndExcludesParticipants(t *testing.T) {
	caller := mysqlschema.CallerFile(t, 1)
	schema := mysqlschema.New(t, mysqlschema.Config{
		InitDBPath:     mysqlschema.InitDBPath(t, caller, "../../../deploy/mysql/initdb/001_robot_service.sql"),
		DatabasePrefix: "hy_robot_test",
	})
	ctx := appcode.WithContext(context.Background(), "lalu")
	repo, err := Open(ctx, schema.DSN)
	if err != nil {
		t.Fatalf("open robot repo failed: %v", err)
	}
	t.Cleanup(func() { _ = repo.Close() })
	if _, err := repo.RegisterGameRobots(ctx, "lalu", "dice", []int64{101, 202}, 7, 1781200000000); err != nil {
		t.Fatalf("register game robots failed: %v", err)
	}
	if _, err := repo.PickGameRobot(ctx, "lalu", "dice", []int64{101, 202}, 1781200000100); !xerr.IsCode(err, xerr.NotFound) {
		t.Fatalf("all excluded robots should return NotFound, got %v", err)
	}
	robot, err := repo.PickGameRobot(ctx, "lalu", "rock", []int64{101}, 1781200000200)
	if err != nil {
		t.Fatalf("pick available robot failed: %v", err)
	}
	if robot.UserID != 202 || robot.GameID != "rock" || robot.LastUsedAtMS != 1781200000200 || robot.UsedCount != 1 {
		t.Fatalf("picked robot mismatch: %+v", robot)
	}
}
