using Lada.Framework.Data.Domains.ErrorReports;
using Lada.Framework.Data.Enums;
using Lada.Framework.Data.Repositories;
using Lada.Framework.DTO;
using Lada.Framework.DTO.SmartTable;
using Lada.Framework.Infrastructures.Helpers;
using Lada.Framework.Infrastructures.Services;
using Ladaer.BackEnd.Infrastructures.DTO.Items.ErrorReports;
using Ladaer.BackEnd.Infrastructures.DTO.Models.ErrorReports;
using Ladaer.BackEnd.Infrastructures.DTO.Results.ErrorReports;
using Ladaer.BackEnd.Infrastructures.Extensions;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel;

namespace Ladaer.BackEnd.Infrastructures.Services.ErrorReports
{
    public interface IErrorReportService
    {
        /// <summary>
        /// Tìm kiếm báo lỗi
        /// </summary>
        /// <param name="param">Tham số tìm kiếm</param>
        /// <returns>Danh sách báo lỗi</returns>
        Task<SmartTableResult<ErrorReportItem>> Search(SmartTableParam param);

        /// <summary>
        /// Tạo mới báo lỗi
        /// </summary>
        /// <param name="model">Thông tin báo lỗi</param>
        /// <returns>Kết quả tạo báo lỗi</returns>
        Task<ErrorReportResult> Create(ErrorReportModel model);

        /// <summary>
        /// Lấy chi tiết báo lỗi
        /// </summary>
        /// <param name="id">ID báo lỗi</param>
        /// <returns>Chi tiết báo lỗi</returns>
        Task<ErrorReportDetailResult> GetById(int id);

        /// <summary>
        /// Cập nhật trạng thái báo lỗi (dành cho admin)
        /// </summary>
        /// <param name="model">Thông tin cập nhật</param>
        /// <returns>Kết quả cập nhật</returns>
        Task<ErrorReportUpdateResult> UpdateStatus(ErrorReportUpdateModel model);

        /// <summary>
        /// Xóa báo lỗi
        /// </summary>
        /// <param name="id">ID báo lỗi</param>
        /// <returns>Kết quả xóa</returns>
        Task<BaseResult> Delete(int id);

        /// <summary>
        /// Lấy danh sách báo lỗi theo trạng thái
        /// </summary>
        /// <param name="status">Trạng thái</param>
        /// <param name="pageIndex">Trang hiện tại</param>
        /// <param name="pageSize">Kích thước trang</param>
        /// <returns>Danh sách báo lỗi</returns>
        Task<ErrorReportListResult> GetByStatus(ErrorReportStatus status, int pageIndex = 1, int pageSize = 20);
    }

    public class ErrorReportService : IErrorReportService
    {
        private readonly IRepository<ErrorReport> _errorReportRepository;
        private readonly IRepository<ErrorReportMedia> _errorReportMediaRepository;
        private readonly IUnifiedMediaService _mediaService;

        public ErrorReportService(
            IRepository<ErrorReport> errorReportRepository,
            IRepository<ErrorReportMedia> errorReportMediaRepository,
            IUnifiedMediaService mediaService)
        {
            _errorReportRepository = errorReportRepository;
            _errorReportMediaRepository = errorReportMediaRepository;
            _mediaService = mediaService;
        }

