using AipGateway.AIP;
using AipGateway.API.Domain.IRepositories.IGenericRepositories;
using AipGateway.API.Domain.Models.Request;
using AipGateway.API.Domain.Models.Response;
using AutoMapper;
using Quartz.Util;
using System.IO;

namespace AipGateway.API.Services.impl
{
    public class ApiStreamService : IApiStreamService
    {
        private readonly ILogger<ApiFileService> _log;
        private readonly IUnitOfWork _unitOfWork;
        private readonly IMapper _mapper;

        public ApiStreamService(ILogger<ApiFileService> logger, IUnitOfWork unitOfWork, IMapper mapper)
        {
            _log = logger;
            _unitOfWork = unitOfWork;
            _mapper = mapper;
            _log.LogError("ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo: ApiStreamService");
        }

        public async Task<ResponseInfo> GetInfo(RequestStream req)
        {
            string actualFileName = Path.Combine(ContainerService.aipConfig.TargetFileDir, req.apiGuid + Path.GetExtension(req.dispFileName).ToLower());
            try
            {
                string? newFileExt = ContainerService.GetSupportedFileType(req.dispFileName);
                if (newFileExt == null)
                {
                    return new ResponseInfo
                    {
                        errorCode = 102,
                        errorMessage = "지원하지 않는 파일형식 입니다.",
                    };
                }
                var task = Task.Run(() =>
                {
                    using(var stream = new MemoryStream(Convert.FromBase64String(req.fileData)))
                    {
                        var fileInfo = ContainerService.aipFileManager.GetFileInfo(stream, actualFileName);
                        bool isLabled = false;
                        bool isProtected = false;
                        DateTime creationTime = DateTime.Now;
                        string contentId = string.Empty;
                        string owner = string.Empty;
                        string labelId = string.Empty;
                        string labelName = string.Empty;
                        string templateId = string.Empty;
                        string templateName = string.Empty;
                        Int64 fileSize = 0;
                        if (fileInfo != null)
                        {
                            fileSize = fileInfo.FileSize;
                            if (fileInfo.Content != null)
                            {
                                creationTime = fileInfo.Content.CreationTime;
                            }
                            if (fileInfo.Label != null)
                            {
                                isLabled = true;
                                labelId = fileInfo.Label.Id;
                                labelName = fileInfo.Label.Name;
                            }
                            if (fileInfo.Protection != null)
                            {
                                owner = fileInfo.Protection.Owner;
                                contentId = fileInfo.Protection.ContentId;
                                if (fileInfo.Protection.ProtectionDescriptor != null)
                                {
                                    isProtected = true;
                                    templateId = fileInfo.Protection.ProtectionDescriptor.TemplateId;
                                    templateName = fileInfo.Protection.ProtectionDescriptor.Name;
                                }
                            }
                        }
                        return new ResponseInfo
                        {
                            isLabled = isLabled,
                            isProtected = isProtected,
                            creationTime = creationTime,
                            contentId = contentId,
                            owner = owner,
                            labelId = labelId,
                            labelName = labelName,
                            templateId = templateId,
                            templateName = templateName,
                            dispFileName = req.dispFileName,

                            FileLabelGuid = labelId,
                            FileProtectionGuid = templateId,
                            FileOwner = owner,
                            FileExt = Path.GetExtension(req.dispFileName),
                            FileSize = fileSize,
                        };
                    }
                });
                ResponseInfo result = await task;
                return result;
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                ContainerService.DeleteFile(actualFileName);
            }
        }

