package service_test

import (
	"context"
	"testing"

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

// =============================================================================
// UserService Roles Tests
// =============================================================================

func TestUserService_GetUserRoles(t *testing.T) {
	env := setupAuthTestEnv(t)
	if env == nil {
		return
	}
	ctx := context.Background()

	// Create test user
	user := &domain.User{
		Username: "userroles",
		Password: "$2a$10$hash",
		Status:   domain.UserStatusActive,
	}
	env.userSvc.Create(ctx, user)

	t.Run("Get user roles for existing user", func(t *testing.T) {
		roles, err := env.userSvc.GetUserRoles(ctx, user.ID)
		if err != nil {
			t.Fatalf("GetUserRoles failed: %v", err)
		}
		// User may have no roles initially
		_ = roles
	})

	t.Run("Get user roles for non-existent user", func(t *testing.T) {
		_, err := env.userSvc.GetUserRoles(ctx, 99999)
		if err == nil {
			t.Error("Expected error for non-existent user")
		}
	})

	t.Run("Get user roles with zero ID", func(t *testing.T) {
		_, err := env.userSvc.GetUserRoles(ctx, 0)
		if err == nil {
			t.Error("Expected error for zero user ID")
		}
	})
}

func TestUserService_AssignRoles(t *testing.T) {
	env := setupAuthTestEnv(t)
	if env == nil {
		return
	}
	ctx := context.Background()

	// Create test user
	user := &domain.User{
		Username: "assignroles",
		Password: "$2a$10$hash",
		Status:   domain.UserStatusActive,
	}
	env.userSvc.Create(ctx, user)

	t.Run("Assign roles to user", func(t *testing.T) {
		err := env.userSvc.AssignRoles(ctx, user.ID, []int64{1, 2})
		// May fail if roles don't exist, but should not panic
		_ = err
		t.Logf("AssignRoles returned: %v", err)
	})

	t.Run("Assign empty roles", func(t *testing.T) {
		err := env.userSvc.AssignRoles(ctx, user.ID, []int64{})
		_ = err
		t.Logf("Assign empty roles returned: %v", err)
	})

	t.Run("Assign roles to non-existent user", func(t *testing.T) {
		err := env.userSvc.AssignRoles(ctx, 99999, []int64{1})
		if err == nil {
			t.Error("Expected error for non-existent user")
		}
	})
}

func TestUserService_ListAdmins(t *testing.T) {
	env := setupAuthTestEnv(t)
	if env == nil {
		return
	}
	ctx := context.Background()

	t.Run("List admins", func(t *testing.T) {
		admins, err := env.userSvc.ListAdmins(ctx)
		if err != nil {
			t.Fatalf("ListAdmins failed: %v", err)
		}
		// May return empty list
		_ = admins
	})
}

func TestUserService_BatchDelete(t *testing.T) {
	env := setupAuthTestEnv(t)
	if env == nil {
		return
	}
	ctx := context.Background()

	// Create test users
	user1 := &domain.User{
		Username: "batchdel1",
		Password: "$2a$10$hash",
		Status:   domain.UserStatusActive,
	}
	user2 := &domain.User{
		Username: "batchdel2",
		Password: "$2a$10$hash",
		Status:   domain.UserStatusActive,
	}
	env.userSvc.Create(ctx, user1)
	env.userSvc.Create(ctx, user2)

	t.Run("Batch delete users", func(t *testing.T) {
		_, err := env.userSvc.BatchDelete(ctx, &service.BatchDeleteRequest{IDs: []int64{user1.ID, user2.ID}})
		if err != nil {
			t.Fatalf("BatchDelete failed: %v", err)
		}

		// Verify deletion
		_, err1 := env.userSvc.GetByID(ctx, user1.ID)
		_, err2 := env.userSvc.GetByID(ctx, user2.ID)
		if err1 == nil || err2 == nil {
			t.Error("Expected users to be deleted")
		}
	})

	t.Run("Batch delete empty list", func(t *testing.T) {
		_, err := env.userSvc.BatchDelete(ctx, &service.BatchDeleteRequest{IDs: []int64{}})
		_ = err
		t.Logf("BatchDelete empty list returned: %v", err)
	})
}

func TestUserService_ListCursor(t *testing.T) {
	env := setupAuthTestEnv(t)
	if env == nil {
		return
	}
	ctx := context.Background()

	// Create test users
	for i := 0; i < 5; i++ {
		user := &domain.User{
			Username: "cursoruser_" + string(rune('a'+i)),
			Password: "$2a$10$hash",
			Status:   domain.UserStatusActive,
		}
		env.userSvc.Create(ctx, user)
	}

	t.Run("List users with cursor", func(t *testing.T) {
		req := &service.ListCursorRequest{
			Cursor:    "",
			Size:      10,
			SortBy:    "id",
			SortOrder: "asc",
		}
		resp, err := env.userSvc.ListCursor(ctx, req)
		if err != nil {
			t.Fatalf("ListCursor failed: %v", err)
		}
		// Check that we got a valid response
		if resp == nil {
			t.Error("Expected response to not be nil")
		}
		// Items may be empty if no users match
		t.Logf("ListCursor returned %d items", len(resp.Items))
	})

	t.Run("List users with cursor invalid size", func(t *testing.T) {
		req := &service.ListCursorRequest{
			Cursor:    "",
			Size:      0,
			SortBy:    "id",
			SortOrder: "asc",
		}
		_, err := env.userSvc.ListCursor(ctx, req)
		_ = err
		t.Logf("ListCursor with zero size returned: %v", err)
	})
}
