using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using QuestPDF.Fluent;
using SportsDivision.Application.Interfaces;
using SportsDivision.Web.Reports;

namespace SportsDivision.Web.Controllers;

[Authorize]
public class ReportController : Controller
{
    private readonly IReportService _reportService;
    private readonly ITournamentService _tournamentService;
    private readonly IScoringService _scoringService;

    public ReportController(
        IReportService reportService,
        ITournamentService tournamentService,
        IScoringService scoringService)
    {
        _reportService = reportService;
        _tournamentService = tournamentService;
        _scoringService = scoringService;
    }

    [HttpGet]
    public async Task<IActionResult> Index()
    {
        var tournaments = await _tournamentService.GetAllAsync();
        ViewBag.Tournaments = tournaments;
        return View(tournaments);
    }

    [HttpGet]
    public async Task<IActionResult> PopularEvents(int tournamentId)
    {
        var report = await _reportService.GetPopularEventsAsync(tournamentId);
        ViewBag.TournamentId = tournamentId;
        return View(report);
    }

    [HttpGet]
    public async Task<IActionResult> RegistrationByGender(int tournamentId, int? zoneId)
    {
        var report = await _reportService.GetRegistrationByGenderAsync(tournamentId, zoneId);
        ViewBag.TournamentId = tournamentId;
        ViewBag.ZoneId = zoneId;
        return View(report);
    }

    [HttpGet]
    public async Task<IActionResult> EventSchoolReport(int tournamentId, int? eventId, int? eventLevelId)
    {
        var report = await _reportService.GetEventSchoolReportAsync(tournamentId, eventId, eventLevelId);
        ViewBag.TournamentId = tournamentId;
        ViewBag.EventId = eventId;
        ViewBag.EventLevelId = eventLevelId;
        return View(report);
    }

    [HttpGet]
    public async Task<IActionResult> StudentsBySchool(int tournamentId, int? schoolId, int? zoneId)
    {
        var report = await _reportService.GetStudentsBySchoolAsync(tournamentId, schoolId, zoneId);
        ViewBag.TournamentId = tournamentId;
        ViewBag.SchoolId = schoolId;
        ViewBag.ZoneId = zoneId;
        return View(report);
    }

    [HttpGet]
    public async Task<IActionResult> ScoresByEvent(int tournamentId, int? eventId, int? eventLevelId)
    {
        var report = await _reportService.GetScoresByEventAsync(tournamentId, eventId, eventLevelId);
        ViewBag.TournamentId = tournamentId;
        ViewBag.EventId = eventId;
        ViewBag.EventLevelId = eventLevelId;
        return View(report);
    }

    [HttpGet]
    public async Task<IActionResult> StudentPoints(int tournamentId, int? schoolId, int? zoneId)
    {
        var report = await _reportService.GetStudentPointsAsync(tournamentId, schoolId, zoneId);
        ViewBag.TournamentId = tournamentId;
        ViewBag.SchoolId = schoolId;
        ViewBag.ZoneId = zoneId;
        return View(report);
    }

    [HttpGet]
    public async Task<IActionResult> SchoolStandings(int tournamentId)
    {
        var standings = await _scoringService.GetSchoolStandingsAsync(tournamentId);
        ViewBag.TournamentId = tournamentId;
        return View(standings);
    }

    [HttpGet]
    public async Task<IActionResult> PopularEventsPdf(int tournamentId)
    {
        var report = await _reportService.GetPopularEventsAsync(tournamentId);
        var tournament = await _tournamentService.GetByIdAsync(tournamentId);
        var document = new PopularEventsDocument(report, tournament?.Name ?? "Tournament");
        var pdf = document.GeneratePdf();
        return File(pdf, "application/pdf", $"PopularEvents_{tournamentId}.pdf");
    }

    [HttpGet]
    public async Task<IActionResult> RegistrationByGenderPdf(int tournamentId, int? zoneId)
    {
        var report = await _reportService.GetRegistrationByGenderAsync(tournamentId, zoneId);
        var tournament = await _tournamentService.GetByIdAsync(tournamentId);
        var document = new RegistrationByGenderDocument(report, tournament?.Name ?? "Tournament");
        var pdf = document.GeneratePdf();
        return File(pdf, "application/pdf", $"RegistrationByGender_{tournamentId}.pdf");
    }

    [HttpGet]
    public async Task<IActionResult> EventSchoolReportPdf(int tournamentId, int? eventId, int? eventLevelId)
    {
        var report = await _reportService.GetEventSchoolReportAsync(tournamentId, eventId, eventLevelId);
        var tournament = await _tournamentService.GetByIdAsync(tournamentId);
        var document = new EventSchoolDocument(report, tournament?.Name ?? "Tournament");
        var pdf = document.GeneratePdf();
        return File(pdf, "application/pdf", $"EventSchoolReport_{tournamentId}.pdf");
    }

