package service_test

import (
	"context"
	"testing"

	"github.com/user-management-system/internal/domain"
	"github.com/user-management-system/internal/repository"
	"github.com/user-management-system/internal/service"
	gormsqlite "gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

// =============================================================================
// Permission Service Tests
// =============================================================================

func setupPermissionTestEnv(t *testing.T) (*service.PermissionService, *gorm.DB) {
	t.Helper()

	db, err := gorm.Open(gormsqlite.New(gormsqlite.Config{
		DriverName: "sqlite",
		DSN:        "file:perm_test?mode=memory&cache=shared",
	}), &gorm.Config{
		Logger: logger.Default.LogMode(logger.Silent),
	})
	if err != nil {
		t.Fatalf("failed to connect database: %v", err)
	}

	if err := db.AutoMigrate(&domain.Permission{}); err != nil {
		t.Fatalf("failed to migrate: %v", err)
	}

	permissionRepo := repository.NewPermissionRepository(db)
	permSvc := service.NewPermissionService(permissionRepo)

	return permSvc, db
}

func TestPermissionService_CreatePermission(t *testing.T) {
	svc, _ := setupPermissionTestEnv(t)
	ctx := context.Background()

	t.Run("Create permission success", func(t *testing.T) {
		req := &service.CreatePermissionRequest{
			Name:        "测试权限",
			Code:        "test_perm",
			Type:        int(domain.PermissionTypeMenu),
			Description: "测试权限描述",
		}
		perm, err := svc.CreatePermission(ctx, req)
		if err != nil {
			t.Fatalf("CreatePermission failed: %v", err)
		}
		if perm.Code != "test_perm" {
			t.Errorf("Expected code 'test_perm', got %s", perm.Code)
		}
		if perm.Level != 1 {
			t.Errorf("Expected level 1, got %d", perm.Level)
		}
	})

	t.Run("Create permission with duplicate code", func(t *testing.T) {
		req := &service.CreatePermissionRequest{
			Name: "重复权限",
			Code: "test_perm", // duplicate
			Type: int(domain.PermissionTypeMenu),
		}
		_, err := svc.CreatePermission(ctx, req)
		if err == nil {
			t.Error("Expected error for duplicate code")
		}
	})

	t.Run("Create permission with parent", func(t *testing.T) {
		// Create parent first
		parentReq := &service.CreatePermissionRequest{
			Name: "父权限",
			Code: "parent_perm",
			Type: int(domain.PermissionTypeMenu),
		}
		parent, _ := svc.CreatePermission(ctx, parentReq)

		// Create child
		childReq := &service.CreatePermissionRequest{
			Name:     "子权限",
			Code:     "child_perm",
			Type:     int(domain.PermissionTypeButton),
			ParentID: &parent.ID,
		}
		child, err := svc.CreatePermission(ctx, childReq)
		if err != nil {
			t.Fatalf("CreatePermission with parent failed: %v", err)
		}
		if child.Level != 2 {
			t.Errorf("Expected level 2, got %d", child.Level)
		}
	})

	t.Run("Create permission with non-existent parent", func(t *testing.T) {
		nonExistentID := int64(9999)
		req := &service.CreatePermissionRequest{
			Name:     "孤儿权限",
			Code:     "orphan_perm",
			Type:     int(domain.PermissionTypeMenu),
			ParentID: &nonExistentID,
		}
		_, err := svc.CreatePermission(ctx, req)
		if err == nil {
			t.Error("Expected error for non-existent parent")
		}
	})
}

func TestPermissionService_UpdatePermission(t *testing.T) {
	svc, _ := setupPermissionTestEnv(t)
	ctx := context.Background()

	// Create test permission
	req := &service.CreatePermissionRequest{
		Name: "更新测试",
		Code: "update_perm",
		Type: int(domain.PermissionTypeMenu),
	}
	perm, _ := svc.CreatePermission(ctx, req)

	t.Run("Update permission name", func(t *testing.T) {
		updateReq := &service.UpdatePermissionRequest{
			Name: "更新后名称",
		}
		updated, err := svc.UpdatePermission(ctx, perm.ID, updateReq)
		if err != nil {
			t.Fatalf("UpdatePermission failed: %v", err)
		}
		if updated.Name != "更新后名称" {
			t.Errorf("Expected name '更新后名称', got %s", updated.Name)
		}
	})

	t.Run("Update permission path and method", func(t *testing.T) {
		updateReq := &service.UpdatePermissionRequest{
			Path:   "/api/test",
			Method: "GET",
		}
		updated, err := svc.UpdatePermission(ctx, perm.ID, updateReq)
		if err != nil {
			t.Fatalf("UpdatePermission failed: %v", err)
		}
		if updated.Path != "/api/test" {
			t.Errorf("Expected path '/api/test', got %s", updated.Path)
		}
	})

	t.Run("Update non-existent permission", func(t *testing.T) {
		updateReq := &service.UpdatePermissionRequest{
			Name: "不存在",
		}
		_, err := svc.UpdatePermission(ctx, 9999, updateReq)
		if err == nil {
			t.Error("Expected error for non-existent permission")
		}
	})

	t.Run("Update permission with self as parent", func(t *testing.T) {
		updateReq := &service.UpdatePermissionRequest{
			ParentID: &perm.ID,
		}
		_, err := svc.UpdatePermission(ctx, perm.ID, updateReq)
		if err == nil {
			t.Error("Expected error for self-parent")
		}
	})
}

func TestPermissionService_DeletePermission(t *testing.T) {
	svc, _ := setupPermissionTestEnv(t)
	ctx := context.Background()

	t.Run("Delete permission success", func(t *testing.T) {
		req := &service.CreatePermissionRequest{
			Name: "待删除权限",
			Code: "delete_perm",
			Type: int(domain.PermissionTypeMenu),
		}
		perm, _ := svc.CreatePermission(ctx, req)

		err := svc.DeletePermission(ctx, perm.ID)
		if err != nil {
			t.Fatalf("DeletePermission failed: %v", err)
		}
	})

	t.Run("Delete non-existent permission", func(t *testing.T) {
		err := svc.DeletePermission(ctx, 9999)
		if err == nil {
			t.Error("Expected error for non-existent permission")
		}
	})
}

func TestPermissionService_GetPermission(t *testing.T) {
	svc, _ := setupPermissionTestEnv(t)
	ctx := context.Background()

	req := &service.CreatePermissionRequest{
		Name: "获取测试",
		Code: "get_perm",
		Type: int(domain.PermissionTypeMenu),
	}
	created, _ := svc.CreatePermission(ctx, req)

	t.Run("Get permission success", func(t *testing.T) {
		perm, err := svc.GetPermission(ctx, created.ID)
		if err != nil {
			t.Fatalf("GetPermission failed: %v", err)
		}
		if perm.Code != "get_perm" {
			t.Errorf("Expected code 'get_perm', got %s", perm.Code)
		}
	})

	t.Run("Get non-existent permission", func(t *testing.T) {
		_, err := svc.GetPermission(ctx, 9999)
		if err == nil {
			t.Error("Expected error for non-existent permission")
		}
	})
}

func TestPermissionService_ListPermissions(t *testing.T) {
	svc, _ := setupPermissionTestEnv(t)
	ctx := context.Background()

	// Create test permissions
	for i := 0; i < 5; i++ {
		req := &service.CreatePermissionRequest{
			Name: "列表权限",
			Code: string(rune('a' + i)),
			Type: int(domain.PermissionTypeMenu),
		}
		svc.CreatePermission(ctx, req)
	}

	t.Run("List permissions with pagination", func(t *testing.T) {
		req := &service.ListPermissionRequest{
			Page:     1,
			PageSize: 3,
		}
		perms, total, err := svc.ListPermissions(ctx, req)
		if err != nil {
			t.Fatalf("ListPermissions failed: %v", err)
		}
		if len(perms) > 3 {
			t.Errorf("Expected max 3 permissions, got %d", len(perms))
		}
		if total < 5 {
			t.Errorf("Expected total >= 5, got %d", total)
		}
	})

	t.Run("List permissions with default pagination", func(t *testing.T) {
		req := &service.ListPermissionRequest{}
		_, _, err := svc.ListPermissions(ctx, req)
		if err != nil {
			t.Fatalf("ListPermissions failed: %v", err)
		}
	})

	t.Run("List permissions with keyword", func(t *testing.T) {
		req := &service.ListPermissionRequest{
			Keyword: "列表",
		}
		perms, _, err := svc.ListPermissions(ctx, req)
		if err != nil {
			t.Fatalf("ListPermissions failed: %v", err)
		}
		if len(perms) == 0 {
			t.Error("Expected permissions with keyword")
		}
	})
}

func TestPermissionService_GetPermissionTree(t *testing.T) {
	svc, _ := setupPermissionTestEnv(t)
	ctx := context.Background()

	// Create parent permission
	parentReq := &service.CreatePermissionRequest{
		Name: "父权限",
		Code: "tree_parent",
		Type: int(domain.PermissionTypeMenu),
	}
	parent, _ := svc.CreatePermission(ctx, parentReq)

	// Create child permission
	childReq := &service.CreatePermissionRequest{
		Name:     "子权限",
		Code:     "tree_child",
		Type:     int(domain.PermissionTypeButton),
		ParentID: &parent.ID,
	}
	svc.CreatePermission(ctx, childReq)

	t.Run("Get permission tree", func(t *testing.T) {
		tree, err := svc.GetPermissionTree(ctx)
		if err != nil {
			t.Fatalf("GetPermissionTree failed: %v", err)
		}
		if len(tree) == 0 {
			t.Error("Expected permission tree")
		}
	})
}

func TestPermissionService_UpdatePermissionStatus(t *testing.T) {
	svc, _ := setupPermissionTestEnv(t)
	ctx := context.Background()

	req := &service.CreatePermissionRequest{
		Name: "状态测试",
		Code: "status_perm",
		Type: int(domain.PermissionTypeMenu),
	}
	perm, _ := svc.CreatePermission(ctx, req)

	t.Run("Update status success", func(t *testing.T) {
		err := svc.UpdatePermissionStatus(ctx, perm.ID, domain.PermissionStatusDisabled)
		if err != nil {
			t.Fatalf("UpdatePermissionStatus failed: %v", err)
		}
	})
}
