//using Microsoft.AspNetCore.Http;

using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Enums;
using adas_core.Domain.Models.AppSettings;
using adas_core.Domain.Models.DTO;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Serilog;

namespace adas_core.Application.Services;

/// <summary>
/// Provides a concrete implementation of the <see cref="IFileService"/> contract for performing file-related operations.
/// </summary>
public class FileService : IFileService
{
    private readonly string? _assetsDirectory;

    private readonly ILogger<FileService> _logger;
    private readonly string? _updateDirectory;

    public FileService(
        IOptions<ApiSettings> apiSettings,
        ILogger<FileService> logger
    )
    {
        _logger = logger;

        if (apiSettings.Value.PathUpdateFiles != null)
            _updateDirectory = Path.Combine(apiSettings.Value.PathUpdateFiles);
        if (apiSettings.Value.PathToDisplayAssets != null)
            _assetsDirectory = Path.Combine(apiSettings.Value.PathToDisplayAssets);
    }


    /// <summary>
    /// Copies the provided uploaded files into the configured update directory, creating each file on disk.
    /// Returns false if the update directory is not configured (null, empty, or whitespace); otherwise returns true after all files have been copied.
    /// </summary>
    /// <param name="files">The collection of uploaded form files to be written to the update directory.</param>
    /// <returns>A task that resolves to true when every file is successfully copied, or false when the update directory is not configured.</returns>
    public async Task<bool> CopyUpdateFiles(ICollection<IFormFile> files)
    {
        if (string.IsNullOrWhiteSpace(_updateDirectory)) return false;

        foreach (var file in files)
        {
            await using var stream = new FileStream(Path.Combine(_updateDirectory, file.FileName), FileMode.Create);
            await file.CopyToAsync(stream);
        }

        return true;
    }

    /// <summary>
    /// Asynchronously uploads a collection of asset files into a directory organized by the specified theme. If the assets directory is not configured, the method returns false; otherwise, it ensures the target directory exists, writes each file to disk, and returns true.
    /// </summary>
    /// <param name="files">The collection of uploaded form files to persist to the assets directory.</param>
    /// <param name="themeParse">The asset theme used to determine the subdirectory in which the files will be stored.</param>
    /// <returns>A task that resolves to <c>true</c> when the files are successfully written, or <c>false</c> when the assets directory path is not configured.</returns>
    public async Task<bool> UploadAssetFiles(ICollection<IFormFile> files, FileEnum.AssetTheme themeParse)
    {
        if (string.IsNullOrWhiteSpace(_assetsDirectory)) return false;
        var directoryInfo = new DirectoryInfo(Path.Combine(_assetsDirectory, themeParse.ToString()));
        if (!directoryInfo.Exists) directoryInfo.Create();
        foreach (var file in files)
        {
            await using var stream =
                new FileStream(Path.Combine(_assetsDirectory, themeParse.ToString(), file.FileName), FileMode.Create);
            await file.CopyToAsync(stream);
        }

        return true;
    }

    /// <summary>
    /// Retrieves all asset files from the subdirectory that matches the specified theme, creating the subdirectory if it does not exist.
    /// Returns an empty list when the assets directory is not configured or when an error occurs while reading the files.
    /// </summary>
    /// <param name="themeParse">The theme used to locate the corresponding subdirectory within the assets directory.</param>
    /// <returns>A list of <see cref="AssetDto"/> objects containing the name, extension, and full path of each file found; an empty list if the assets directory is not configured or an error occurs.</returns>
    public List<AssetDto> GetAllAssetFile(FileEnum.AssetTheme themeParse)
    {
        try
        {
            if (string.IsNullOrWhiteSpace(_assetsDirectory)) return [];
            var listToReturn = new List<AssetDto>();
            var directoryInfo = new DirectoryInfo(Path.Combine(_assetsDirectory, themeParse.ToString()));

            if (!directoryInfo.Exists) directoryInfo.Create();

            var files = directoryInfo.GetFiles(); // Obtener todos los archivos en el directorio
            foreach (var file in files)
            {
                var assetDto = new AssetDto
                {
                    Name = file.Name,
                    Extension = file.Extension,
                    Path = file.FullName // Obtener la ruta completa del archivo
                };
                listToReturn.Add(assetDto);
            }

            return listToReturn;
        }
        catch (Exception e)
        {
            _logger.LogError("Error while retrieving assets: {eMessage} {eStackTrace}", e.Message, e.StackTrace);
            return [];
        }
    }

    /// <summary>
    /// Retrieves the list of file paths contained in the specified directory.
    /// If the directory does not exist, a warning is logged and an empty list is returned;
    /// if an error occurs during retrieval, it is logged and an empty list is returned.
    /// </summary>
    /// <param name="directoryPath">The path of the directory to search for files.</param>
    /// <returns>A list of file paths found in the directory, or an empty list if the directory does not exist or an error occurs.</returns>
    public List<string> GetFilesInDirectory(string directoryPath)
    {
        List<string> fileList = [];

        try
        {
            if (Directory.Exists(directoryPath))
                // Obtiene todos los archivos en el directorio
                fileList.AddRange(Directory.GetFiles(directoryPath));
            else
                Log.Warning("La ruta proporcionada no existe: {directoryPath}", directoryPath);
        }
        catch (Exception ex)
        {
            Log.Error("Ocurrió un error al buscar archivos: {exMessage}", ex.Message);
        }

        return fileList;
    }
}