    [HttpGet]
    public async Task<IActionResult> StudentsBySchoolPdf(int tournamentId, int? schoolId, int? zoneId)
    {
        var report = await _reportService.GetStudentsBySchoolAsync(tournamentId, schoolId, zoneId);
        var tournament = await _tournamentService.GetByIdAsync(tournamentId);
        var document = new StudentsBySchoolDocument(report, tournament?.Name ?? "Tournament");
        var pdf = document.GeneratePdf();
        return File(pdf, "application/pdf", $"StudentsBySchool_{tournamentId}.pdf");
    }

    [HttpGet]
    public async Task<IActionResult> ScoresByEventPdf(int tournamentId, int? eventId, int? eventLevelId)
    {
        var report = await _reportService.GetScoresByEventAsync(tournamentId, eventId, eventLevelId);
        var tournament = await _tournamentService.GetByIdAsync(tournamentId);
        var document = new ScoresByEventDocument(report, tournament?.Name ?? "Tournament");
        var pdf = document.GeneratePdf();
        return File(pdf, "application/pdf", $"ScoresByEvent_{tournamentId}.pdf");
    }

    [HttpGet]
    public async Task<IActionResult> StudentPointsPdf(int tournamentId, int? schoolId, int? zoneId)
    {
        var report = await _reportService.GetStudentPointsAsync(tournamentId, schoolId, zoneId);
        var tournament = await _tournamentService.GetByIdAsync(tournamentId);
        var document = new StudentPointsDocument(report, tournament?.Name ?? "Tournament");
        var pdf = document.GeneratePdf();
        return File(pdf, "application/pdf", $"StudentPoints_{tournamentId}.pdf");
    }

    // ----- Excel (.xlsx) exports -----

    private async Task<string> TournamentNameAsync(int tournamentId)
        => (await _tournamentService.GetByIdAsync(tournamentId))?.Name ?? "Tournament";

    [HttpGet]
    public async Task<IActionResult> PopularEventsExcel(int tournamentId)
    {
        var report = await _reportService.GetPopularEventsAsync(tournamentId);
        var bytes = ReportExcelExporter.PopularEvents(report, await TournamentNameAsync(tournamentId));
        return File(bytes, ReportExcelExporter.MimeType, $"PopularEvents_{tournamentId}.xlsx");
    }

    [HttpGet]
    public async Task<IActionResult> RegistrationByGenderExcel(int tournamentId, int? zoneId)
    {
        var report = await _reportService.GetRegistrationByGenderAsync(tournamentId, zoneId);
        var bytes = ReportExcelExporter.RegistrationByGender(report, await TournamentNameAsync(tournamentId));
        return File(bytes, ReportExcelExporter.MimeType, $"RegistrationByGender_{tournamentId}.xlsx");
    }

    [HttpGet]
    public async Task<IActionResult> EventSchoolReportExcel(int tournamentId, int? eventId, int? eventLevelId)
    {
        var report = await _reportService.GetEventSchoolReportAsync(tournamentId, eventId, eventLevelId);
        var bytes = ReportExcelExporter.EventSchoolReport(report, await TournamentNameAsync(tournamentId));
        return File(bytes, ReportExcelExporter.MimeType, $"EventSchoolReport_{tournamentId}.xlsx");
    }

    [HttpGet]
    public async Task<IActionResult> StudentsBySchoolExcel(int tournamentId, int? schoolId, int? zoneId)
    {
        var report = await _reportService.GetStudentsBySchoolAsync(tournamentId, schoolId, zoneId);
        var bytes = ReportExcelExporter.StudentsBySchool(report, await TournamentNameAsync(tournamentId));
        return File(bytes, ReportExcelExporter.MimeType, $"StudentsBySchool_{tournamentId}.xlsx");
    }

    [HttpGet]
    public async Task<IActionResult> ScoresByEventExcel(int tournamentId, int? eventId, int? eventLevelId)
    {
        var report = await _reportService.GetScoresByEventAsync(tournamentId, eventId, eventLevelId);
        var bytes = ReportExcelExporter.ScoresByEvent(report, await TournamentNameAsync(tournamentId));
        return File(bytes, ReportExcelExporter.MimeType, $"ScoresByEvent_{tournamentId}.xlsx");
    }

    [HttpGet]
    public async Task<IActionResult> StudentPointsExcel(int tournamentId, int? schoolId, int? zoneId)
    {
        var report = await _reportService.GetStudentPointsAsync(tournamentId, schoolId, zoneId);
        var bytes = ReportExcelExporter.StudentPoints(report, await TournamentNameAsync(tournamentId));
        return File(bytes, ReportExcelExporter.MimeType, $"StudentPoints_{tournamentId}.xlsx");
    }

    [HttpGet]
    public async Task<IActionResult> SchoolStandingsExcel(int tournamentId)
    {
        var standings = await _scoringService.GetSchoolStandingsAsync(tournamentId);
        var bytes = ReportExcelExporter.SchoolStandings(standings, await TournamentNameAsync(tournamentId));
        return File(bytes, ReportExcelExporter.MimeType, $"SchoolStandings_{tournamentId}.xlsx");
    }
}
