package repository

import (
	"context"
	"fmt"
	"sync/atomic"
	"testing"

	_ "modernc.org/sqlite"
	gormsqlite "gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"

	"github.com/user-management-system/internal/domain"
)

var themeTestCounter int64

// openThemeTestDB 为每个测试打开独立的内存数据库
func openThemeTestDB(t *testing.T) *gorm.DB {
	t.Helper()

	id := atomic.AddInt64(&themeTestCounter, 1)
	dsn := fmt.Sprintf("file:themetestdb%d?mode=memory&cache=private", id)

	db, err := gorm.Open(gormsqlite.New(gormsqlite.Config{
		DriverName: "sqlite",
		DSN:        dsn,
	}), &gorm.Config{
		Logger: logger.Default.LogMode(logger.Silent),
	})
	if err != nil {
		t.Fatalf("打开测试数据库失败: %v", err)
	}

	if err := db.AutoMigrate(&domain.ThemeConfig{}); err != nil {
		t.Fatalf("数据库迁移失败: %v", err)
	}
	return db
}

// setupThemeTestDB 兼容性别名
func setupThemeTestDB(t *testing.T) *gorm.DB {
	return openThemeTestDB(t)
}

// TestThemeConfigRepository_Create 测试创建主题
func TestThemeConfigRepository_Create(t *testing.T) {
	db := setupThemeTestDB(t)
	repo := NewThemeConfigRepository(db)
	ctx := context.Background()

	theme := &domain.ThemeConfig{
		Name:           "test-theme",
		PrimaryColor:   "#ff0000",
		SecondaryColor: "#00ff00",
		Enabled:        true,
	}

	if err := repo.Create(ctx, theme); err != nil {
		t.Fatalf("Create() error = %v", err)
	}
	if theme.ID == 0 {
		t.Error("创建后主题ID不应为0")
	}
}

// TestThemeConfigRepository_GetByID 测试根据ID获取主题
func TestThemeConfigRepository_GetByID(t *testing.T) {
	db := setupThemeTestDB(t)
	repo := NewThemeConfigRepository(db)
	ctx := context.Background()

	theme := &domain.ThemeConfig{
		Name:       "getbyid-theme",
		PrimaryColor: "#0000ff",
		Enabled:     true,
	}
	repo.Create(ctx, theme)

	found, err := repo.GetByID(ctx, theme.ID)
	if err != nil {
		t.Fatalf("GetByID() error = %v", err)
	}
	if found.Name != "getbyid-theme" {
		t.Errorf("Name = %v, want getbyid-theme", found.Name)
	}
}

// TestThemeConfigRepository_GetByName 测试根据名称获取主题
func TestThemeConfigRepository_GetByName(t *testing.T) {
	db := setupThemeTestDB(t)
	repo := NewThemeConfigRepository(db)
	ctx := context.Background()

	theme := &domain.ThemeConfig{
		Name:       "unique-theme-name",
		PrimaryColor: "#ffff00",
		Enabled:     true,
	}
	repo.Create(ctx, theme)

	found, err := repo.GetByName(ctx, "unique-theme-name")
	if err != nil {
		t.Fatalf("GetByName() error = %v", err)
	}
	if found.ID != theme.ID {
		t.Errorf("ID = %v, want %v", found.ID, theme.ID)
	}
}

// TestThemeConfigRepository_GetByName_NotFound 测试名称不存在
func TestThemeConfigRepository_GetByName_NotFound(t *testing.T) {
	db := setupThemeTestDB(t)
	repo := NewThemeConfigRepository(db)
	ctx := context.Background()

	_, err := repo.GetByName(ctx, "not-exist-theme")
	if err == nil {
		t.Error("GetByName() should return error for non-existent theme")
	}
}

// TestThemeConfigRepository_Update 测试更新主题
func TestThemeConfigRepository_Update(t *testing.T) {
	db := setupThemeTestDB(t)
	repo := NewThemeConfigRepository(db)
	ctx := context.Background()

	theme := &domain.ThemeConfig{
		Name:         "update-test",
		PrimaryColor: "#000000",
		Enabled:      true,
	}
	repo.Create(ctx, theme)

	theme.PrimaryColor = "#ffffff"
	if err := repo.Update(ctx, theme); err != nil {
		t.Fatalf("Update() error = %v", err)
	}

	found, _ := repo.GetByID(ctx, theme.ID)
	if found.PrimaryColor != "#ffffff" {
		t.Errorf("PrimaryColor = %v, want #ffffff", found.PrimaryColor)
	}
}

