using Lada.Framework.DTO;
using Lada.Framework.DTO.Enums;
using Lada.Framework.DTO.Results;
using Lada.Framework.Infrastructures.AppSettings;
using Lada.Framework.Infrastructures.Helpers;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using System.Diagnostics;

namespace Lada.Framework.Infrastructures.Services
{
    /// <summary>
    /// Giao diện cho dịch vụ upload CV
    /// </summary>
    public interface ICvUploadService
    {
        /// <summary>
        /// Upload file CV
        /// </summary>
        /// <param name="file">File CV</param>
        /// <param name="candidateId">ID ứng viên (tùy chọn)</param>
        /// <param name="documentType">Loại tài liệu</param>
        /// <returns>Kết quả upload</returns>
        Task<CvUploadResult> UploadCvAsync(IFormFile file, int? candidateId = null, DocumentType documentType = DocumentType.CV);

        /// <summary>
        /// Xóa file CV
        /// </summary>
        /// <param name="filePath">Đường dẫn file</param>
        /// <returns>Kết quả xóa</returns>
        Task<BaseResult> DeleteCvAsync(string filePath);

        /// <summary>
        /// Lấy URL từ đường dẫn hệ thống
        /// </summary>
        /// <param name="filePath">Đường dẫn file</param>
        /// <returns>URL truy cập</returns>
        string GetUrlFromPath(string filePath);
    }

    /// <summary>
    /// Triển khai dịch vụ upload CV
    /// </summary>
    public class CvUploadService : ICvUploadService
    {
        private readonly MediaProcessingSettings _settings;
        private readonly IAppConfigService? _appConfigService;
        private readonly string[] _allowedExtensions = [".pdf", ".doc", ".docx", ".jpg", ".jpeg", ".png"];
        private readonly long _maxFileSize = 10 * 1024 * 1024; // 10MB

        public CvUploadService(IOptions<MediaProcessingSettings> settings, IAppConfigService? appConfigService = null)
        {
            _settings = settings.Value;
            _appConfigService = appConfigService;
        }

        /// <summary>
        /// Upload file CV
        /// </summary>
        /// <param name="file">File CV</param>
        /// <param name="candidateId">ID ứng viên (tùy chọn)</param>
        /// <param name="documentType">Loại tài liệu</param>
        /// <returns>Kết quả upload</returns>
        public async Task<CvUploadResult> UploadCvAsync(IFormFile file, int? candidateId = null, DocumentType documentType = DocumentType.CV)
        {
            var result = new CvUploadResult();

            try
            {
                // Kiểm tra file
                if (file == null || file.Length == 0)
                {
                    result.Result = Result.Failed;
                    result.Message = "Không có file được chọn";
                    return result;
                }

                // Kiểm tra kích thước file
                if (file.Length > _maxFileSize)
                {
                    result.Result = Result.Failed;
                    result.Message = $"File quá lớn. Kích thước tối đa cho phép là {_maxFileSize / (1024 * 1024)}MB";
                    return result;
                }

                // Kiểm tra định dạng file
                var fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant();
                if (!_allowedExtensions.Contains(fileExtension))
                {
                    result.Result = Result.Failed;
                    result.Message = $"Định dạng file không được hỗ trợ. Chỉ chấp nhận: {string.Join(", ", _allowedExtensions)}";
                    return result;
                }

                // Tạo tên file unique
                var fileName = GenerateFileName(file);

                // Tạo đường dẫn thư mục theo cấu trúc Documents\CV\yyyy\mm\dd\
                var folderPath = GetDocumentFolderPath(documentType);

                // Lưu file gốc vào hệ thống
                var savedOriginalFilePath = await SaveToDiskAsync(file, fileName, folderPath);

                // Chuyển đổi sang PDF nếu cần
                var finalFilePath = await ConvertToPdfIfNeeded(savedOriginalFilePath, fileExtension);

                // Tạo URL truy cập
                var fileUrl = await GetUrlBySystemPath(finalFilePath);

                // Lấy thông tin file sau khi xử lý
                var fileInfo = new FileInfo(finalFilePath);

                // Trả về kết quả
                result.Result = Result.Success;
                result.Message = "Upload CV thành công";
                result.FileName = file.FileName;
                result.FilePath = finalFilePath;
                result.FileUrl = fileUrl;
                result.FileSize = fileInfo.Length;
                result.FileType = Path.GetExtension(finalFilePath); // Có thể là .pdf sau khi convert
                result.UploadedTime = DateTimeHelper.CurrentTime();
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = $"Lỗi upload CV: {ex.Message}";
            }

            return result;
        }

