using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SportsDivision.Application.DTOs;
using SportsDivision.Application.Interfaces;
using SportsDivision.Domain.Enums;
using SportsDivision.Web.Helpers;

namespace SportsDivision.Web.Controllers;

[Authorize]
public class TournamentController : Controller
{
    private readonly ITournamentService _tournamentService;
    private readonly IEventService _eventService;

    public TournamentController(ITournamentService tournamentService, IEventService eventService)
    {
        _tournamentService = tournamentService;
        _eventService = eventService;
    }

    public async Task<IActionResult> Index(TournamentStatus? status, bool showArchived = false, int page = 1, int pageSize = PaginationHelper.PageSize)
    {
        var all = await _tournamentService.GetAllAsync(includeArchived: true);
        var archivedCount = all.Count(t => t.IsArchived);

        var tournaments = showArchived ? all : all.Where(t => !t.IsArchived);

        if (status.HasValue)
        {
            tournaments = tournaments.Where(t => t.Status == status.Value);
        }

        ViewBag.SelectedStatus = status;
        ViewBag.ShowArchived = showArchived;
        ViewBag.ArchivedCount = archivedCount;

        return View(this.Page(tournaments, page, pageSize));
    }

    public async Task<IActionResult> Details(int id)
    {
        try
        {
            var tournament = await _tournamentService.GetByIdAsync(id);
            if (tournament == null)
            {
                return NotFound();
            }

            var eventLevels = await _tournamentService.GetEventLevelsAsync(id);
            ViewBag.EventLevels = eventLevels;
            ViewBag.Events = await _eventService.GetAllAsync();
            ViewBag.Levels = await _tournamentService.GetAllEventLevelsAsync();

            return View(tournament);
        }
        catch (KeyNotFoundException)
        {
            return NotFound();
        }
    }

    [HttpGet]
    public IActionResult Create()
    {
        return View(new TournamentCreateDto());
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create(TournamentCreateDto dto)
    {
        if (!ModelState.IsValid)
        {
            return View(dto);
        }

        try
        {
            var tournament = await _tournamentService.CreateAsync(dto);
            TempData["SuccessMessage"] = "Tournament created successfully.";
            return RedirectToAction(nameof(Details), new { id = tournament.TournamentId });
        }
        catch (InvalidOperationException ex)
        {
            TempData["ErrorMessage"] = ex.Message;
            return View(dto);
        }
    }

    [HttpGet]
    public async Task<IActionResult> Edit(int id)
    {
        try
        {
            var tournament = await _tournamentService.GetByIdAsync(id);
            if (tournament == null)
            {
                return NotFound();
            }

            var dto = new TournamentUpdateDto
            {
                TournamentId = tournament.TournamentId,
                Name = tournament.Name,
                StartDate = tournament.StartDate,
                EndDate = tournament.EndDate,
                ZoneId = tournament.ZoneId,
                SchoolLevel = tournament.SchoolLevel
            };

            return View(dto);
        }
        catch (KeyNotFoundException)
        {
            return NotFound();
        }
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Edit(TournamentUpdateDto dto)
    {
        if (!ModelState.IsValid)
        {
            return View(dto);
        }

        try
        {
            await _tournamentService.UpdateAsync(dto);
            TempData["SuccessMessage"] = "Tournament updated successfully.";
            return RedirectToAction(nameof(Details), new { id = dto.TournamentId });
        }
        catch (KeyNotFoundException)
        {
            return NotFound();
        }
        catch (InvalidOperationException ex)
        {
            TempData["ErrorMessage"] = ex.Message;
            return View(dto);
        }
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Delete(int id)
    {
        try
        {
            await _tournamentService.DeleteAsync(id);
            TempData["SuccessMessage"] = "Tournament deleted successfully.";
        }
        catch (KeyNotFoundException)
        {
            return NotFound();
        }
        catch (InvalidOperationException ex)
        {
            TempData["ErrorMessage"] = ex.Message;
        }

        return RedirectToAction(nameof(Index));
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> AddEventLevel(TournamentEventLevelCreateDto dto)
    {
        try
        {
            await _tournamentService.AddEventLevelAsync(dto);
            TempData["SuccessMessage"] = "Event level added to tournament successfully.";
        }
        catch (KeyNotFoundException)
        {
            return NotFound();
        }
        catch (InvalidOperationException ex)
        {
            TempData["ErrorMessage"] = ex.Message;
        }

        return RedirectToAction(nameof(Details), new { id = dto.TournamentId });
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> RemoveEventLevel(int tournamentEventLevelId, int id)
    {
        try
        {
            await _tournamentService.RemoveEventLevelAsync(tournamentEventLevelId);
            TempData["SuccessMessage"] = "Event level removed from tournament successfully.";
        }
        catch (KeyNotFoundException)
        {
            return NotFound();
        }
        catch (InvalidOperationException ex)
        {
            TempData["ErrorMessage"] = ex.Message;
        }

        return RedirectToAction(nameof(Details), new { id });
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> UpdateStatus(int id, TournamentStatus status)
    {
        try
        {
            await _tournamentService.UpdateStatusAsync(id, status);
            TempData["SuccessMessage"] = $"Tournament status updated to {status}.";
        }
        catch (KeyNotFoundException)
        {
            return NotFound();
        }
        catch (InvalidOperationException ex)
        {
            TempData["ErrorMessage"] = ex.Message;
        }

        return RedirectToAction(nameof(Details), new { id });
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Archive(int id)
    {
        try
        {
            await _tournamentService.ArchiveAsync(id);
            TempData["SuccessMessage"] = "Tournament archived successfully.";
        }
        catch (KeyNotFoundException)
        {
            return NotFound();
        }
        catch (InvalidOperationException ex)
        {
            TempData["ErrorMessage"] = ex.Message;
        }

        return RedirectToAction(nameof(Index));
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Unarchive(int id)
    {
        try
        {
            await _tournamentService.UnarchiveAsync(id);
            TempData["SuccessMessage"] = "Tournament unarchived successfully.";
        }
        catch (KeyNotFoundException)
        {
            return NotFound();
        }
        catch (InvalidOperationException ex)
        {
            TempData["ErrorMessage"] = ex.Message;
        }

        return RedirectToAction(nameof(Index));
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> ToggleAgeWaiver(int tournamentEventLevelId, int id)
    {
        try
        {
            await _tournamentService.ToggleAgeWaiverAsync(tournamentEventLevelId);
            TempData["SuccessMessage"] = "Age waiver toggled successfully.";
        }
        catch (KeyNotFoundException)
        {
            return NotFound();
        }
        catch (InvalidOperationException ex)
        {
            TempData["ErrorMessage"] = ex.Message;
        }

        return RedirectToAction(nameof(Details), new { id });
    }
}
