using IWS5.Api.Enum;
using IWS5.Core.DTO.IAdmin.Schedules;
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;

[Authorize(Roles = nameof(UserGroups.PDAdminGroup))]
[Route("admin/[controller]")]
[ApiController]
public class SchedulesController(
    ISchedulesService schedulesService,
    ILogger<SchedulesController> logger)
    : ControllerBase
{
    /// <summary>
    /// Returns all schedules.
    /// </summary>
    [HttpGet]
    [SwaggerOperation(Summary = "List schedules", Description = "Returns all schedules.")]
    [ProducesResponseType(typeof(CodeResponse<List<ScheduleListItemDTO>>), 200)]
    public async Task<IActionResult> GetAllSchedules()
    {
        var result = await schedulesService.GetSchedulesAsync();
        return Ok(result);
    }

    /// <summary>
    /// Returns details about a single schedule.
    /// </summary>
    [HttpGet("{scheduleId:int}")]
    [SwaggerOperation(Summary = "Get schedule details", Description = "Returns details about a single schedule.")]
    [ProducesResponseType(typeof(CodeResponse<ScheduleDetailsDTO>), 200)]
    [ProducesResponseType(404)]
    public async Task<IActionResult> GetSchedule([FromRoute] ScheduleRouteDTO route)
    {
        var result = await schedulesService.GetScheduleDetailsAsync(route.ScheduleId);

        return result.Code == IWS5.Core.Enums.ResponseCode.NotFound
            ? NotFound(result)
            : Ok(result);
    }

    /// <summary>
    /// Creates a new schedule.
    /// </summary>
    [HttpPost]
    [SwaggerOperation(Summary = "Create schedule", Description = "Creates a new schedule.")]
    [ProducesResponseType(typeof(CodeResponse<ScheduleDetailsDTO>), 200)]
    [ProducesResponseType(400)]
    public async Task<IActionResult> CreateSchedule([FromBody] ScheduleCreateRequestDTO request)
    {
        if (!ModelState.IsValid)
            return BadRequest(ModelState);

        var result = await schedulesService.CreateScheduleAsync(request);
        return Ok(result);
    }

    /// <summary>
    /// Updates an existing schedule.
    /// </summary>
    [HttpPut("{scheduleId:int}")]
    [SwaggerOperation(Summary = "Update schedule", Description = "Updates an existing schedule.")]
    [ProducesResponseType(typeof(CodeResponse<ScheduleDetailsDTO>), 200)]
    [ProducesResponseType(400)]
    [ProducesResponseType(404)]
    public async Task<IActionResult> UpdateSchedule(
        [FromRoute] ScheduleRouteDTO route,
        [FromBody] ScheduleUpdateRequestDTO request)
    {
        if (!ModelState.IsValid)
            return BadRequest(ModelState);

        var result = await schedulesService.UpdateScheduleAsync(route.ScheduleId, request);

        return result.Code == IWS5.Core.Enums.ResponseCode.NotFound
            ? NotFound(result)
            : Ok(result);
    }

    /// <summary>
    /// Deletes a schedule by ID.
    /// </summary>
    [HttpDelete("{scheduleId:int}")]
    [SwaggerOperation(Summary = "Delete schedule", Description = "Deletes a schedule by ID.")]
    [ProducesResponseType(204)]
    [ProducesResponseType(404)]
    public async Task<IActionResult> DeleteSchedule([FromRoute] ScheduleRouteDTO route)
    {
        var deleted = await schedulesService.DeleteScheduleAsync(route.ScheduleId);
        return deleted ? NoContent() : NotFound(new { message = "Schedule not found." });
    }

    /// <summary>
    /// Updates an existing schedule's status.
    /// </summary>
    [HttpPatch("{scheduleId:int}/status")]
    [SwaggerOperation(Summary = "Update schedule status/enabled", Description = "Updates an existing schedule's status.")]
    [ProducesResponseType(200)]
    [ProducesResponseType(404)]
    public async Task<IActionResult> UpdateScheduleStatus(
        [FromRoute] ScheduleRouteDTO route,
        [FromQuery] ScheduleStatusUpdateQueryDTO query)
    {
        var updated = await schedulesService.UpdateStatusAsync(route.ScheduleId, query.Enabled, query.StatusId);

        return updated
            ? Ok(new { success = true })
            : NotFound(new { success = false, message = "Schedule not found." });
    }

    /// <summary>
    /// Triggers a schedule to run.
    /// </summary>
    [HttpPost("{scheduleId:int}/run")]
    [SwaggerOperation(Summary = "Run schedule manually", Description = "Triggers a schedule to run.")]
    [ProducesResponseType(200)]
    [ProducesResponseType(404)]
    public async Task<IActionResult> RunSchedule([FromRoute] ScheduleRouteDTO route)
    {
        var triggered = await schedulesService.RunScheduleAsync(route.ScheduleId);

        return triggered
            ? Ok(new { success = true, message = $"Schedule {route.ScheduleId} triggered successfully." })
            : NotFound(new { success = false, message = $"Schedule {route.ScheduleId} not found (or cannot be triggered)." });
    }

    /// <summary>
    /// Lists the schedule types.
    /// </summary>
    [HttpGet("types")]
    [SwaggerOperation(Summary = "List schedule types", Description = "Lists the schedule types.")]
    public async Task<IActionResult> ListScheduleTypes()
    {
        var result = await schedulesService.ListScheduleTypesAsync();
        return Ok(result);
    }

    /// <summary>
    /// Gets details about a schedule type by ID.
    /// </summary>
    [HttpGet("types/{scheduleTypeId:int}")]
    [SwaggerOperation(Summary = "Get schedule type by id", Description = "Gets details about a schedule type by ID.")]
    public async Task<IActionResult> GetScheduleType(int scheduleTypeId)
    {
        var result = await schedulesService.GetScheduleTypeByIdAsync(scheduleTypeId);
        return result == null ? NotFound() : Ok(result);
    }
}