        public async Task<ResponseStream> SetLabel(RequestStreamSet req)
        {
            string actualFileName = Path.Combine(ContainerService.aipConfig.TargetFileDir, req.apiGuid + Path.GetExtension(req.dispFileName).ToLower());
            try
            {
                string? newFileExt = ContainerService.GetSupportedFileType(req.dispFileName);
                if (newFileExt == null)
                {
                    return new ResponseStream
                    {
                        errorCode = 102,
                        errorMessage = "지원하지 않는 파일형식 입니다.",
                        dispFileName = req.dispFileName,
                    };
                }

                var task = Task.Run(() =>
                {
                    string fileExt = Path.GetExtension(req.dispFileName).ToLower();
                    string? newFileExt = ContainerService.GetSupportedFileType(req.dispFileName);
                    if (newFileExt == null)
                    {
                        return new ResponseStream
                        {
                            errorCode = 102,
                            errorMessage = "지원하지 않는 파일형식 입니다.",
                            dispFileName = req.dispFileName,
                        };
                    }
                    using (var stream = new MemoryStream(Convert.FromBase64String(req.fileData)))
                    {
                        string dispFileName = Path.GetFileNameWithoutExtension(req.dispFileName) + newFileExt;
                        actualFileName = Path.Combine(ContainerService.aipConfig.TargetFileDir, req.apiGuid + newFileExt);
                        string comment = req.comment.IsNullOrWhiteSpace() ? "SetLabel" : req.comment;
                        SetFileInfo result = ContainerService.aipFileManager.SetLabel(stream, actualFileName, req.email, req.aipGuid, "", comment);
                        return new ResponseStream
                        {
                            errorCode = result.errorNo,
                            errorMessage = result.errorMsg,
                            dispFileName = dispFileName,
                            outputFileName = Path.GetFileName(actualFileName),
                            fileData = ContainerService.GetFileData(actualFileName),

                            FileOwner = result.fileOwner,
                            FileExt = fileExt,
                            FileSize = result.fileSize,
                            FileLabelGuid = result.lableGuid,
                            FileProtectionGuid = result.templateGuid,

                            NewFileName = dispFileName,
                            NewFileOwner = result.newFileOwner,
                            NewFileExt = newFileExt,
                            NewFileSize = result.newFileSize,
                            NewFileLabelGuid = result.newFileLabelGuid,
                            NewFileProtectionGuid = result.newFileTemplateGuid,
                        };
                    }
                });
                ResponseStream result = await task;
                return result;
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                ContainerService.DeleteFile(actualFileName);
            }
        }

        public async Task<ResponseStream> DelLabel(RequestStreamDel req)
        {
            string actualFileName = Path.Combine(ContainerService.aipConfig.TargetFileDir, req.apiGuid + Path.GetExtension(req.dispFileName).ToLower());
            try
            {
                string? newFileExt = ContainerService.GetSupportedFileType(req.dispFileName);
                if (newFileExt == null)
                {
                    return new ResponseStream
                    {
                        errorCode = 102,
                        errorMessage = "지원하지 않는 파일형식 입니다.",
                        dispFileName = req.dispFileName,
                    };
                }

                var task = Task.Run(() =>
                {
                    string fileExt = Path.GetExtension(req.dispFileName).ToLower();
                    string? newFileExt = ContainerService.GetSupportedFileType(req.dispFileName);
                    if (newFileExt == null)
                    {
                        return new ResponseStream
                        {
                            errorCode = 102,
                            errorMessage = "지원하지 않는 파일형식 입니다.",
                            dispFileName = req.dispFileName,
                        };
                    }
                    using (var stream = new MemoryStream(Convert.FromBase64String(req.fileData)))
                    {
                        string dispFileName = Path.GetFileNameWithoutExtension(req.dispFileName) + newFileExt;
                        actualFileName = Path.Combine(ContainerService.aipConfig.TargetFileDir, req.apiGuid + newFileExt);
                        string comment = req.comment.IsNullOrWhiteSpace() ? "DelLabel" : req.comment;
                        SetFileInfo result = ContainerService.aipFileManager.DeleteLabel(stream, actualFileName, req.email, comment);
                        return new ResponseStream
                        {
                            errorCode = result.errorNo,
                            errorMessage = result.errorMsg,
                            dispFileName = dispFileName,
                            outputFileName = Path.GetFileName(actualFileName),
                            fileData = ContainerService.GetFileData(actualFileName),

                            FileOwner = result.fileOwner,
                            FileExt = fileExt,
                            FileSize = result.fileSize,
                            FileLabelGuid = result.lableGuid,
                            FileProtectionGuid = result.templateGuid,

                            NewFileName = dispFileName,
                            NewFileOwner = result.newFileOwner,
                            NewFileExt = newFileExt,
                            NewFileSize = result.newFileSize,
                            NewFileLabelGuid = result.newFileLabelGuid,
                            NewFileProtectionGuid = result.newFileTemplateGuid,
                        };
                    }
                });
                ResponseStream result = await task;
                return result;
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                ContainerService.DeleteFile(actualFileName);
            }
        }