        public async Task<SmartTableResult<ErrorReportItem>> Search(SmartTableParam param)
        {
            var query = _errorReportRepository.Query();

            // Xử lý tìm kiếm
            if (param.Search?.PredicateObject != null)
            {
                dynamic search = param.Search.PredicateObject;

                // Tìm kiếm theo từ khóa
                if (search.Keyword != null)
                {
                    string keyword = search.Keyword;
                    keyword = keyword.Trim().ToLower();
                    if (!string.IsNullOrWhiteSpace(keyword))
                    {
                        query = query.Where(er =>
                            er.Url.ToLower().Contains(keyword) ||
                            er.ErrorDescription.ToLower().Contains(keyword) ||
                            er.ReporterName.ToLower().Contains(keyword) ||
                            er.ReporterEmail.ToLower().Contains(keyword));
                    }
                }

                // Lọc theo trạng thái
                if (search.Status != null)
                {
                    int statusValue = search.Status;
                    var status = (ErrorReportStatus)statusValue;
                    query = query.Where(er => er.Status == status);
                }

                // Lọc theo ngày tạo
                if (search.CreatedStart != null && search.CreatedEnd != null)
                {
                    DateTimeOffset start = search.CreatedStart;
                    DateTimeOffset end = search.CreatedEnd;
                    // Chuyển từ UTC sang local time (GMT+7) và lấy đầu/cuối ngày
                    DateTimeOffset startParam = start.ToLocalTime().StartOfDay();
                    DateTimeOffset endParam = end.ToLocalTime().EndOfDay();
                    query = query.Where(er => er.CreatedTime >= startParam && er.CreatedTime <= endParam);
                }
            }

            // Sắp xếp mặc định
            if (param.Sort == null)
            {
                param.Sort = new Lada.Framework.DTO.SmartTable.Sort { Predicate = "CreatedTime", Reverse = true };
            }

            // Sử dụng extension method để xử lý phân trang và sắp xếp
            var result = await query
                .Include(er => er.ErrorReportMedias).ToSmartTableResultAsync(param, er => new ErrorReportItem
                {
                    Id = er.Id,
                    Url = er.Url,
                    ErrorDescription = er.ErrorDescription,
                    Status = er.Status,
                    StatusDisplay = er.Status.GetDescription(),
                    AdminNote = er.AdminNote,
                    ReportedByUserId = er.ReportedByUserId,
                    ReporterName = er.ReporterName,
                    ReporterEmail = er.ReporterEmail,
                    ReporterPhone = er.ReporterPhone,
                    BrowserInfo = er.BrowserInfo,
                    DeviceInfo = er.DeviceInfo,
                    CreatedTime = er.CreatedTime,
                    UpdatedTime = er.UpdatedTime,
                    CreatedBy = er.CreatedBy,
                    CreatedByUserName = er.CreatedByUserName,
                    UpdatedBy = er.UpdatedBy,
                    UpdatedByUserName = er.UpdatedByUserName,
                    MediaItems = er.ErrorReportMedias?.Select(erm => new ErrorReportMediaItem
                    {
                        Id = erm.Id,
                        ErrorReportId = erm.ErrorReportId,
                        ImageUrl = GetImageUrl(erm.SystemPath),
                        OriginalFileName = erm.OriginalFileName,
                        FileSize = erm.FileSize,
                        FileSizeDisplay = FormatFileSize(erm.FileSize),
                        ContentType = erm.ContentType,
                        Description = erm.Description,
                        DisplayOrder = erm.DisplayOrder,
                        CreatedTime = erm.CreatedTime,
                        UpdatedTime = erm.UpdatedTime
                    }).OrderBy(m => m.DisplayOrder).ToList() ?? new List<ErrorReportMediaItem>()
                });

            return result;
        }

        private string GetImageUrl(string systemPath)
        {
            if (string.IsNullOrEmpty(systemPath))
                return string.Empty;

            // Chuyển đổi đường dẫn vật lý thành URL
            // Cần implement logic chuyển đổi phù hợp với cấu hình hệ thống
            return systemPath.Replace("\\", "/");
        }

        private string FormatFileSize(long bytes)
        {
            string[] sizes = { "B", "KB", "MB", "GB" };
            double len = bytes;
            int order = 0;
            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len = len / 1024;
            }
            return $"{len:0.##} {sizes[order]}";
        }

