using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using PARR.BLL.Domain;
using PARR.BLL.Services.Interfaces;
using PARR.BLL.Settings;

namespace PARR.BLL.Services.Implementations
{
    internal class FileService : IFileService
    {
        private readonly StorageSettings storageSettings;
        private readonly ILogger<FileService> logger;

        public FileService(StorageSettings storageSettings, ILogger<FileService> logger)
        {
            this.storageSettings = storageSettings;
            this.logger = logger;
        }

        public bool IsExtensionAllowed(IFormFile formFile, string[] allowedExtensions)
        {
            var extension = Path.GetExtension(formFile.FileName).ToLower();

            return !string.IsNullOrEmpty(extension) && allowedExtensions.Contains(extension);
        }

        public bool IsNotExceededLimit(IFormFile formFile, int limitMb)
        {
            var fileSizeByte = formFile.Length;
            var fileSizeMByte = fileSizeByte / 1024.0 / 1024.0;

            return fileSizeMByte < limitMb;
        }

        public async Task<UploadResult?> UploadAsync(IFormFile formFile, string[] rootFolderWithoutStorage)
        {
            InitRootFolders(rootFolderWithoutStorage);

            //Генерим уникальное имя файла: старое имя + рандом в середину
            var newFileName = $"{Path.GetFileNameWithoutExtension(formFile.FileName)}-{Path.GetFileNameWithoutExtension(Path.GetRandomFileName())}{Path.GetExtension(formFile.FileName)}";


            var relativePath = Path.Combine(Path.Combine(rootFolderWithoutStorage), newFileName);
            var absPath = Path.Combine(storageSettings.StoragePath, relativePath);

            if (File.Exists(absPath))
            {
                logger.LogError($"Не могу сохранить файл, такой файл уже существует: {absPath}");
                return null;
            }

            try
            {
                var origFileName = Path.GetFileName(formFile.FileName);

                using (var stream = new FileStream(absPath, FileMode.Create))
                {
                    await formFile.CopyToAsync(stream);
                    logger.LogInformation($"Файл сохранен {origFileName}, {absPath}");
                }

                return new UploadResult { FileName = origFileName, Path = relativePath };
            }
            catch (Exception ex)
            {
                logger.LogError(ex, $"Ошибка при сохранении файла {absPath}");
                return null;
            }
        }

        private void InitRootFolders(string[] rootFolderWithoutStorage)
        {
            if (!rootFolderWithoutStorage.Any())
                return;

            var path = string.Empty;
            foreach (var item in rootFolderWithoutStorage)
            {
                path = Path.Combine(path, item);
                CreateDirectory(path);
            }
        }

        private void CreateDirectory(string relativePath)
        {
            var absolutePath = Path.Combine(storageSettings.StoragePath, relativePath);

            try
            {
                if (!Directory.Exists(absolutePath))
                    Directory.CreateDirectory(absolutePath);

                // не нужно ничего возвращать, при сохраненнии файла будет ошибка и ее обработаем
                //return true;
            }
            catch (Exception e)
            {
                logger.LogError(e, $"Не могу создать директорию: {absolutePath}");
                //return false;
            }
        }

        public bool DeleteFile(string path)
        {
            logger.LogInformation($"Удаляю файл: {path}");

            try
            {
                if (!File.Exists(path))
                    return true;

                File.Delete(path);
                logger.LogInformation($"Файл удален: {path}");

                return true;
            }
            catch (Exception e)
            {
                logger.LogError(e, $"Ошибка при удалении файла {path}");
                return false;
            }
        }
    }
}