        public async Task<ResponseStream> SetProtection(RequestStreamSet req)
        {
            string actualFileName = Path.Combine(ContainerService.aipConfig.TargetFileDir, req.apiGuid + Path.GetExtension(req.dispFileName).ToLower());
            try
            {
                string? newFileExt = ContainerService.GetSupportedFileType(req.dispFileName);
                if (newFileExt == null)
                {
                    return new ResponseStream
                    {
                        errorCode = 102,
                        errorMessage = "지원하지 않는 파일형식 입니다.",
                        dispFileName = req.dispFileName,
                    };
                }

                var task = Task.Run(() =>
                {
                    string fileExt = Path.GetExtension(req.dispFileName).ToLower();
                    string? newFileExt = ContainerService.GetSupportedFileType(req.dispFileName);
                    if (newFileExt == null)
                    {
                        return new ResponseStream
                        {
                            errorCode = 102,
                            errorMessage = "지원하지 않는 파일형식 입니다.",
                            dispFileName = req.dispFileName,
                        };
                    }
                    using (var stream = new MemoryStream(Convert.FromBase64String(req.fileData)))
                    {
                        string dispFileName = Path.GetFileNameWithoutExtension(req.dispFileName) + newFileExt;
                        actualFileName = Path.Combine(ContainerService.aipConfig.TargetFileDir, req.apiGuid + newFileExt);
                        string comment = req.comment.IsNullOrWhiteSpace() ? "SetProtection" : req.comment;
                        SetFileInfo result = ContainerService.aipFileManager.SetProtection(stream, actualFileName, req.email, req.aipGuid, comment);
                        return new ResponseStream
                        {
                            errorCode = result.errorNo,
                            errorMessage = result.errorMsg,
                            dispFileName = dispFileName,
                            outputFileName = Path.GetFileName(actualFileName),
                            fileData = ContainerService.GetFileData(actualFileName),

                            FileOwner = result.fileOwner,
                            FileExt = fileExt,
                            FileSize = result.fileSize,
                            FileLabelGuid = result.lableGuid,
                            FileProtectionGuid = result.templateGuid,

                            NewFileName = dispFileName,
                            NewFileOwner = result.newFileOwner,
                            NewFileExt = newFileExt,
                            NewFileSize = result.newFileSize,
                            NewFileLabelGuid = result.newFileLabelGuid,
                            NewFileProtectionGuid = result.newFileTemplateGuid,
                        };
                    }
                });
                ResponseStream result = await task;
                return result;
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                ContainerService.DeleteFile(actualFileName);
            }
        }

        public async Task<ResponseStream> DelProtection(RequestStreamDel req)
        {
            string actualFileName = Path.Combine(ContainerService.aipConfig.TargetFileDir, req.apiGuid + Path.GetExtension(req.dispFileName).ToLower());
            try
            {
                string? newFileExt = ContainerService.GetSupportedFileType(req.dispFileName);
                if (newFileExt == null)
                {
                    return new ResponseStream
                    {
                        errorCode = 102,
                        errorMessage = "지원하지 않는 파일형식 입니다.",
                        dispFileName = req.dispFileName,
                    };
                }

                var task = Task.Run(() =>
                {
                    string fileExt = Path.GetExtension(req.dispFileName).ToLower();
                    string? newFileExt = ContainerService.GetSupportedFileType(req.dispFileName);
                    if (newFileExt == null)
                    {
                        return new ResponseStream
                        {
                            errorCode = 102,
                            errorMessage = "지원하지 않는 파일형식 입니다.",
                            dispFileName = req.dispFileName,
                        };
                    }
                    using (var stream = new MemoryStream(Convert.FromBase64String(req.fileData)))
                    {
                        string dispFileName = Path.GetFileNameWithoutExtension(req.dispFileName) + newFileExt;
                        actualFileName = Path.Combine(ContainerService.aipConfig.TargetFileDir, req.apiGuid + newFileExt);
                        string comment = req.comment.IsNullOrWhiteSpace() ? "DelLabel" : req.comment;
                        SetFileInfo result = ContainerService.aipFileManager.DeleteLabel(stream, actualFileName, req.email, comment);
                        return new ResponseStream
                        {
                            errorCode = result.errorNo,
                            errorMessage = result.errorMsg,
                            dispFileName = dispFileName,
                            outputFileName = Path.GetFileName(actualFileName),
                            fileData = ContainerService.GetFileData(actualFileName),

                            FileOwner = result.fileOwner,
                            FileExt = fileExt,
                            FileSize = result.fileSize,
                            FileLabelGuid = result.lableGuid,
                            FileProtectionGuid = result.templateGuid,

                            NewFileName = dispFileName,
                            NewFileOwner = result.newFileOwner,
                            NewFileExt = newFileExt,
                            NewFileSize = result.newFileSize,
                            NewFileLabelGuid = result.newFileLabelGuid,
                            NewFileProtectionGuid = result.newFileTemplateGuid,
                        };
                    }
                });
                ResponseStream result = await task;
                return result;
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                ContainerService.DeleteFile(actualFileName);
            }
        }

