using adas_core.Application.Exceptions;
using adas_core.Application.Services.Interfaces;
using adas_core.Authentication.Attributes;
using adas_core.Domain.Enums;
using adas_core.Domain.Models.DTO.Display;
using adas_core.Domain.Models.Filter;
using adas_core.Domain.Models.GroupedObservations;
using adas_core.Domain.Models.MongoModels;
using adas_core.Domain.Utils;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MongoDB.Bson;
using Newtonsoft.Json;

namespace adas_core.Controllers;

/// <summary>
///     Provides endpoints for managing and retrieving display configuration data.
/// </summary>
/// <param name="displayConfigService">The service used to handle display configuration operations.</param>
/// <returns>
///     A new instance of <see cref="ConfigDisplayController"/>.
/// </returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="displayConfigService"/> is <see langword="null"/>.</exception>
[Route("config-displays")]
[ApiController]
public class ConfigDisplayController(
    IDisplayConfigService displayConfigService)
    : ControllerBase
{

    /// <summary>
    ///     GetByCodeSysAndCode all display config list
    /// </summary>
    /// <returns>
    ///     List<DisplayConfig />
    /// </returns>
    [HttpGet]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> List()
    {
        return Ok(await displayConfigService.GetAll());
    }

    /// <summary>
    ///     GetByCodeSysAndCode all display config compact paginated
    /// </summary>
    /// <returns>
    ///     List<DisplayConfig />
    /// </returns>
    [HttpPost("paginated")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> ListCompactPaginated([FromBody] PaginationFilter request)
    {
        return Ok(await displayConfigService.GetAllCompactPaginated(request));
    }

    /// <summary>
    ///     GetByCodeSysAndCode all display config compact
    /// </summary>
    /// <returns>
    ///     List<DisplayConfig />
    /// </returns>
    [HttpGet("compact")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    public async Task<IActionResult> ListCompact()
    {
        return Ok(await displayConfigService.GetAllCompact());
    }

    /// <summary>
    ///     GetByCodeSysAndCode all display config list by type
    /// </summary>
    /// <returns>
    ///     List<DisplayConfig />
    /// </returns>
    [HttpGet("{type}/type")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> ListByType(DisplayConfigEnums.DisplayType type)
    {
        return Ok(await displayConfigService.GetByType(type));
    }

    /// <summary>
    ///     GetByCodeSysAndCode display config by it object id
    /// </summary>
    /// <returns>
    ///     displayConfig
    /// </returns>
    [HttpGet("{id}")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> ListById(string id)
    {
        if (!ObjectId.TryParse(id, out var objectId))
            throw new InvalidFormatException(HttpEnum.ErrorMessage.BadRequestInvalidFormat);
        var result = await displayConfigService.GetById(objectId);
        return Ok(result);
    }

    /// <summary>
    /// Inserts a new display configuration by delegating to the display configuration service and returns the created result.
    /// </summary>
    /// <param name="config">The display configuration to insert, supplied in the request body.</param>
    /// <returns>An <see cref="IActionResult"/> containing the inserted display configuration wrapped in an HTTP 200 OK response.</returns>
    [HttpPost]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> Insert([FromBody] DisplayConfig config)
    {
        var result = await displayConfigService.InsertOne(config);
        return Ok(result);
    }

    /// <summary>
    /// Inserts a minimal display configuration. If a display config ID template is provided, the configuration is inserted using the template along with the specified type and hospital; otherwise, it is inserted using the minimal fields from the supplied DTO.
    /// </summary>
    /// <param name="config">The display configuration payload received in the request body, which may optionally include a display config ID template.</param>
    /// <returns>An <see cref="IActionResult"/> containing the result of the insertion operation.</returns>
    [HttpPost("compact")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> InsertMinimal([FromBody] CreateDisplayConfigDto config)
    {
        var result = config.DisplayConfigIdTemplate != null
            ? await displayConfigService.InsertOneWithTemplate(config.DisplayConfigIdTemplate, config.Type,
                config.Hospital)
            : await displayConfigService.InsertOneMinimal(config);
        return Ok(result);
    }

    /// <summary>
    /// Handles a GET request to the "insertion-test" endpoint, performing a test insertion via the display configuration service. Requires the caller to have the <see cref="PermissionEnum.RolesType.AuthSome"/> role and the "Source.DisplayId" permission.
    /// </summary>
    /// <returns>An <see cref="IActionResult"/> containing the result of the test insertion wrapped in an HTTP 200 OK response.</returns>
    [HttpGet("insertion-test")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> InsertNurse()
    {
        var result = await displayConfigService.InsertOneTest();
        return Ok(result);
    }

    /// <summary>
    ///     Update display Config and notify subscribers
    /// </summary>
    /// <returns>
    ///     display
    /// </returns>
    [HttpPut("{id}")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> UpdateConfig(string id, [FromBody] object newDisplayConfig)
    {
        if (!ObjectId.TryParse(id, out var objectId))
            throw new InvalidFormatException(HttpEnum.ErrorMessage.BadRequestInvalidFormat);

        var result = await displayConfigService.UpdateConfig(objectId, newDisplayConfig);
        return Ok(result);
    }

    /// <summary>
    /// Updates the color configuration for the specified display configuration identifier.
    /// Requires the AuthSome role and the "DisplayId" source permission, and validates the identifier format before delegating the update to the display configuration service.
    /// </summary>
    /// <param name="idConfig">The display configuration identifier; must be a valid ObjectId.</param>
    /// <param name="colorConfig">The new color configuration to apply.</param>
    /// <returns>An <see cref="IActionResult"/> containing the update result on success, or a not-modified status when the update produces no changes.</returns>
    /// <exception cref="InvalidFormatException">Thrown when <paramref name="idConfig"/> is not a valid ObjectId format.</exception>
    [HttpPut("{idConfig}/color-config")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> UpdateConfigColor(string idConfig, ColorConfig colorConfig)
    {
        if (!ObjectId.TryParse(idConfig, out var objectIdConfigDisplay))
            throw new InvalidFormatException(HttpEnum.ErrorMessage.BadRequestInvalidFormat);
        var result = await displayConfigService.UpdateConfigColor(objectIdConfigDisplay, colorConfig);

        return result ? Ok(result) : Ok((int)HttpEnum.ErrorMessage.OkResouceNotModified);
    }

    /// <summary>
    /// Updates the header configuration associated with the specified display configuration identifier.
    /// Validates the identifier format and applies the new header configuration, returning the result of the operation or a not-modified response when no changes were applied.
    /// </summary>
    /// <param name="idConfig">The display configuration identifier expected in a valid ObjectId format.</param>
    /// <param name="headerConfig">The header configuration payload to be applied to the display configuration.</param>
    /// <returns>An <see cref="IActionResult"/> containing the update result on success, or a response indicating that the resource was not modified when no changes were made.</returns>
    /// <exception cref="InvalidFormatException">Thrown when <paramref name="idConfig"/> cannot be parsed as a valid ObjectId.</exception>
    [HttpPut("{idConfig}/header-config")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> UpdateHeaderConfig(string idConfig, HeaderConfig headerConfig)
    {
        if (!ObjectId.TryParse(idConfig, out var objectIdConfigDisplay))
            throw new InvalidFormatException(HttpEnum.ErrorMessage.BadRequestInvalidFormat);
        var result = await displayConfigService.UpdateHeaderConfig(objectIdConfigDisplay, headerConfig);

        return result ? Ok(result) : Ok((int)HttpEnum.ErrorMessage.OkResouceNotModified);
    }

    /// <summary>
    /// Updates the home banner configuration for a nurse display configuration identified by the given id.
    /// Validates the id format, ensures the configuration exists, and verifies its type is <see cref="DisplayConfigEnums.DisplayType.DisplayNurse"/> before applying the banner update.
    /// </summary>
    /// <param name="idConfig">The string identifier of the display configuration whose home banner will be updated; must be a valid ObjectId.</param>
    /// <param name="bannerItems">The list of banner items to set as the home banner configuration.</param>
    /// <returns>An <see cref="IActionResult"/> containing the update result on success, or the not-modified status code when no changes are applied.</returns>
    /// <exception cref="InvalidFormatException">Thrown when <paramref name="idConfig"/> is not a valid ObjectId format.</exception>
    /// <exception cref="NotFoundException">Thrown when no display configuration is found for the parsed id.</exception>
    /// <exception cref="BadRequestException">Thrown when the found display configuration is not of type <see cref="DisplayConfigEnums.DisplayType.DisplayNurse"/>.</exception>
    [HttpPut("{idConfig}/home-banner")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> UpdateSetHomeBanner(string idConfig, List<BannerItem> bannerItems)
    {
        if (!ObjectId.TryParse(idConfig, out var objectIdConfigDisplay))
            throw new InvalidFormatException(HttpEnum.ErrorMessage.BadRequestInvalidFormat);
        var displayConfig = await displayConfigService.GetById(objectIdConfigDisplay) ??
                            throw new NotFoundException(HttpEnum.ErrorMessage.NotFoundResourceMissing);
        if (displayConfig.Type != DisplayConfigEnums.DisplayType.DisplayNurse)
            throw new BadRequestException(HttpEnum.ErrorMessage.BadRequestIncorrectType);
        var result = await displayConfigService.UpdateSetHomeBanner(objectIdConfigDisplay, bannerItems);
        return result ? Ok(result) : Ok((int)HttpEnum.ErrorMessage.OkResouceNotModified);
    }

    /// <summary>
    /// Updates the base configuration for a display source.
    /// </summary>
    /// <param name="baseConfig">The display configuration to apply as the base configuration.</param>
    /// <returns>An <see cref="IActionResult"/> containing the update result, or an "OkResouceNotModified" response when no changes were made.</returns>
    [HttpPut("update/base-config")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> UpdateBaseConfig(DisplayConfig baseConfig)
    {
        var result = await displayConfigService.UpdateBaseConfig(baseConfig);
        return result ? Ok(result) : Ok(HttpEnum.ErrorMessage.OkResouceNotModified);
    }

    /// <summary>
    /// Updates the card configuration for a display based on the provided configuration data.
    /// Returns the updated configuration on success, or a "resource not modified" response if no changes were applied.
    /// </summary>
    /// <param name="baseConfig">The card configuration data to be updated.</param>
    /// <returns>An <see cref="IActionResult"/> containing the updated configuration or a not-modified response.</returns>
    [HttpPut("update/card-config")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> UpdateCardConfig(CardConfig baseConfig)
    {
        var result = await displayConfigService.UpdateCardConfig(baseConfig);
        return result ? Ok(result) : Ok(HttpEnum.ErrorMessage.OkResouceNotModified);
    }

    /// <summary>
    /// Updates the card detail configuration by delegating to the display configuration service.
    /// Returns the service result on success, or a "resource not modified" response when the update produced no changes.
    /// </summary>
    /// <param name="baseConfig">The card details configuration to be updated.</param>
    /// <returns>An <see cref="IActionResult"/> containing the update result, or a not-modified message if the resource was not changed.</returns>
    [HttpPut("update/detail-config")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> UpdateDetailConfig(CardDetailsConfig baseConfig)
    {
        var result = await displayConfigService.UpdateDetailConfig(baseConfig);
        return result ? Ok(result) : Ok(HttpEnum.ErrorMessage.OkResouceNotModified);
    }

    /// <summary>
    /// Updates the chart configuration for a display based on the provided configuration.
    /// Returns the result of the update operation if successful, or a not-modified response if no changes were applied.
    /// </summary>
    /// <param name="baseConfig">The chart configuration to update.</param>
    /// <returns>An <see cref="IActionResult"/> containing the update result, or an OkResouceNotModified response when the configuration was not changed.</returns>
    [HttpPut("update/chart-config")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> UpdateChartConfig(ChartConfig baseConfig)
    {
        var result = await displayConfigService.UpdateChartConfig(baseConfig);
        return result ? Ok(result) : Ok(HttpEnum.ErrorMessage.OkResouceNotModified);
    }

    /// <summary>
    /// Updates the field list associated with a display configuration identified by its ID.
    /// Validates the configuration ID format before delegating the update to the display configuration service.
    /// </summary>
    /// <param name="idConfig">The string identifier of the display configuration to update.</param>
    /// <param name="fields">The list of fields to be applied to the specified display configuration.</param>
    /// <returns>An <see cref="IActionResult"/> containing the result of the update operation.</returns>
    /// <exception cref="InvalidFormatException">Thrown when the provided <paramref name="idConfig"/> is not a valid ObjectId format.</exception>
    [HttpPut("{idConfig}/field-list")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> UpdateFieldList(string idConfig, List<Field> fields)
    {
        if (!ObjectId.TryParse(idConfig, out var objectIdConfigDisplay))
            throw new InvalidFormatException(HttpEnum.ErrorMessage.BadRequestInvalidFormat);
        var result = await displayConfigService.UpdateFieldList(objectIdConfigDisplay, fields);
        return Ok(result);
    }

    /// <summary>
    /// Updates the display name of a hospital display configuration identified by the given configuration ID.
    /// Validates the ID format and the new display name, returning a success result when the update is applied
    /// or a not-modified status when no change is made.
    /// </summary>
    /// <param name="idConfig">The configuration identifier whose display name will be updated.</param>
    /// <param name="updateDisplayConfigNameDto">The data transfer object containing the new display configuration name.</param>
    /// <returns>An <see cref="IActionResult"/> containing the update result, or a not-modified status when the name is unchanged.</returns>
    /// <exception cref="InvalidFormatException">Thrown when the configuration ID is not a valid format or when the display name is empty.</exception>
    [HttpPost("{idConfig}/name")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> UpdateName(string idConfig, UpdateDisplayConfigNameDto updateDisplayConfigNameDto)
    {
        if (!ObjectId.TryParse(idConfig, out var objectIdConfigDisplay))
            throw new InvalidFormatException(HttpEnum.ErrorMessage.BadRequestInvalidFormat);
        var displayConfigName = updateDisplayConfigNameDto.DisplayName;
        if (displayConfigName.IsEmpty())
            throw new InvalidFormatException(HttpEnum.ErrorMessage.BadRequestInvalidFormat);
        var result =
            await displayConfigService.UpdateDisplayConfigHospitalName(objectIdConfigDisplay, displayConfigName);
        return result ? Ok(result) : Ok((int)HttpEnum.ErrorMessage.OkResouceNotModified);
    }

    /// <summary>
    /// Handles the HTTP POST request to insert a new card configuration. Requires the caller to be authorized with the appropriate role and permission for the "Source" entity on the "DisplayId" field, delegating the actual creation to the display configuration service.
    /// </summary>
    /// <param name="updateDisplayConfigNameDto">The data transfer object containing the card configuration details to be created.</param>
    /// <returns>An <see cref="IActionResult"/> containing the result of the insert operation wrapped in an HTTP 200 OK response.</returns>
    [HttpPost("card-config")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> InsertCardConfig(CreateDisplayConfigCardDto updateDisplayConfigNameDto)
    {
        var result = await displayConfigService.InsertCardConfig(updateDisplayConfigNameDto);
        return Ok(result);
    }

    /// <summary>
    /// Inserts a new card detail configuration for the source display.
    /// Requires the AuthSome role and "Source"-"DisplayId" permission to access.
    /// </summary>
    /// <param name="updateDisplayConfigNameDto">The data transfer object containing the details of the card display configuration to create.</param>
    /// <returns>An <see cref="IActionResult"/> containing the result of the insert operation wrapped in an HTTP 200 OK response.</returns>
    [HttpPost("detail-config")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> InsertCardDetailConfig(CreateDisplayConfigCardDto updateDisplayConfigNameDto)
    {
        var result = await displayConfigService.InsertCardDetailConfig(updateDisplayConfigNameDto);
        return Ok(result);
    }

    /// <summary>
    /// Inserts a new chart configuration based on the provided display configuration data, applying role-based and permission-based authorization checks.
    /// </summary>
    /// <param name="updateDisplayConfigNameDto">The data transfer object containing the chart configuration details to be created.</param>
    /// <returns>An <see cref="IActionResult"/> containing the result of the chart configuration insertion wrapped in an HTTP 200 OK response.</returns>
    [HttpPost("chart-config")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> InsertChartConfig(CreateDisplayConfigCardDto updateDisplayConfigNameDto)
    {
        var result = await displayConfigService.InsertChartConfig(updateDisplayConfigNameDto);
        return Ok(result);
    }

    /// <summary>
    /// Retrieves all card display configurations from the display configuration service.
    /// This endpoint allows anonymous access and returns the complete list of card configurations.
    /// </summary>
    /// <returns>An <see cref="IActionResult"/> containing the HTTP 200 OK response with all card configurations.</returns>
    [HttpGet("get-all-card-config")]
    [AllowAnonymous]
    public async Task<IActionResult> GetAllCardConfig()
    {
        var result = await displayConfigService.GetCardConfigAll();
        return Ok(result);
    }

    /// <summary>
    /// Deletes a display configuration identified by the provided identifier.
    /// Validates the identifier format and delegates the deletion to the display configuration service, returning a success response when the operation completes or raising a conflict when the deletion fails.
    /// </summary>
    /// <param name="idConfig">The identifier of the display configuration to delete.</param>
    /// <returns>An <see cref="IActionResult"/> containing the result of the deletion when successful.</returns>
    /// <exception cref="InvalidFormatException">Thrown when <paramref name="idConfig"/> is not a valid identifier format.</exception>
    /// <exception cref="ConflictException">Thrown when the display configuration could not be deleted.</exception>
    [HttpDelete("{idConfig}")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> DeleteDisplayConfig(string idConfig)
    {
        if (!ObjectId.TryParse(idConfig, out var objectIdConfigDisplay))
            throw new InvalidFormatException(HttpEnum.ErrorMessage.BadRequestInvalidFormat);
        var result = await displayConfigService.DeleteDisplayConfig(objectIdConfigDisplay);
        if (result) return Ok(result);

        throw new ConflictException(HttpEnum.ErrorMessage.ConflictDeleteFailed);
    }

    /// <summary>
    /// Deletes a chart configuration identified by its identifier. Validates the identifier format and returns success when the configuration is removed, or raises an error when deletion cannot be completed.
    /// </summary>
    /// <param name="idConfig">The string representation of the chart configuration's identifier to be deleted.</param>
    /// <returns>An <see cref="IActionResult"/> that returns HTTP 200 (OK) with the result of the deletion when the chart configuration is successfully removed.</returns>
    /// <exception cref="InvalidFormatException">Thrown when <paramref name="idConfig"/> is not a valid identifier format.</exception>
    /// <exception cref="ConflictException">Thrown when the chart configuration cannot be deleted due to a conflict.</exception>
    [HttpDelete("chart-config/{idConfig}")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> DeleteChartConfig(string idConfig)
    {
        if (!ObjectId.TryParse(idConfig, out var objectIdConfigDisplay))
            throw new InvalidFormatException(HttpEnum.ErrorMessage.BadRequestInvalidFormat);
        var result = await displayConfigService.DeleteChartConfig(objectIdConfigDisplay);
        if (result) return Ok(result);

        throw new ConflictException(HttpEnum.ErrorMessage.ConflictDeleteFailed);
    }

    /// <summary>
    /// Retrieves the chart configuration for the specified identifier.
    /// Returns the configuration when found, or throws a not-found exception when no matching configuration exists.
    /// </summary>
    /// <param name="idConfig">The string identifier of the chart configuration to retrieve. Must be a valid ObjectId.</param>
    /// <returns>The chart configuration wrapped in an HTTP 200 OK response when found.</returns>
    /// <exception cref="InvalidFormatException">Thrown when <paramref name="idConfig"/> is not a valid ObjectId format.</exception>
    /// <exception cref="NotFoundException">Thrown when no chart configuration matches the provided identifier.</exception>
    [HttpGet("chart-config/{idConfig}")]
    [AllowAnonymous]
    public async Task<IActionResult> GetChartConfig(string idConfig)
    {
        if (!ObjectId.TryParse(idConfig, out var objectIdConfigDisplay))
            throw new InvalidFormatException(HttpEnum.ErrorMessage.BadRequestInvalidFormat);
        var result = await displayConfigService.GetChartConfig(objectIdConfigDisplay);
        if (result != null) return Ok(result);

        throw new NotFoundException();
    }

    /// <summary>
    /// Retrieves the locations associated with the specified display configuration identifier.
    /// Validates that the provided identifier is a valid ObjectId; otherwise, an invalid format exception is thrown.
    /// </summary>
    /// <param name="idConfig">The display configuration identifier used to look up its associated locations.</param>
    /// <returns>The display configuration locations returned by the service.</returns>
    /// <exception cref="InvalidFormatException">Thrown when <paramref name="idConfig"/> is not a valid ObjectId format.</exception>
    [HttpGet("{idConfig}/locations")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> GetDisplayConfigLocations(string idConfig)
    {
        if (!ObjectId.TryParse(idConfig, out var objectIdConfigDisplay))
            throw new InvalidFormatException(HttpEnum.ErrorMessage.BadRequestInvalidFormat);
        return Ok(await displayConfigService.GetDisplayConfigLocations(objectIdConfigDisplay));
    }


    /// <summary>
    ///     Search media element
    /// </summary>
    /// <param name="id">display config id</param>
    /// <param name="filename"></param>
    /// <returns> File stream </returns>
    /// <exception cref="InvalidFormatException"></exception>
    //[AuthorizeRoles(RolesType.Some)]
    //[TypeFilter(type: typeof(AuthorizePermissionsAttribute), Arguments = new object[] { "DisplayId", AuthorizeUserByServiceType.CONFIGDISPLAY })]
    [HttpGet]
    [AllowAnonymous]
    [Route("{id}/getMedia/{filename}")]
    public async Task<IActionResult> StreamMediaById(string filename, string id)
    {
        try
        {
            // Validar el ID
            if (!ObjectId.TryParse(id, out var configDisplayId))
                throw new InvalidFormatException(HttpEnum.ErrorMessage.BadRequestInvalidFormat);

            // Obtener la configuraci�n y ruta
            var config = await displayConfigService.GetById(configDisplayId);
            var sharedFolderPath = config.MediaFolder;

            // Validar existencia de carpeta y archivo
            if (!Directory.Exists(sharedFolderPath)) return NotFound("Shared Folder Not Exists");

            var filePath = Path.Combine(sharedFolderPath, filename);
            if (!System.IO.File.Exists(filePath)) return NotFound("File not found");

            var fileInfo = new FileInfo(filePath);
            var fileLength = fileInfo.Length;

            // Leer el encabezado "Range"
            var rangeHeader = Request.Headers["Range"].ToString();
            var end = fileLength - 1;

            if (!string.IsNullOrEmpty(rangeHeader))
            {
                // Parsear el rango solicitado
                var range = rangeHeader.Replace("bytes=", "").Split('-');
                var start = long.Parse(range[0]);
                if (range.Length > 1 && !string.IsNullOrEmpty(range[1])) end = long.Parse(range[1]);

                // Validar el rango solicitado
                if (start >= fileLength || end >= fileLength || start > end)
                    return StatusCode(416, $"Requested Range Not Satisfiable. File length: {fileLength}");
            }

            // Crear un flujo continuo para transmitir los datos
            return new FileStreamResult(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read),
                MediaUtils.GetMimeType(filePath))
            {
                EnableRangeProcessing = true
            };
        }
        catch (Exception ex)
        {
            return StatusCode(500, $"Error al procesar la solicitud: {ex.Message}");
        }
    }


    /// <summary>
    ///     GetByCodeSysAndCode all media files in a shared folder
    /// </summary>
    /// <param name="id">display config id</param>
    /// <returns>File details list</returns>
    /// <exception cref="InvalidFormatException"></exception>
    [AllowAnonymous]
    [HttpGet("allMediaFiles/{id}")]
    public async Task<IActionResult> GetAllMediaFiles(string id)
    {
        try
        {
            if (!ObjectId.TryParse(id, out var configDisplayId))
                throw new InvalidFormatException(HttpEnum.ErrorMessage.BadRequestInvalidFormat);

            var config = await displayConfigService.GetById(configDisplayId);

            var sharedFolderPath = config.MediaFolder; // @"\\10.0.20.75\smartuci-nurseplan\ad-media";

            // Verificar si la carpeta existe
            if (!Directory.Exists(sharedFolderPath)) return NotFound("Shared Folder Not Exists");

            // Obtener todos los archivos en la carpeta
            var files = Directory.GetFiles(sharedFolderPath);

            var fileDetails = files.Select(file => new
            {
                Name = Path.GetFileName(file),
                Type = MediaUtils.GetMimeType(file),
                SizeInBytes = new FileInfo(file).Length,
                Duration = MediaUtils.IsVideoFile(file)
                    ? MediaUtils.GetVideoDuration(file)
                    : null // S�lo calcula duraci�n para videos
            });

            return Ok(JsonConvert.SerializeObject(fileDetails, new JsonSerializerSettings
            {
                Formatting = Formatting.None
            }));
        }
        catch (Exception ex)
        {
            return StatusCode(500, $"Error al procesar la solicitud: {ex.Message}");
        }
    }
}