        public async Task<ErrorReportResult> Create(ErrorReportModel model)
        {
            var result = new ErrorReportResult();
            var currentTime = DateTimeHelper.CurrentTime();

            try
            {
                // Tạo entity ErrorReport
                var errorReport = new ErrorReport
                {
                    Url = model.Url,
                    ErrorDescription = model.ErrorDescription,
                    Status = ErrorReportStatus.New,
                    ReporterName = model.ReporterName,
                    ReporterEmail = model.ReporterEmail,
                    ReporterPhone = model.ReporterPhone,
                    BrowserInfo = model.BrowserInfo,
                    DeviceInfo = model.DeviceInfo,
                    CreatedTime = currentTime,
                    UpdatedTime = currentTime,
                    // TODO: Lấy thông tin user hiện tại nếu đã đăng nhập
                    // ReportedByUserId = User.GetCurrentUserId(),
                    CreatedBy = 0, // TODO: Lấy từ context
                    CreatedByUserName = model.ReporterName,
                    UpdatedBy = 0,
                    UpdatedByUserName = model.ReporterName
                };

                await _errorReportRepository.InsertAsync(errorReport);

                // Xử lý upload hình ảnh
                if (model.Images != null && model.Images.Any())
                {
                    var mediaItems = new List<ErrorReportMedia>();
                    int displayOrder = 1;

                    foreach (var image in model.Images)
                    {
                        if (image.Length > 0)
                        {
                            // TODO: Sử dụng MediaService để upload hình ảnh
                            // var uploadResult = await _mediaService.UploadImageAsync(image, "error-reports");

                            // Tạm thời tạo đường dẫn giả
                            var fileName = $"{Guid.NewGuid()}_{image.FileName}";
                            var systemPath = Path.Combine("uploads", "error-reports", fileName);

                            var mediaItem = new ErrorReportMedia
                            {
                                ErrorReportId = errorReport.Id,
                                SystemPath = systemPath,
                                OriginalFileName = image.FileName,
                                FileSize = image.Length,
                                ContentType = image.ContentType,
                                DisplayOrder = displayOrder++,
                                CreatedTime = currentTime,
                                UpdatedTime = currentTime,
                                CreatedBy = 0,
                                CreatedByUserName = model.ReporterName,
                                UpdatedBy = 0,
                                UpdatedByUserName = model.ReporterName
                            };

                            mediaItems.Add(mediaItem);
                        }
                    }

                    if (mediaItems.Any())
                    {
                        await _errorReportMediaRepository.InsertAsync(mediaItems);
                    }
                }

                result.Id = errorReport.Id;
                result.Result = Result.Success;
                result.Message = "Báo lỗi đã được tạo thành công";
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = ex.Message;
            }

            return result;
        }

        public async Task<ErrorReportDetailResult> GetById(int id)
        {
            var result = new ErrorReportDetailResult();

            try
            {
                var errorReport = await _errorReportRepository.Query()
                    .Include(er => er.ErrorReportMedias)
                    .FirstOrDefaultAsync(er => er.Id == id);

                if (errorReport == null)
                {
                    result.Result = Result.Failed;
                    result.Message = "Không tìm thấy báo lỗi";
                    return result;
                }

                result.ErrorReport = new ErrorReportItem
                {
                    Id = errorReport.Id,
                    Url = errorReport.Url,
                    ErrorDescription = errorReport.ErrorDescription,
                    Status = errorReport.Status,
                    StatusDisplay = errorReport.Status.GetDescription(),
                    AdminNote = errorReport.AdminNote,
                    ReportedByUserId = errorReport.ReportedByUserId,
                    ReporterName = errorReport.ReporterName,
                    ReporterEmail = errorReport.ReporterEmail,
                    ReporterPhone = errorReport.ReporterPhone,
                    BrowserInfo = errorReport.BrowserInfo,
                    DeviceInfo = errorReport.DeviceInfo,
                    CreatedTime = errorReport.CreatedTime,
                    UpdatedTime = errorReport.UpdatedTime,
                    CreatedBy = errorReport.CreatedBy,
                    CreatedByUserName = errorReport.CreatedByUserName,
                    UpdatedBy = errorReport.UpdatedBy,
                    UpdatedByUserName = errorReport.UpdatedByUserName,
                    MediaItems = errorReport.ErrorReportMedias?.Select(erm => new ErrorReportMediaItem
                    {
                        Id = erm.Id,
                        ErrorReportId = erm.ErrorReportId,
                        ImageUrl = GetImageUrl(erm.SystemPath),
                        OriginalFileName = erm.OriginalFileName,
                        FileSize = erm.FileSize,
                        FileSizeDisplay = FormatFileSize(erm.FileSize),
                        ContentType = erm.ContentType,
                        Description = erm.Description,
                        DisplayOrder = erm.DisplayOrder,
                        CreatedTime = erm.CreatedTime,
                        UpdatedTime = erm.UpdatedTime
                    }).OrderBy(m => m.DisplayOrder).ToList() ?? new List<ErrorReportMediaItem>()
                };

                result.Result = Result.Success;
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = ex.Message;
            }

            return result;
        }

