package service

import (
	"context"
	"time"

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

// Interfaces for dependency inversion (DIP) — service layer depends on these abstractions, not concrete types.
type statsUserRepository interface {
	List(ctx context.Context, offset, limit int) ([]*domain.User, int64, error)
	ListByStatus(ctx context.Context, status domain.UserStatus, offset, limit int) ([]*domain.User, int64, error)
	ListCreatedAfter(ctx context.Context, since time.Time, offset, limit int) ([]*domain.User, int64, error)
}

type statsLoginLogRepository interface {
	CountByResultSince(ctx context.Context, success bool, since time.Time) (int64, error)
}

// StatsService 统计服务
type StatsService struct {
	userRepo     statsUserRepository
	loginLogRepo statsLoginLogRepository
}

// NewStatsService 创建统计服务
func NewStatsService(
	userRepo statsUserRepository,
	loginLogRepo statsLoginLogRepository,
) *StatsService {
	return &StatsService{
		userRepo:     userRepo,
		loginLogRepo: loginLogRepo,
	}
}

// UserStats 用户统计数据
type UserStats struct {
	TotalUsers    int64 `json:"total_users"`
	ActiveUsers   int64 `json:"active_users"`
	InactiveUsers int64 `json:"inactive_users"`
	LockedUsers   int64 `json:"locked_users"`
	DisabledUsers int64 `json:"disabled_users"`
	NewUsersToday int64 `json:"new_users_today"`
	NewUsersWeek  int64 `json:"new_users_week"`
	NewUsersMonth int64 `json:"new_users_month"`
}

// LoginStats 登录统计数据
type LoginStats struct {
	LoginsTodaySuccess int64 `json:"logins_today_success"`
	LoginsTodayFailed  int64 `json:"logins_today_failed"`
	LoginsWeek         int64 `json:"logins_week"`
}

// DashboardStats 仪表盘综合统计
type DashboardStats struct {
	Users  UserStats  `json:"users"`
	Logins LoginStats `json:"logins"`
}

// GetUserStats 获取用户统计
func (s *StatsService) GetUserStats(ctx context.Context) (*UserStats, error) {
	stats := &UserStats{}

	// 统计总用户数
	_, total, err := s.userRepo.List(ctx, 0, 1)
	if err != nil {
		return nil, err
	}
	stats.TotalUsers = total

	// 按状态统计
	statusCounts := map[domain.UserStatus]*int64{
		domain.UserStatusActive:   &stats.ActiveUsers,
		domain.UserStatusInactive: &stats.InactiveUsers,
		domain.UserStatusLocked:   &stats.LockedUsers,
		domain.UserStatusDisabled: &stats.DisabledUsers,
	}
	for status, countPtr := range statusCounts {
		_, cnt, err := s.userRepo.ListByStatus(ctx, status, 0, 1)
		if err == nil {
			*countPtr = cnt
		}
	}

	// 今日新增
	stats.NewUsersToday = s.countNewUsers(ctx, daysAgo(0))
	// 本周新增
	stats.NewUsersWeek = s.countNewUsers(ctx, daysAgo(7))
	// 本月新增
	stats.NewUsersMonth = s.countNewUsers(ctx, daysAgo(30))

	return stats, nil
}

// countNewUsers 统计指定时间之后的新增用户数
func (s *StatsService) countNewUsers(ctx context.Context, since time.Time) int64 {
	_, count, err := s.userRepo.ListCreatedAfter(ctx, since, 0, 0)
	if err != nil {
		return 0
	}
	return count
}

// GetDashboardStats 获取仪表盘综合统计
func (s *StatsService) GetDashboardStats(ctx context.Context) (*DashboardStats, error) {
	userStats, err := s.GetUserStats(ctx)
	if err != nil {
		return nil, err
	}

	loginStats := &LoginStats{}
	// 今日登录成功/失败
	today := daysAgo(0)
	if s.loginLogRepo != nil {
		if successCount, err := s.loginLogRepo.CountByResultSince(ctx, true, today); err == nil {
			loginStats.LoginsTodaySuccess = successCount
		}
		if failedCount, err := s.loginLogRepo.CountByResultSince(ctx, false, today); err == nil {
			loginStats.LoginsTodayFailed = failedCount
		}
		if weekCount, err := s.loginLogRepo.CountByResultSince(ctx, true, daysAgo(7)); err == nil {
			loginStats.LoginsWeek = weekCount
		}
	}

	return &DashboardStats{
		Users:  *userStats,
		Logins: *loginStats,
	}, nil
}

// daysAgo 返回N天前的时间（当天0点）
func daysAgo(n int) time.Time {
	now := time.Now()
	start := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
	return start.AddDate(0, 0, -n)
}