        /// <summary>
        /// Xóa file CV
        /// </summary>
        /// <param name="filePath">Đường dẫn file</param>
        /// <returns>Kết quả xóa</returns>
        public Task<BaseResult> DeleteCvAsync(string filePath)
        {
            var result = new BaseResult();

            try
            {
                if (string.IsNullOrEmpty(filePath))
                {
                    result.Result = Result.Success;
                    result.Message = "Không có file để xóa";
                    return Task.FromResult(result);
                }

                if (File.Exists(filePath))
                {
                    File.Delete(filePath);
                }

                result.Result = Result.Success;
                result.Message = "Xóa file CV thành công";
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = $"Lỗi xóa file CV: {ex.Message}";
            }

            return Task.FromResult(result);
        }

        /// <summary>
        /// Lấy URL từ đường dẫn hệ thống
        /// </summary>
        /// <param name="filePath">Đường dẫn file</param>
        /// <returns>URL truy cập</returns>
        public string GetUrlFromPath(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
                return "";

            // Sử dụng logic tương tự ImageService
            return GetUrlBySystemPath(filePath).Result;
        }

        #region Private Methods

        /// <summary>
        /// Tạo đường dẫn thư mục cho tài liệu theo cấu trúc Documents\{DocumentType}\yyyy\mm\dd\
        /// </summary>
        /// <param name="documentType">Loại tài liệu</param>
        /// <returns>Đường dẫn thư mục tương đối</returns>
        private static string GetDocumentFolderPath(DocumentType documentType)
        {
            var now = DateTimeOffset.Now;
            var documentTypeName = Enum.GetName(documentType) ?? "CV";
            return $"Documents\\{documentTypeName}\\{now.Year}\\{now.Month}\\{now.Day}\\";
        }

        /// <summary>
        /// Tạo tên file unique
        /// </summary>
        /// <param name="file">File upload</param>
        /// <returns>Tên file unique</returns>
        private static string GenerateFileName(IFormFile file)
        {
            var fileNameWithoutExt = Path.GetFileNameWithoutExtension(file.FileName);
            var fileExt = Path.GetExtension(file.FileName).ToLower();
            var fileName = fileNameWithoutExt.Length <= 90 ? fileNameWithoutExt : fileNameWithoutExt.Substring(0, 90);
            return $"{fileName}-{DateTimeOffset.Now.Ticks}{fileExt}";
        }

        /// <summary>
        /// Lưu file vào đĩa
        /// </summary>
        /// <param name="file">File cần lưu</param>
        /// <param name="fileName">Tên file</param>
        /// <param name="relativeFolder">Thư mục tương đối</param>
        /// <returns>Đường dẫn file đầy đủ</returns>
        private async Task<string> SaveToDiskAsync(IFormFile file, string fileName, string relativeFolder)
        {
            // Lấy RootPath từ AppConfigService (cached) hoặc fallback về settings
            var rootPath = _appConfigService != null
                ? await _appConfigService.GetConfigValueAsync("Media.RootPath") ?? _settings.RootPath
                : _settings.RootPath;

            if (string.IsNullOrEmpty(rootPath))
                throw new InvalidOperationException("RootPath not configured");

            var fullFolderPath = Path.Combine(rootPath, relativeFolder);
            var filePath = Path.Combine(fullFolderPath, fileName);

            if (!Directory.Exists(fullFolderPath))
            {
                Directory.CreateDirectory(fullFolderPath);
            }

            var fileInfo = new FileInfo(filePath);
            if (fileInfo.Exists)
            {
                fileInfo.Delete();
            }

            using var fileStream = new FileStream(filePath, FileMode.Create);
            await file.CopyToAsync(fileStream);

            return filePath;
        }

