using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using RacePlannerApi.Data;
using RacePlannerApi.DTOs;
using RacePlannerApi.Models;

namespace RacePlannerApi.Controllers;

[ApiController]
[Route("api/[controller]")]
[Authorize]
public class DashboardController : ControllerBase
{
    private readonly RacePlannerDbContext _context;

    public DashboardController(RacePlannerDbContext context)
    {
        _context = context;
    }

    [HttpGet("organizer")]
    [Authorize(Roles = "Organizer")]
    public async Task<ActionResult<OrganizerDashboardDto>> GetOrganizerDashboard()
    {
        var userId = GetCurrentUserId();
        if (userId == null)
        {
            return Unauthorized();
        }

        var events = await _context.Events
            .Include(e => e.Registrations)
            .ThenInclude(r => r.Payments)
            .Where(e => e.OrganizerId == userId.Value)
            .ToListAsync();

        var totalEvents = events.Count;
        var publishedEvents = events.Count(e => e.Status == EventStatus.Published);
        var draftEvents = events.Count(e => e.Status == EventStatus.Draft);

        var allRegistrations = events.SelectMany(e => e.Registrations).ToList();
        var totalRegistrations = allRegistrations.Count;
        var pendingRegistrations = allRegistrations.Count(r => r.Status == RegistrationStatus.Pending);
        var confirmedRegistrations = allRegistrations.Count(r => r.Status == RegistrationStatus.Confirmed);
        var cancelledRegistrations = allRegistrations.Count(r => r.Status == RegistrationStatus.Cancelled);

        var totalRevenue = allRegistrations
            .SelectMany(r => r.Payments)
            .Sum(p => p.Amount);

        var upcomingEvents = events
            .Where(e => e.EventDate >= DateTime.UtcNow && e.EventDate <= DateTime.UtcNow.AddDays(30))
            .OrderBy(e => e.EventDate)
            .Take(5)
            .Select(e => new EventSummaryDto
            {
                Id = e.Id,
                Name = e.Name,
                EventDate = e.EventDate,
                Location = e.Location,
                RegistrationCount = e.Registrations.Count(r => r.Status != RegistrationStatus.Cancelled),
                MaxParticipants = e.MaxParticipants
            })
            .ToList();

        var eventsNearCapacity = events
            .Where(e => e.MaxParticipants.HasValue && e.Status == EventStatus.Published)
            .Select(e => new EventCapacityDto
            {
                Id = e.Id,
                Name = e.Name,
                EventDate = e.EventDate,
                RegistrationCount = e.Registrations.Count(r => r.Status != RegistrationStatus.Cancelled),
                MaxParticipants = e.MaxParticipants
            })
            .Where(e => e.CapacityPercentage >= 80)
            .OrderByDescending(e => e.CapacityPercentage)
            .Take(5)
            .ToList();

        var dashboard = new OrganizerDashboardDto
        {
            TotalEvents = totalEvents,
            PublishedEvents = publishedEvents,
            DraftEvents = draftEvents,
            TotalRegistrations = totalRegistrations,
            PendingRegistrations = pendingRegistrations,
            ConfirmedRegistrations = confirmedRegistrations,
            CancelledRegistrations = cancelledRegistrations,
            TotalRevenue = totalRevenue,
            UpcomingEvents = upcomingEvents,
            EventsNearCapacity = eventsNearCapacity
        };

        return Ok(dashboard);
    }

    [HttpGet("participant")]
    public async Task<ActionResult<ParticipantDashboardDto>> GetParticipantDashboard()
    {
        var userId = GetCurrentUserId();
        if (userId == null)
        {
            return Unauthorized();
        }

        var registrations = await _context.Registrations
            .Include(r => r.Event)
            .Where(r => r.ParticipantId == userId.Value)
            .ToListAsync();

        var totalRegistrations = registrations.Count;
        var upcomingEvents = registrations.Count(r => r.Event.EventDate >= DateTime.UtcNow && r.Status != RegistrationStatus.Cancelled);
        var completedEvents = registrations.Count(r => r.Event.EventDate < DateTime.UtcNow && r.Status == RegistrationStatus.Completed);
        var cancelledRegistrations = registrations.Count(r => r.Status == RegistrationStatus.Cancelled);

        var registrationSummaries = registrations
            .OrderByDescending(r => r.Event.EventDate)
            .Take(10)
            .Select(r => new RegistrationSummaryDto
            {
                Id = r.Id,
                EventId = r.EventId,
                EventName = r.Event.Name,
                EventDate = r.Event.EventDate,
                Status = r.Status.ToString(),
                RegisteredAt = r.CreatedAt
            })
            .ToList();

        var upcomingEventList = registrations
            .Where(r => r.Event.EventDate >= DateTime.UtcNow && r.Status != RegistrationStatus.Cancelled)
            .OrderBy(r => r.Event.EventDate)
            .Take(5)
            .Select(r => new UpcomingEventDto
            {
                Id = r.EventId,
                Name = r.Event.Name,
                EventDate = r.Event.EventDate,
                Location = r.Event.Location
            })
            .ToList();

        var dashboard = new ParticipantDashboardDto
        {
            TotalRegistrations = totalRegistrations,
            UpcomingEvents = upcomingEvents,
            CompletedEvents = completedEvents,
            CancelledRegistrations = cancelledRegistrations,
            MyRegistrations = registrationSummaries,
            UpcomingEventList = upcomingEventList
        };

        return Ok(dashboard);
    }

    private Guid? GetCurrentUserId()
    {
        var userIdClaim = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
        if (Guid.TryParse(userIdClaim, out var userId))
        {
            return userId;
        }
        return null;
    }
}