using SportsDivision.Application.DTOs;
using SportsDivision.Application.Interfaces;
using SportsDivision.Domain.Enums;
using SportsDivision.Domain.Interfaces;

namespace SportsDivision.Application.Services;

public class DashboardService : IDashboardService
{
    private readonly IUnitOfWork _uow;
    private readonly IScoringService _scoringService;

    public DashboardService(IUnitOfWork uow, IScoringService scoringService)
    {
        _uow = uow;
        _scoringService = scoringService;
    }

    public async Task<DashboardDto> GetDashboardAsync(int? tournamentId = null)
    {
        var dashboard = new DashboardDto
        {
            TotalStudents = await _uow.Students.CountAsync(),
            MaleStudents = await _uow.Students.CountAsync(s => s.Sex == Sex.Male),
            FemaleStudents = await _uow.Students.CountAsync(s => s.Sex == Sex.Female),
            TotalSchools = await _uow.Schools.CountAsync(),
            TotalEvents = await _uow.Events.CountAsync(),
            TotalScores = await _uow.Scores.CountAsync(),
            ActiveTournaments = await _uow.Tournaments.CountAsync(t => t.Status == TournamentStatus.InProgress && !t.IsArchived),
            DraftTournaments = await _uow.Tournaments.CountAsync(t => t.Status == TournamentStatus.Draft && !t.IsArchived),
            RegistrationTournaments = await _uow.Tournaments.CountAsync(t => t.Status == TournamentStatus.Registration && !t.IsArchived),
            CompletedTournaments = await _uow.Tournaments.CountAsync(t => t.Status == TournamentStatus.Completed && !t.IsArchived),
            ArchivedTournaments = await _uow.Tournaments.CountAsync(t => t.IsArchived)
        };

        if (tournamentId.HasValue)
        {
            var tels = (await _uow.TournamentEventLevels.GetByTournamentAsync(tournamentId.Value)).ToList();
            int regCount = 0;
            int scoredEvents = 0;
            var recent = new List<RecentScoreDto>();

            foreach (var tel in tels)
            {
                var regs = await _uow.EventRegistrations.GetByTournamentEventLevelAsync(tel.TournamentEventLevelId);
                regCount += regs.Count();

                bool hasResults = false;
                foreach (var reg in regs.Where(r => r.Score != null))
                {
                    if (reg.Score!.Placement != null) hasResults = true;
                    recent.Add(new RecentScoreDto
                    {
                        StudentName = reg.Student?.FullName ?? "Unknown",
                        EventName = tel.Event?.Name ?? string.Empty,
                        EventLevelName = tel.EventLevel?.Name ?? string.Empty,
                        RawPerformance = reg.Score!.RawPerformance,
                        Placement = reg.Score.Placement,
                        RecordedAt = reg.Score.RecordedAt
                    });
                }
                if (hasResults) scoredEvents++;
            }

            dashboard.TotalRegistrations = regCount;
            dashboard.EventsCompleted = scoredEvents;
            dashboard.EventsInProgress = tels.Count - scoredEvents;
            dashboard.RecentScores = recent.OrderByDescending(r => r.RecordedAt).Take(8).ToList();

            var standings = await _scoringService.GetSchoolStandingsAsync(tournamentId.Value);
            dashboard.TopSchools = standings.Take(10).ToList();
        }

        return dashboard;
    }
}
