using IWS5.Api.Enum;
using IWS5.Core.DTO.IAdmin.Reports;
using IWS5.Core.Models;
using IWS5.Core.Services.IAdmin;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;

namespace IWS5.AdminApi.Controllers;

/// <summary>
/// Controller for managing admin reports.
/// </summary>
[Authorize(Roles = nameof(UserGroups.PDAdminGroup))]
[Route("admin/[controller]")]
[ApiController]
public class ReportsController(IReportsService reportsService, ILogger<ReportsController> logger) : ControllerBase
{
    /// <summary>
    /// Returns all reports (ID, name, description).
    /// </summary>
    [HttpGet]
    [SwaggerOperation(Summary = "Gets all reports", Description = "Returns all available reports.")]
    [ProducesResponseType(typeof(List<ReportDetailsDTO>), 200)]
    [ProducesResponseType(401)]
    [ProducesResponseType(500)]
    public async Task<IActionResult> GetReports()
    {
        try
        {
            var result = await reportsService.GetReportsAsync();
            return Ok(result);
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Error while fetching reports");
            return StatusCode(500, new { message = "Error fetching reports", error = ex.Message });
        }
    }

    /// <summary>
    /// Returns a single report details including SQL.
    /// </summary>
    [HttpGet("{reportId:int}/details")]
    [SwaggerOperation(Summary = "Get report details", Description = "Fetches details of a specific report.")]
    [ProducesResponseType(typeof(ReportDetailsDTO), 200)]
    [ProducesResponseType(404)]
    public async Task<IActionResult> GetReportDetails(int reportId)
    {
        if (reportId <= 0) return BadRequest("Invalid report ID.");
        var report = await reportsService.GetReportDetailsAsync(reportId);
        if (report == null)
            return NotFound();
        return Ok(report);
    }

    /// <summary>
    /// Returns the result for a given report.
    /// </summary>
    [HttpGet("{reportId:int}/run")]
    [SwaggerOperation(Summary = "Run a report", Description = "Executes the SQL for the report and returns results.")]
    [ProducesResponseType(typeof(RunReportResultDTO), 200)]
    public async Task<IActionResult> GetReportResult(int reportId)
    {
        if (reportId <= 0) return BadRequest("Invalid report ID.");
        var result = await reportsService.RunReportAsync(reportId);
        if (result == null)
            return NotFound();
        return Ok(result);
    }

    /// <summary>
    /// Makes a report the active home page report.
    /// </summary>
    [HttpPatch("{reportId:int}/make-active")]
    [SwaggerOperation(Summary = "Makes a report active", Description = "Makes a report the active home page report and de-actives all other reports.")]
    [ProducesResponseType(typeof(MakeActiveReportResponseDTO), 200)]
    public async Task<IActionResult> SetReportStatus(int reportId)
    {
        if (reportId <= 0) return BadRequest("Invalid report ID.");
        var result = await reportsService.UpdateStatusAsync(reportId);
        return Ok(result);
    }

    /// <summary>
    /// Create a new report.
    /// </summary>
    [HttpPost]
    [SwaggerOperation(Summary = "Creates a new report")]
    [ProducesResponseType(typeof(CodeResponse<ReportDetailsDTO>), 200)]
    [ProducesResponseType(400)]
    public async Task<IActionResult> Create([FromBody] CreateReportRequestDTO request)
    {
        var result = await reportsService.CreateReportAsync(request);
        return Ok(result);
    }

    /// <summary>
    /// Updates an existing report.
    /// </summary>
    [HttpPut("{reportId:int}")]
    [SwaggerOperation(Summary = "Update report", Description = "Updates a report’s name, description and SQL.")]
    [ProducesResponseType(typeof(ReportDetailsDTO), 200)]
    public async Task<IActionResult> UpdateReport(int reportId, [FromBody] UpdateReportRequestDTO request)
    {
        if (reportId <= 0) return BadRequest("Invalid report ID.");
        var updated = await reportsService.UpdateReportAsync(reportId, request);
        return Ok(updated);
    }

    /// <summary>
    /// Deletes a report by ID.
    /// </summary>
    [HttpDelete("{reportId:int}")]
    [SwaggerOperation(Summary = "Delete report")]
    [ProducesResponseType(204)]
    public async Task<IActionResult> DeleteReport(int reportId)
    {
        if (reportId <= 0) return BadRequest("Invalid report ID.");
        await reportsService.DeleteReportAsync(reportId);
        return NoContent();
    }
}
