using Asp.Versioning;
using Core.Cerberos.Adapters;
using Core.Cerberos.Adapters.Attributes;
using Core.Cerberos.Adapters.Common.Constants;
using Core.Cerberos.Application.UseCases.Modules.Input;
using Core.Cerberos.Application.UseCases.Modules.Ports;
using Lib.Architecture.BuildingBlocks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Core.Cerberos.Service.API.Controllers
{
    /// 
    /// Handles all services and business rules related to .
    /// 
    [ApiVersion("1.0")]
    [Route("api/v{api-version:apiVersion}/[controller]")]
    [Produces("application/json")]
    [ApiController]
    public class ModuleController : ControllerBase
    {
        private readonly IComponentHandler getModuleHandler;
        private readonly IComponentHandler getAllModulesHandler;
        private readonly IComponentHandler getAllModulesByListHandler;
        private readonly IComponentHandler createModuleHandler;
        private readonly IComponentHandler updateModuleHandler;
        private readonly IComponentHandler changeModuleStatusHandler;
        private readonly IModulePort port;
        /// 
        /// Handles all services and business rules related to .
        /// 
        public ModuleController(
            IComponentHandler getModuleHandler,
            IComponentHandler getAllModulesHandler,
            IComponentHandler getAllModulesByListHandler,
            IComponentHandler createModuleHandler,
            IComponentHandler updateModuleHandler,
            IComponentHandler changeModuleStatusHandler,
            IModulePort port
            )
        {
            this.createModuleHandler = createModuleHandler;
            this.updateModuleHandler = updateModuleHandler;
            this.changeModuleStatusHandler = changeModuleStatusHandler;
            this.getAllModulesHandler = getAllModulesHandler;
            this.getModuleHandler = getModuleHandler;
            this.getAllModulesByListHandler = getAllModulesByListHandler;
            this.port = port;
        }
        /// 
        /// Gets all the modules.
        /// 
        [HttpGet("GetAll")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [ProducesResponseType(StatusCodes.Status401Unauthorized)]
        [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)]
        [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)]
        [ProducesResponseType(StatusCodes.Status500InternalServerError)]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [Authorize(AuthenticationSchemes = Schemes.HeathScheme)]
        [Permission("ModuleManagement.Read, RoleManagement.Read")]
        public async Task GetAllModulesAsync(CancellationToken cancellationToken)
        {
            await getAllModulesHandler.ExecuteAsync(new GetAllModulesRequest { }, cancellationToken).ConfigureAwait(false);
            return port.ViewModel;
        }
        /// 
        /// Gets all the modules by module identifiers.
        /// 
        /// The request containing the list of module identifiers.
        /// Cancellation token for the asynchronous operation.
        /// The  representing the result of the service call.
        /// The modules found.
        /// No content if no modules are found.
        /// Bad request if the module identifiers are missing or invalid.
        /// Unauthorized if the user is not authenticated.
        /// Precondition failed if the request does not meet expected conditions.
        /// Unprocessable entity if the request cannot be processed.
        /// Internal server error if an unexpected error occurs.
        [HttpPost]
        [Route(Routes.GetModuleList)]
        [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [ProducesResponseType(StatusCodes.Status401Unauthorized)]
        [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)]
        [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)]
        [ProducesResponseType(StatusCodes.Status500InternalServerError)]
        [Authorize(AuthenticationSchemes = Schemes.HeathScheme)]
        [Permission("ModuleManagement.Read")]
        public async Task GetAllModulesByListAsync([FromBody] GetAllModulesByListRequest request, CancellationToken cancellationToken)
        {
            if (request == null || request.Modules == null || !request.Modules.Any())
            {
                return BadRequest("Module identifiers are required.");
            }
            await getAllModulesByListHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false);
            return port.ViewModel;
        }
        /// 
        /// Gets the module by identifier.
        /// 
        [HttpPost]
        [Route("GetById")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [ProducesResponseType(StatusCodes.Status401Unauthorized)]
        [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)]
        [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)]
        [ProducesResponseType(StatusCodes.Status500InternalServerError)]
        [Authorize(AuthenticationSchemes = Schemes.HeathScheme)]
        [Permission("ModuleManagement.Read")]
        public async Task GetModuleById([FromBody] GetModuleRequest request, CancellationToken cancellationToken)
        {
            if (request.Id == null || !request.Id.Any())
            {
                return BadRequest("Invalid Module Id");
            }
            await getModuleHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false);
            return port.ViewModel;
        }
        /// 
        /// Creates a new module.
        /// 
        [HttpPost("Create")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [ProducesResponseType(StatusCodes.Status401Unauthorized)]
        [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)]
        [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)]
        [ProducesResponseType(StatusCodes.Status500InternalServerError)]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [Authorize(AuthenticationSchemes = Schemes.HeathScheme)]
        [Permission("ModuleManagement.Write")]
        public async Task CreateModuleAsync([FromBody] CreateModuleRequest newModule, CancellationToken cancellationToken = default)
        {
            await createModuleHandler.ExecuteAsync(newModule, cancellationToken).ConfigureAwait(false);
            return port.ViewModel;
        }
        /// 
        /// Updates a full module by identifier.
        /// 
        [HttpPut("Update")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [ProducesResponseType(StatusCodes.Status401Unauthorized)]
        [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)]
        [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)]
        [ProducesResponseType(StatusCodes.Status500InternalServerError)]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [Authorize(AuthenticationSchemes = Schemes.HeathScheme)]
        [Permission("ModuleManagement.Write")]
        public async Task UpdateModuleAsync([FromBody] UpdateModuleRequest request, CancellationToken cancellationToken = default)
        {
            await updateModuleHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false);
            return port.ViewModel;
        }
        /// 
        /// Changes the status of the module.
        /// 
        [HttpPatch]
        [Route("ChangeStatus")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [ProducesResponseType(StatusCodes.Status401Unauthorized)]
        [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)]
        [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)]
        [ProducesResponseType(StatusCodes.Status500InternalServerError)]
        [Authorize(AuthenticationSchemes = Schemes.HeathScheme)]
        [Permission("ModuleManagement.Write")]
        public async Task ChangeModuleStatusAsync([FromBody] ChangeModuleStatusRequest request,
                                                                     CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(request.Id)) { return BadRequest("Invalid module identifier"); }
            await changeModuleStatusHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false);
            return port.ViewModel;
        }
    }
}