        /// <summary>
        /// Tạo URL từ system path (tương tự ImageService)
        /// </summary>
        /// <param name="systemPath">Đường dẫn hệ thống</param>
        /// <returns>URL truy cập</returns>
        private async Task<string> GetUrlBySystemPath(string systemPath)
        {
            try
            {
                string domain;
                string rootPath;

                if (_appConfigService != null)
                {
                    domain = await _appConfigService.GetConfigValueAsync("Media.Domain") ?? _settings.Domain;
                    rootPath = await _appConfigService.GetConfigValueAsync("Media.RootPath") ?? _settings.RootPath ?? throw new InvalidOperationException("RootPath not configured");
                }
                else
                {
                    domain = _settings.Domain;
                    rootPath = _settings.RootPath ?? throw new InvalidOperationException("RootPath not configured");
                }

                if (!string.IsNullOrEmpty(domain) && !string.IsNullOrEmpty(rootPath))
                {
                    // Normalize paths để đảm bảo consistent format
                    var normalizedSystemPath = systemPath.Replace("\\", "/");
                    var normalizedRootPath = rootPath.Replace("\\", "/").TrimEnd('/');

                    // Tạo relative path
                    var relativePath = normalizedSystemPath.Replace(normalizedRootPath + "/", "");

                    // Tạo URL
                    return $"{domain.TrimEnd('/')}/{relativePath}";
                }
            }
            catch (Exception)
            {
                // Log error if needed
            }

            return string.Empty;
        }

        /// <summary>
        /// Chuyển đổi file sang PDF nếu cần thiết
        /// </summary>
        /// <param name="originalFilePath">Đường dẫn file gốc</param>
        /// <param name="originalExtension">Extension file gốc</param>
        /// <returns>Đường dẫn file sau khi xử lý (có thể là PDF hoặc file gốc)</returns>
        private async Task<string> ConvertToPdfIfNeeded(string originalFilePath, string originalExtension)
        {
            try
            {
                // Kiểm tra cấu hình có cho phép convert không
                bool autoConvertToPdf = _appConfigService != null
                    ? bool.TryParse(await _appConfigService.GetConfigValueAsync("Media.AutoConvertToPdf"), out var configValue) ? configValue : _settings.AutoConvertToPdf
                    : _settings.AutoConvertToPdf;

                if (!autoConvertToPdf)
                {
                    return originalFilePath;
                }

                // Nếu đã là PDF hoặc là ảnh thì không cần convert
                if (originalExtension.ToLowerInvariant() == ".pdf" ||
                    IsImageFile(originalExtension))
                {
                    return originalFilePath;
                }

                // Chỉ convert các file document (doc, docx) sang PDF
                if (IsDocumentFile(originalExtension))
                {
                    return await ConvertDocumentToPdf(originalFilePath);
                }

                // Các file khác giữ nguyên
                return originalFilePath;
            }
            catch (Exception ex)
            {
                // Nếu convert thất bại, log error và trả về file gốc
                // TODO: Add logging here
                return originalFilePath;
            }
        }

