package service_test

import (
	"context"
	"testing"
	"time"

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

// =============================================================================
// Stats Service Tests - TDD approach
// =============================================================================

// mockStatsUserRepo 模拟用户仓储
type mockStatsUserRepo struct {
	totalUsers    int64
	activeUsers   int64
	inactiveUsers int64
	lockedUsers   int64
	disabledUsers int64
	newUsersToday int64
}

func (m *mockStatsUserRepo) List(ctx context.Context, offset, limit int) ([]*domain.User, int64, error) {
	return nil, m.totalUsers, nil
}

func (m *mockStatsUserRepo) ListByStatus(ctx context.Context, status domain.UserStatus, offset, limit int) ([]*domain.User, int64, error) {
	switch status {
	case domain.UserStatusActive:
		return nil, m.activeUsers, nil
	case domain.UserStatusInactive:
		return nil, m.inactiveUsers, nil
	case domain.UserStatusLocked:
		return nil, m.lockedUsers, nil
	case domain.UserStatusDisabled:
		return nil, m.disabledUsers, nil
	}
	return nil, 0, nil
}

func (m *mockStatsUserRepo) ListCreatedAfter(ctx context.Context, since time.Time, offset, limit int) ([]*domain.User, int64, error) {
	return nil, m.newUsersToday, nil
}

// mockStatsLoginLogRepo 模拟登录日志仓储
type mockStatsLoginLogRepo struct {
	successCount int64
	failedCount  int64
	weekCount    int64
}

func (m *mockStatsLoginLogRepo) CountByResultSince(ctx context.Context, success bool, since time.Time) (int64, error) {
	if success {
		return m.successCount, nil
	}
	return m.failedCount, nil
}

func TestStatsService_GetUserStats(t *testing.T) {
	ctx := context.Background()

	t.Run("获取用户统计", func(t *testing.T) {
		userRepo := &mockStatsUserRepo{
			totalUsers:    100,
			activeUsers:   80,
			inactiveUsers: 10,
			lockedUsers:   5,
			disabledUsers: 5,
			newUsersToday: 3,
		}
		loginLogRepo := &mockStatsLoginLogRepo{}
		svc := service.NewStatsService(userRepo, loginLogRepo)

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

		if stats.TotalUsers != 100 {
			t.Errorf("期望 TotalUsers=100, 得到 %d", stats.TotalUsers)
		}
		if stats.ActiveUsers != 80 {
			t.Errorf("期望 ActiveUsers=80, 得到 %d", stats.ActiveUsers)
		}
		if stats.InactiveUsers != 10 {
			t.Errorf("期望 InactiveUsers=10, 得到 %d", stats.InactiveUsers)
		}
		if stats.LockedUsers != 5 {
			t.Errorf("期望 LockedUsers=5, 得到 %d", stats.LockedUsers)
		}
		if stats.DisabledUsers != 5 {
			t.Errorf("期望 DisabledUsers=5, 得到 %d", stats.DisabledUsers)
		}
	})
}

func TestStatsService_GetDashboardStats(t *testing.T) {
	ctx := context.Background()

	t.Run("获取仪表盘统计", func(t *testing.T) {
		userRepo := &mockStatsUserRepo{
			totalUsers:    50,
			activeUsers:   40,
			inactiveUsers: 5,
			lockedUsers:   3,
			disabledUsers: 2,
			newUsersToday: 2,
		}
		loginLogRepo := &mockStatsLoginLogRepo{
			successCount: 100,
			failedCount:  10,
			weekCount:    500,
		}
		svc := service.NewStatsService(userRepo, loginLogRepo)

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

		if stats.Users.TotalUsers != 50 {
			t.Errorf("期望 Users.TotalUsers=50, 得到 %d", stats.Users.TotalUsers)
		}
		if stats.Logins.LoginsTodaySuccess != 100 {
			t.Errorf("期望 LoginsTodaySuccess=100, 得到 %d", stats.Logins.LoginsTodaySuccess)
		}
		if stats.Logins.LoginsTodayFailed != 10 {
			t.Errorf("期望 LoginsTodayFailed=10, 得到 %d", stats.Logins.LoginsTodayFailed)
		}
	})
}