        public async Task<ResponseStream> SetLabelProtection(RequestStreamAllSet req)
        {
            string actualFileName = Path.Combine(ContainerService.aipConfig.TargetFileDir, req.apiGuid + Path.GetExtension(req.dispFileName).ToLower());
            try
            {
                string? newFileExt = ContainerService.GetSupportedFileType(req.dispFileName);
                if (newFileExt == null)
                {
                    return new ResponseStream
                    {
                        errorCode = 102,
                        errorMessage = "지원하지 않는 파일형식 입니다.",
                        dispFileName = req.dispFileName,
                    };
                }

                var task = Task.Run(() =>
                {
                    string fileExt = Path.GetExtension(req.dispFileName).ToLower();
                    string? newFileExt = ContainerService.GetSupportedFileType(req.dispFileName);
                    if (newFileExt == null)
                    {
                        return new ResponseStream
                        {
                            errorCode = 102,
                            errorMessage = "지원하지 않는 파일형식 입니다.",
                            dispFileName = req.dispFileName,
                        };
                    }
                    using (var stream = new MemoryStream(Convert.FromBase64String(req.fileData)))
                    {
                        string dispFileName = Path.GetFileNameWithoutExtension(req.dispFileName) + newFileExt;
                        actualFileName = Path.Combine(ContainerService.aipConfig.TargetFileDir, req.apiGuid + newFileExt);
                        string comment = req.comment.IsNullOrWhiteSpace() ? "SetLabel" : req.comment;
                        SetFileInfo result = ContainerService.aipFileManager.SetLabel(stream, actualFileName, req.email, req.labelGuid, req.templateGuid, comment);
                        return new ResponseStream
                        {
                            errorCode = result.errorNo,
                            errorMessage = result.errorMsg,
                            dispFileName = dispFileName,
                            outputFileName = Path.GetFileName(actualFileName),
                            fileData = ContainerService.GetFileData(actualFileName),

                            FileOwner = result.fileOwner,
                            FileExt = fileExt,
                            FileSize = result.fileSize,
                            FileLabelGuid = result.lableGuid,
                            FileProtectionGuid = result.templateGuid,

                            NewFileName = dispFileName,
                            NewFileOwner = result.newFileOwner,
                            NewFileExt = newFileExt,
                            NewFileSize = result.newFileSize,
                            NewFileLabelGuid = result.newFileLabelGuid,
                            NewFileProtectionGuid = result.newFileTemplateGuid,
                        };
                    }
                });
                ResponseStream result = await task;
                return result;
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                ContainerService.DeleteFile(actualFileName);
            }
        }

        public async Task<ResponseStream> DelLabelProtection(RequestStreamDel req)
        {
            string actualFileName = Path.Combine(ContainerService.aipConfig.TargetFileDir, req.apiGuid + Path.GetExtension(req.dispFileName).ToLower());
            try
            {
                string? newFileExt = ContainerService.GetSupportedFileType(req.dispFileName);
                if (newFileExt == null)
                {
                    return new ResponseStream
                    {
                        errorCode = 102,
                        errorMessage = "지원하지 않는 파일형식 입니다.",
                        dispFileName = req.dispFileName,
                    };
                }

                var task = Task.Run(() =>
                {
                    string fileExt = Path.GetExtension(req.dispFileName).ToLower();
                    string? newFileExt = ContainerService.GetSupportedFileType(req.dispFileName);
                    if (newFileExt == null)
                    {
                        return new ResponseStream
                        {
                            errorCode = 102,
                            errorMessage = "지원하지 않는 파일형식 입니다.",
                            dispFileName = req.dispFileName,
                        };
                    }
                    using (var stream = new MemoryStream(Convert.FromBase64String(req.fileData)))
                    {
                        string dispFileName = Path.GetFileNameWithoutExtension(req.dispFileName) + newFileExt;
                        actualFileName = Path.Combine(ContainerService.aipConfig.TargetFileDir, req.apiGuid + newFileExt);
                        string comment = req.comment.IsNullOrWhiteSpace() ? "DelLabel" : req.comment;
                        SetFileInfo result = ContainerService.aipFileManager.DeleteLabel(stream, actualFileName, req.email, comment, true);
                        return new ResponseStream
                        {
                            errorCode = result.errorNo,
                            errorMessage = result.errorMsg,
                            dispFileName = dispFileName,
                            outputFileName = Path.GetFileName(actualFileName),
                            fileData = ContainerService.GetFileData(actualFileName),

                            FileOwner = result.fileOwner,
                            FileExt = fileExt,
                            FileSize = result.fileSize,
                            FileLabelGuid = result.lableGuid,
                            FileProtectionGuid = result.templateGuid,

                            NewFileName = dispFileName,
                            NewFileOwner = result.newFileOwner,
                            NewFileExt = newFileExt,
                            NewFileSize = result.newFileSize,
                            NewFileLabelGuid = result.newFileLabelGuid,
                            NewFileProtectionGuid = result.newFileTemplateGuid,
                        };
                    }
                });
                ResponseStream result = await task;
                return result;
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                ContainerService.DeleteFile(actualFileName);
            }
        }

    }
}