        /// <summary>
        /// Kiểm tra xem có phải file ảnh không
        /// </summary>
        /// <param name="extension">Extension file</param>
        /// <returns>True nếu là file ảnh</returns>
        private static bool IsImageFile(string extension)
        {
            var imageExtensions = new[] { ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff" };
            return imageExtensions.Contains(extension.ToLowerInvariant());
        }

        /// <summary>
        /// Kiểm tra xem có phải file document không
        /// </summary>
        /// <param name="extension">Extension file</param>
        /// <returns>True nếu là file document</returns>
        private static bool IsDocumentFile(string extension)
        {
            var documentExtensions = new[] { ".doc", ".docx", ".rtf", ".txt" };
            return documentExtensions.Contains(extension.ToLowerInvariant());
        }

        /// <summary>
        /// Chuyển đổi file document sang PDF
        /// </summary>
        /// <param name="documentPath">Đường dẫn file document</param>
        /// <returns>Đường dẫn file PDF</returns>
        private async Task<string> ConvertDocumentToPdf(string documentPath)
        {
            var fileInfo = new FileInfo(documentPath);
            var outputFolder = fileInfo.Directory!.FullName;
            var fileName = Path.GetFileNameWithoutExtension(documentPath);
            var pdfFilePath = Path.Combine(outputFolder, $"{fileName}.pdf");

            // Xóa file PDF cũ nếu tồn tại
            if (File.Exists(pdfFilePath))
            {
                File.Delete(pdfFilePath);
            }

            try
            {
                // Sử dụng LibreOffice để convert (nếu có cài đặt)
                var success = await ConvertUsingLibreOffice(documentPath, outputFolder);

                if (success && File.Exists(pdfFilePath))
                {
                    // Kiểm tra cấu hình có xóa file gốc không
                    bool deleteOriginal = _appConfigService != null
                        ? bool.TryParse(await _appConfigService.GetConfigValueAsync("Media.DeleteOriginalAfterConvert"), out var configValue) ? configValue : _settings.DeleteOriginalAfterConvert
                        : _settings.DeleteOriginalAfterConvert;

                    if (deleteOriginal)
                    {
                        RemoveFile(documentPath);
                    }

                    return pdfFilePath;
                }
            }
            catch (Exception)
            {
                // Nếu LibreOffice không có hoặc lỗi, thử các phương pháp khác
            }

            // Fallback: Nếu không convert được, trả về file gốc
            return documentPath;
        }

        /// <summary>
        /// Convert document sang PDF sử dụng LibreOffice
        /// </summary>
        /// <param name="inputPath">Đường dẫn file input</param>
        /// <param name="outputFolder">Thư mục output</param>
        /// <returns>True nếu convert thành công</returns>
        private async Task<bool> ConvertUsingLibreOffice(string inputPath, string outputFolder)
        {
            try
            {
                // Tìm LibreOffice executable
                var libreOfficePath = await FindLibreOfficeExecutable();
                if (string.IsNullOrEmpty(libreOfficePath))
                {
                    return false;
                }

                // LibreOffice command để convert sang PDF
                var arguments = $"--headless --convert-to pdf --outdir \"{outputFolder}\" \"{inputPath}\"";

                var processInfo = new ProcessStartInfo
                {
                    FileName = libreOfficePath,
                    Arguments = arguments,
                    RedirectStandardError = true,
                    RedirectStandardOutput = true,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    WorkingDirectory = outputFolder
                };

                using var process = Process.Start(processInfo);
                if (process != null)
                {
                    await process.WaitForExitAsync();
                    return process.ExitCode == 0;
                }

                return false;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// Tìm LibreOffice executable
        /// </summary>
        /// <returns>Đường dẫn LibreOffice hoặc null nếu không tìm thấy</returns>
        private async Task<string?> FindLibreOfficeExecutable()
        {
            // Kiểm tra cấu hình trước
            string? configuredPath = _appConfigService != null
                ? await _appConfigService.GetConfigValueAsync("Media.LibreOfficePath") ?? _settings.LibreOfficePath
                : _settings.LibreOfficePath;

            if (!string.IsNullOrEmpty(configuredPath) && File.Exists(configuredPath))
            {
                return configuredPath;
            }

            // Các đường dẫn phổ biến của LibreOffice
            var possiblePaths = new[]
            {
                @"C:\Program Files\LibreOffice\program\soffice.exe",
                @"C:\Program Files (x86)\LibreOffice\program\soffice.exe",
                @"C:\Program Files\LibreOffice 7.0\program\soffice.exe",
                @"C:\Program Files (x86)\LibreOffice 7.0\program\soffice.exe",
                @"C:\Program Files\LibreOffice 24.2\program\soffice.exe",
                @"C:\Program Files (x86)\LibreOffice 24.2\program\soffice.exe",
                "soffice", // Nếu có trong PATH
                "libreoffice" // Linux/Mac
            };

            foreach (var path in possiblePaths)
            {
                try
                {
                    if (File.Exists(path))
                    {
                        return path;
                    }
                }
                catch
                {
                    // Ignore và thử path tiếp theo
                }
            }

            return null;
        }

        /// <summary>
        /// Xóa file an toàn
        /// </summary>
        /// <param name="filePath">Đường dẫn file</param>
        private static void RemoveFile(string filePath)
        {
            try
            {
                if (File.Exists(filePath))
                {
                    File.Delete(filePath);
                }
            }
            catch (Exception)
            {
                // Log error if needed, but don't fail the process
            }
        }

        #endregion
    }
}