        public async Task<ErrorReportUpdateResult> UpdateStatus(ErrorReportUpdateModel model)
        {
            var result = new ErrorReportUpdateResult();
            var currentTime = DateTimeHelper.CurrentTime();

            try
            {
                var errorReport = await _errorReportRepository.GetByIdAsync(model.Id);
                if (errorReport == null)
                {
                    result.Result = Result.Failed;
                    result.Message = "Không tìm thấy báo lỗi";
                    return result;
                }

                errorReport.Status = model.Status;
                errorReport.AdminNote = model.AdminNote;
                errorReport.UpdatedTime = currentTime;
                // TODO: Lấy thông tin admin hiện tại
                // errorReport.UpdatedBy = User.GetCurrentUserId();
                // errorReport.UpdatedByUserName = User.GetCurrentUserName();

                await _errorReportRepository.UpdateAsync(errorReport);

                result.ErrorReportId = errorReport.Id;
                result.Result = Result.Success;
                result.Message = "Cập nhật trạng thái báo lỗi thành công";
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = ex.Message;
            }

            return result;
        }

        public async Task<BaseResult> Delete(int id)
        {
            var result = new BaseResult();

            try
            {
                var errorReport = await _errorReportRepository.GetByIdAsync(id);
                if (errorReport == null)
                {
                    result.Result = Result.Failed;
                    result.Message = "Không tìm thấy báo lỗi";
                    return result;
                }

                // Xóa các media liên quan
                var mediaItems = await _errorReportMediaRepository.Query()
                    .Where(erm => erm.ErrorReportId == id)
                    .ToListAsync();

                if (mediaItems.Any())
                {
                    // TODO: Xóa file vật lý
                    foreach (var media in mediaItems)
                    {
                        if (File.Exists(media.SystemPath))
                        {
                            File.Delete(media.SystemPath);
                        }
                    }

                    await _errorReportMediaRepository.DeleteAsync(mediaItems);
                }

                await _errorReportRepository.DeleteAsync(errorReport);

                result.Result = Result.Success;
                result.Message = "Xóa báo lỗi thành công";
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = ex.Message;
            }

            return result;
        }

        public async Task<ErrorReportListResult> GetByStatus(ErrorReportStatus status, int pageIndex = 1, int pageSize = 20)
        {
            var result = new ErrorReportListResult();

            try
            {
                var query = _errorReportRepository.Query()
                    .Include(er => er.ErrorReportMedias)
                    .Where(er => er.Status == status)
                    .OrderByDescending(er => er.CreatedTime);

                var totalCount = await query.CountAsync();
                var items = await query
                    .Skip((pageIndex - 1) * pageSize)
                    .Take(pageSize)
                    .ToListAsync();

                result.ErrorReports = items.Select(er => new ErrorReportItem
                {
                    Id = er.Id,
                    Url = er.Url,
                    ErrorDescription = er.ErrorDescription,
                    Status = er.Status,
                    StatusDisplay = er.Status.GetDescription(),
                    AdminNote = er.AdminNote,
                    ReportedByUserId = er.ReportedByUserId,
                    ReporterName = er.ReporterName,
                    ReporterEmail = er.ReporterEmail,
                    ReporterPhone = er.ReporterPhone,
                    BrowserInfo = er.BrowserInfo,
                    DeviceInfo = er.DeviceInfo,
                    CreatedTime = er.CreatedTime,
                    UpdatedTime = er.UpdatedTime,
                    CreatedBy = er.CreatedBy,
                    CreatedByUserName = er.CreatedByUserName,
                    UpdatedBy = er.UpdatedBy,
                    UpdatedByUserName = er.UpdatedByUserName,
                    MediaItems = er.ErrorReportMedias?.Select(erm => new ErrorReportMediaItem
                    {
                        Id = erm.Id,
                        ErrorReportId = erm.ErrorReportId,
                        ImageUrl = GetImageUrl(erm.SystemPath),
                        OriginalFileName = erm.OriginalFileName,
                        FileSize = erm.FileSize,
                        FileSizeDisplay = FormatFileSize(erm.FileSize),
                        ContentType = erm.ContentType,
                        Description = erm.Description,
                        DisplayOrder = erm.DisplayOrder
                    }).OrderBy(m => m.DisplayOrder).ToList() ?? new List<ErrorReportMediaItem>()
                }).ToList();

                result.TotalCount = totalCount;
                result.CurrentPage = pageIndex;
                result.PageSize = pageSize;
                result.Result = Result.Success;
            }
            catch (Exception ex)
            {
                result.Result = Result.SystemError;
                result.Message = ex.Message;
            }

            return result;
        }
    }
}
