using IWS5.Api.Enum;
using IWS5.Core.DTO.IAdmin.Servers;
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 servers.
/// </summary>
[Authorize(Roles = nameof(UserGroups.PDAdminGroup))]
[Route("admin/[controller]")]
[ApiController]
public class ServersController(IServersService serversService, ILogger<ServersController> logger) : ControllerBase
{
    /// <summary>
    /// Returns all servers.
    /// </summary>
    [HttpGet]
    [SwaggerOperation(Summary = "Gets all servers", Description = "Returns all available servers.")]
    [ProducesResponseType(typeof(List<CodeResponse<ServerDetailsDTO>>), 200)]
    [ProducesResponseType(401)]
    [ProducesResponseType(500)]
    public async Task<IActionResult> GetServers()
    {
        try
        {
            var result = await serversService.GetServersAsync();
            return StatusCode((int)result.Code, result);
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Error while fetching servers");
            return StatusCode(500, new { message = "Error fetching servers", error = ex.Message });
        }
    }

    /// <summary>
    /// Returns details about a single server.
    /// </summary>
    /// <returns></returns>
    [HttpGet("{hostName}")]
    [SwaggerOperation(Summary = "Gets a single server", Description = "Returns details about a single server.")]
    [ProducesResponseType(typeof(CodeResponse<ServerDetailsDTO>), 200)]
    [ProducesResponseType(401)]
    [ProducesResponseType(500)]
    public async Task<IActionResult> GetServerDetails(string hostName)
    {
        if (string.IsNullOrEmpty(hostName))
        {
            return BadRequest("Invalid host name.");
        }

        try
        {
            var result = await serversService.GetServerDetailsAsync(hostName);

            if (result == null)
            {
                return NotFound($"Server with host name {hostName} not found.");
            }

            return StatusCode((int)result.Code, result);
        } catch (Exception ex)
        {
            logger.LogError(ex, "Error while fetching server");
            return StatusCode(500, new { message = "Error fetching server", error = ex.Message });
        }
    }

    /// <summary>
    /// Creates a new server.
    /// </summary>
    [HttpPost]
    [SwaggerOperation(Summary = "Create new server", Description = "Creates a new server.")]
    [ProducesResponseType(typeof(CodeResponse<ServerDetailsDTO>), 200)]
    [ProducesResponseType(400)]
    public async Task<IActionResult> CreateServer([FromBody] CreateServerRequestDTO createServerRequest)
    {
        try
        {
            var result = await serversService.CreateServerAsync(createServerRequest);
            return StatusCode((int)result.Code, result);
        } catch (Exception ex)
        {
            logger.LogError(ex, "Error while creating server");
            return StatusCode(500, new { message = "Error creating server", error = ex.Message });
        }
    }

    /// <summary>
    /// Updates an existing server.
    /// </summary>
    [HttpPut("{hostName}")]
    [SwaggerOperation(Summary = "Updates a server", Description = "Updates an existing server.")]
    [ProducesResponseType(typeof(CodeResponse<ServerDetailsDTO>), 200)]
    [ProducesResponseType(401)]
    [ProducesResponseType(500)]
    public async Task<IActionResult> UpdateServer(string hostName, [FromBody] UpdateServerRequestDTO updateServerRequest)
    {
        if (string.IsNullOrEmpty(hostName))
        {
            return BadRequest("Invalid host name.");
        }

        try
        {
            var result = await serversService.UpdateServerAsync(hostName, updateServerRequest);
            return StatusCode((int)result.Code, result);
        } catch (Exception ex)
        {
            logger.LogError(ex, "Error while updating server");
            return StatusCode(500, new { message = "Error updating server", error = ex.Message });
        }
    }

    /// <summary>
    /// Deletes an existing server.
    /// </summary>
    [HttpDelete("{hostName}")]
    [SwaggerOperation(Summary = "Deletes a server", Description = "Deletes an existing server.")]
    [ProducesResponseType(204)]
    [ProducesResponseType(401)]
    [ProducesResponseType(500)]
    public async Task<IActionResult> DeleteServer(string hostName)
    {
        if (string.IsNullOrEmpty(hostName))
        {
            return BadRequest("Invalid host name.");
        }

        try
        {
            var result = await serversService.GetServerDetailsAsync(hostName);
            if (result.ResponseModel == null)
            {
                return NotFound($"Server with host name {hostName} not found.");
            }
            
            await serversService.DeleteServerAsync(hostName);
            return NoContent();
        } catch (Exception ex)
        {
            logger.LogError(ex, "Error while deleting server");
            return StatusCode(500, new { message = "Error deleting server", error = ex.Message });
        }
    }
}