// TestThemeConfigRepository_Delete 测试删除主题
func TestThemeConfigRepository_Delete(t *testing.T) {
	db := setupThemeTestDB(t)
	repo := NewThemeConfigRepository(db)
	ctx := context.Background()

	theme := &domain.ThemeConfig{
		Name:    "delete-test",
		Enabled: true,
	}
	repo.Create(ctx, theme)

	if err := repo.Delete(ctx, theme.ID); err != nil {
		t.Fatalf("Delete() error = %v", err)
	}

	_, err := repo.GetByID(ctx, theme.ID)
	if err == nil {
		t.Error("删除后查询应返回错误")
	}
}

// TestThemeConfigRepository_List 测试获取已启用主题列表
func TestThemeConfigRepository_List(t *testing.T) {
	db := setupThemeTestDB(t)
	repo := NewThemeConfigRepository(db)
	ctx := context.Background()

	repo.Create(ctx, &domain.ThemeConfig{Name: "enabled1", Enabled: true})
	repo.Create(ctx, &domain.ThemeConfig{Name: "enabled2", Enabled: true})
	repo.Create(ctx, &domain.ThemeConfig{Name: "disabled1", Enabled: false})

	themes, err := repo.List(ctx)
	if err != nil {
		t.Fatalf("List() error = %v", err)
	}
	// List filters by enabled=true
	if len(themes) < 2 {
		t.Errorf("len(themes) = %d, want at least 2", len(themes))
	}
}

// TestThemeConfigRepository_ListAll 测试获取所有主题列表
func TestThemeConfigRepository_ListAll(t *testing.T) {
	db := setupThemeTestDB(t)
	repo := NewThemeConfigRepository(db)
	ctx := context.Background()

	repo.Create(ctx, &domain.ThemeConfig{Name: "all1", Enabled: true})
	repo.Create(ctx, &domain.ThemeConfig{Name: "all2", Enabled: false})

	themes, err := repo.ListAll(ctx)
	if err != nil {
		t.Fatalf("ListAll() error = %v", err)
	}
	if len(themes) != 2 {
		t.Errorf("len(themes) = %d, want 2", len(themes))
	}
}

// TestThemeConfigRepository_GetDefault 测试获取默认主题
func TestThemeConfigRepository_GetDefault(t *testing.T) {
	db := setupThemeTestDB(t)
	repo := NewThemeConfigRepository(db)
	ctx := context.Background()

	// 创建一个默认主题
	repo.Create(ctx, &domain.ThemeConfig{
		Name:      "default-theme",
		IsDefault: true,
		Enabled:   true,
	})

	defaultTheme, err := repo.GetDefault(ctx)
	if err != nil {
		t.Fatalf("GetDefault() error = %v", err)
	}
	if defaultTheme.Name != "default-theme" {
		t.Errorf("Name = %v, want default-theme", defaultTheme.Name)
	}
}

// TestThemeConfigRepository_GetDefault_NoDefault 测试无默认主题时返回默认配置
func TestThemeConfigRepository_GetDefault_NoDefault(t *testing.T) {
	db := setupThemeTestDB(t)
	repo := NewThemeConfigRepository(db)
	ctx := context.Background()

	// 不创建任何主题
	defaultTheme, err := repo.GetDefault(ctx)
	if err != nil {
		t.Fatalf("GetDefault() error = %v", err)
	}
	// 应该返回内置默认配置
	if defaultTheme.Name != "default" {
		t.Errorf("Name = %v, want default", defaultTheme.Name)
	}
}

// TestThemeConfigRepository_SetDefault 测试设置默认主题
func TestThemeConfigRepository_SetDefault(t *testing.T) {
	db := setupThemeTestDB(t)
	repo := NewThemeConfigRepository(db)
	ctx := context.Background()

	// 创建两个主题
	theme1 := &domain.ThemeConfig{Name: "theme1", IsDefault: true, Enabled: true}
	theme2 := &domain.ThemeConfig{Name: "theme2", IsDefault: false, Enabled: true}
	repo.Create(ctx, theme1)
	repo.Create(ctx, theme2)

	// 设置 theme2 为默认
	if err := repo.SetDefault(ctx, theme2.ID); err != nil {
		t.Fatalf("SetDefault() error = %v", err)
	}

	// 验证 theme1 不再是默认
	t1, _ := repo.GetByID(ctx, theme1.ID)
	if t1.IsDefault {
		t.Error("theme1 should not be default anymore")
	}

	// 验证 theme2 现在是默认
	t2, _ := repo.GetByID(ctx, theme2.ID)
	if !t2.IsDefault {
		t.Error("theme2 should be default")
	}
}
