using AsbCloudApp.Data;
using AsbCloudApp.Repositories;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace AsbCloudInfrastructure.Repository
{
#nullable enable
    public class FileStorageRepository : IFileStorageRepository
    {
        /// <summary>
        /// Директория хранения файлов
        /// </summary>
        private readonly string RootPath = "files";

        public FileStorageRepository()
        {
        }

        public async Task SaveFileAsync(string filePathRec, Stream fileStreamSrc, CancellationToken token)
        {
            CreateDirectory(filePathRec);
            using var newfileStream = new FileStream(filePathRec, FileMode.Create);
            await fileStreamSrc.CopyToAsync(newfileStream, token).ConfigureAwait(false);
        }

        public void DeleteFile(IEnumerable<string> filesName)
        {
            foreach (var fileName in filesName)
            {
                if (File.Exists(fileName))
                    File.Delete(fileName);
            }
        }

        public long GetFileLength(string srcFilePath)
        {
            var sysFileInfo = new FileInfo(srcFilePath);
            return sysFileInfo.Length;
        }

        public void MoveFile(string srcFilePath, string filePath)
        {
            CreateDirectory(filePath);
            File.Move(srcFilePath, filePath);
        }

        public string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId)
        {
            return Path.Combine(RootPath, $"{idWell}",
                    $"{idCategory}", $"{fileId}" + $"{Path.GetExtension(fileFullName)}");
        }

        public int DeleteFilesNotInList(int idWell, IEnumerable<int> idsFilesList)
        {
            var allFilesPath = GetFilesPath(idWell);
            var result = 0;

            foreach (var filePath in allFilesPath)
            {
                if (int.TryParse(Path.GetFileNameWithoutExtension(filePath), out int idFile) 
                    || !idsFilesList.Any(x => x == idFile))
                {
                    File.Delete(filePath);
                    result++;
                }
            }

            return result;
        }

        public IEnumerable<FileInfoDto> GetListFilesNotDisc(IEnumerable<FileInfoDto> files)
        { 
            var resutl = new List<FileInfoDto>();
            var groupFiles = files.GroupBy(x => x.IdWell);

            foreach (var itemGroupFiles in groupFiles)
            {
                var idsFilesStorage = GetIdsFiles(itemGroupFiles.Key);
                foreach (var file in files)
                {
                    if (!idsFilesStorage.Any(x => x == file.Id))
                        resutl.Add(file);
                }
            }

            return resutl;
        }

        public string GetUrl(int idWell, int idCategory, int idFile, string dotExtention) =>
            Path.Combine(RootPath, idWell.ToString(), idCategory.ToString(), $"{idFile}{dotExtention}");

        private IEnumerable<int> GetIdsFiles(int idWell)
        {
            var result = new List<int>();
            var allFilesPath = GetFilesPath(idWell);

            foreach (var filePath in allFilesPath)
                if(int.TryParse(Path.GetFileNameWithoutExtension(filePath), out int idFile))
                    result.Add(idFile);

            return result;
        }

        private IEnumerable<string> GetFilesPath(int idWell)
        {
            var path = Path.Combine(RootPath, $"{idWell}");
            return Directory.GetFiles(path, "*.*", SearchOption.AllDirectories);
        }

        private static void CreateDirectory(string filePath)
        {
            var directoryName = Path.GetDirectoryName(filePath)!;            
            Directory.CreateDirectory(directoryName);
        }
    }
#nullable disable
}