using Common;
using Common.Constant;
using Common.Http;
using Common.Logic;
using Esim.Apis.DTO.Content;
using Esim.Apis.Singleton;
using Database.Database;
using log4net;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;

namespace Esim.Apis.Business
{
    public class ContentBusinessImpl : IContentBusiness
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(
            typeof(ContentBusinessImpl)
        );

        private ModelContext dbContext;
        IConfiguration configuration;

        public ContentBusinessImpl(ModelContext _dbContext, IConfiguration _configuration)
        {
            dbContext = _dbContext;
            configuration = _configuration;
        }

        public async Task<IActionResult> BannerLoad(HttpRequest httpRequest, BannerLoadReq request)
        {
            var url = httpRequest.Path;
            var json = JsonConvert.SerializeObject(request);
            log.Debug("URL: " + url + " => Request: " + json);
            try
            {
                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
                int pageNumber = request.pageNumber < 0 ? 0 : request.pageNumber;
                int pageSize = request.pageSize <= 0 ? 10 : request.pageSize;

                var query = dbContext.Banners
                    .Where(b => b.Status.HasValue && b.Status.Value)
                    .Where(b => b.StartDate == null || b.StartDate <= DateTime.Now)
                    .Where(b => b.EndDate == null || b.EndDate >= DateTime.Now);

                if (!string.IsNullOrEmpty(request.position))
                {
                    query = query.Where(b => b.Position == request.position);
                }

                int totalCount = query.Count();
                int totalPages = (int)Math.Ceiling((double)totalCount / pageSize);

                var banners = query
                    .OrderBy(b => b.DisplayOrder)
                    .ThenByDescending(b => b.CreatedDate)
                    .Skip(pageNumber * pageSize)
                    .Take(pageSize)
                    .Select(b => new
                    {
                        b.Id,
                        title = lang == "en" ? (b.TitleEn ?? b.Title)
                              : lang == "vi" ? b.Title
                              : (b.TitleLo ?? b.Title),
                        subtitle = lang == "en" ? (b.SubtitleEn ?? b.Subtitle)
                                 : lang == "vi" ? b.Subtitle
                                 : (b.SubtitleLo ?? b.Subtitle),
                        b.ImageUrl,
                        b.ImageMobileUrl,
                        b.LinkUrl,
                        b.LinkTarget,
                        b.Position,
                        b.DisplayOrder
                    })
                    .ToList();

                return DotnetLib.Http.HttpResponse.BuildResponse(
                    log, url, json,
                    CommonErrorCode.Success,
                    ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
                    new { banners = banners, pagination = new { pageNumber, pageSize, totalCount, totalPages } }
                );
            }
            catch (Exception ex)
            {
                log.Error("Exception: ", ex);
            }
            return DotnetLib.Http.HttpResponse.BuildResponse(
                log, url, json,
                CommonErrorCode.SystemError,
                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
                new { }
            );
        }

        public async Task<IActionResult> CustomerReviewLoad(HttpRequest httpRequest, CustomerReviewLoadReq request)
        {
            var url = httpRequest.Path;
            var json = JsonConvert.SerializeObject(request);
            log.Debug("URL: " + url + " => Request: " + json);
            try
            {
                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
                int pageNumber = request.pageNumber < 0 ? 0 : request.pageNumber;
                int pageSize = request.pageSize <= 0 ? 10 : request.pageSize;

                var query = dbContext.CustomerReviews
                    .Where(r => r.Status.HasValue && r.Status.Value);

                if (request.isFeatured.HasValue && request.isFeatured.Value)
                {
                    query = query.Where(r => r.IsFeatured.HasValue && r.IsFeatured.Value);
                }

                int totalCount = query.Count();
                int totalPages = (int)Math.Ceiling((double)totalCount / pageSize);

                var reviews = query
                    .OrderBy(r => r.DisplayOrder)
                    .ThenByDescending(r => r.CreatedDate)
                    .Skip(pageNumber * pageSize)
                    .Take(pageSize)
                    .Select(r => new
                    {
                        r.Id,
                        r.CustomerName,
                        r.AvatarUrl,
                        r.Rating,
                        reviewContent = lang == "en" ? (r.ReviewContentEn ?? r.ReviewContent)
                                      : lang == "vi" ? r.ReviewContent
                                      : (r.ReviewContentLo ?? r.ReviewContent),
                        destination = lang == "en" ? (r.DestinationEn ?? r.Destination)
                                    : lang == "vi" ? r.Destination
                                    : (r.DestinationLo ?? r.Destination),
                        r.IsFeatured,
                        r.CreatedDate
                    })
                    .ToList();

                return DotnetLib.Http.HttpResponse.BuildResponse(
                    log, url, json,
                    CommonErrorCode.Success,
                    ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
                    new { reviews = reviews, pagination = new { pageNumber, pageSize, totalCount, totalPages } }
                );
            }
            catch (Exception ex)
            {
                log.Error("Exception: ", ex);
            }
            return DotnetLib.Http.HttpResponse.BuildResponse(
                log, url, json,
                CommonErrorCode.SystemError,
                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
                new { }
            );
        }

        public async Task<IActionResult> CustomerReviewCreate(HttpRequest httpRequest, CustomerReviewCreateReq request)
        {
            var url = httpRequest.Path;
            var json = JsonConvert.SerializeObject(request);
            log.Debug("URL: " + url + " => Request: " + json);
            try
            {
                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);

                // Create new review (pending approval)
                var review = new CustomerReview
                {
                    CustomerName = request.customerName,
                    ReviewContent = request.reviewContent,
                    Destination = request.destination,
                    Rating = request.rating > 0 ? request.rating : 1,
                    Status = false, // Pending approval
                    IsFeatured = false,
                    CreatedDate = DateTime.Now
                };

                dbContext.CustomerReviews.Add(review);
                await dbContext.SaveChangesAsync();

                return DotnetLib.Http.HttpResponse.BuildResponse(
                    log, url, json,
                    CommonErrorCode.Success,
                    ConfigManager.Instance.GetConfigWebValue("REVIEW_SUBMITTED", lang),
                    new { reviewId = review.Id }
                );
            }
            catch (Exception ex)
            {
                log.Error("Exception: ", ex);
            }
            return DotnetLib.Http.HttpResponse.BuildResponse(
                log, url, json,
                CommonErrorCode.SystemError,
                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
                new { }
            );
        }

        public async Task<IActionResult> FaqCategoryLoad(HttpRequest httpRequest, FaqCategoryLoadReq request)
        {
            var url = httpRequest.Path;
            var json = JsonConvert.SerializeObject(request);
            log.Debug("URL: " + url + " => Request: " + json);
            try
            {
                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
                int pageNumber = request.pageNumber < 0 ? 0 : request.pageNumber;
                int pageSize = request.pageSize <= 0 ? 10 : request.pageSize;

                var query = dbContext.FaqCategories
                    .Where(c => c.Status.HasValue && c.Status.Value);

                int totalCount = query.Count();
                int totalPages = (int)Math.Ceiling((double)totalCount / pageSize);

                var categories = query
                    .OrderBy(c => c.DisplayOrder)
                    .ThenBy(c => c.Id)
                    .Skip(pageNumber * pageSize)
                    .Take(pageSize)
                    .Select(c => new
                    {
                        c.Id,
                        categoryName = lang == "en" ? (c.CategoryNameEn ?? c.CategoryName)
                                     : lang == "vi" ? c.CategoryName
                                     : (c.CategoryNameLo ?? c.CategoryName),
                        c.CategorySlug,
                        description = lang == "en" ? (c.DescriptionEn ?? c.Description)
                                    : lang == "vi" ? c.Description
                                    : (c.DescriptionLo ?? c.Description),
                        c.IconUrl,
                        c.DisplayOrder
                    })
                    .ToList();

                return DotnetLib.Http.HttpResponse.BuildResponse(
                    log, url, json,
                    CommonErrorCode.Success,
                    ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
                    new { categories = categories, pagination = new { pageNumber, pageSize, totalCount, totalPages } }
                );
            }
            catch (Exception ex)
            {
                log.Error("Exception: ", ex);
            }
            return DotnetLib.Http.HttpResponse.BuildResponse(
                log, url, json,
                CommonErrorCode.SystemError,
                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
                new { }
            );
        }

        public async Task<IActionResult> FaqLoad(HttpRequest httpRequest, FaqLoadReq request)
        {
            var url = httpRequest.Path;
            var json = JsonConvert.SerializeObject(request);
            log.Debug("URL: " + url + " => Request: " + json);
            try
            {
                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
                int pageNumber = request.pageNumber < 0 ? 0 : request.pageNumber;
                int pageSize = request.pageSize <= 0 ? 10 : request.pageSize;

                var query = dbContext.Faqs
                    .Where(f => f.Status == true);

                if (request.categoryId.HasValue)
                {
                    query = query.Where(f => f.CategoryId == request.categoryId);
                }

                if (request.isFeatured != null)
                {
                    query = query.Where(f => f.IsFeatured == request.isFeatured);
                }

                int totalCount = query.Count();
                int totalPages = (int)Math.Ceiling((double)totalCount / pageSize);

                var faqs = query
                    .OrderBy(f => f.DisplayOrder)
                    .ThenByDescending(f => f.ViewCount)
                    .Skip(pageNumber * pageSize)
                    .Take(pageSize)
                    .Select(f => new
                    {
                        f.Id,
                        question = lang == "en" ? (f.QuestionEn ?? f.Question)
                                 : lang == "vi" ? f.Question
                                 : (f.QuestionLo ?? f.Question),
                        answer = lang == "en" ? (f.AnswerEn ?? f.Answer)
                               : lang == "vi" ? f.Answer
                               : (f.AnswerLo ?? f.Answer),
                        f.CategoryId,
                        f.ViewCount,
                        f.IsFeatured
                    })
                    .ToList();

                return DotnetLib.Http.HttpResponse.BuildResponse(
                    log, url, json,
                    CommonErrorCode.Success,
                    ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
                    new { faqs = faqs, pagination = new { pageNumber, pageSize, totalCount, totalPages } }
                );
            }
            catch (Exception ex)
            {
                log.Error("Exception: ", ex);
            }
            return DotnetLib.Http.HttpResponse.BuildResponse(
                log, url, json,
                CommonErrorCode.SystemError,
                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
                new { }
            );
        }

        /// <summary>
        /// Load device eSIM compatibility list
        /// </summary>
        public async Task<IActionResult> DeviceCompatibilityLoad(HttpRequest httpRequest, DeviceCompatibilityReq request)
        {
            var url = httpRequest.Path;
            var json = JsonConvert.SerializeObject(request);
            log.Debug("URL: " + url + " => Request: " + json);
            try
            {
                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
                int pageNumber = request.pageNumber < 0 ? 0 : request.pageNumber;
                int pageSize = request.pageSize <= 0 ? 50 : request.pageSize;

                // Base query - only active devices
                var query = dbContext.DeviceEsimCompatibilities
                    .Where(d => d.Status.HasValue && d.Status.Value && d.SupportsEsim.HasValue && d.SupportsEsim.Value);

                // Filter by brand
                if (!string.IsNullOrEmpty(request.brand))
                {
                    query = query.Where(d => d.Brand == request.brand);
                }

                // Filter by category
                if (!string.IsNullOrEmpty(request.category))
                {
                    query = query.Where(d => d.Category == request.category);
                }

                // Filter by popular flag
                if (request.isPopular.HasValue && request.isPopular.Value)
                {
                    query = query.Where(d => d.IsPopular.HasValue && d.IsPopular.Value);
                }

                // Search by keyword in model name (all language variants)
                if (!string.IsNullOrEmpty(request.searchKeyword))
                {
                    var keyword = request.searchKeyword.ToLower();
                    query = query.Where(d =>
                        d.ModelName.ToLower().Contains(keyword) ||
                        (d.ModelNameEn != null && d.ModelNameEn.ToLower().Contains(keyword)) ||
                        (d.ModelNameLo != null && d.ModelNameLo.ToLower().Contains(keyword))
                    );
                }

                // Get total count for pagination
                int totalCount = query.Count();
                int totalPages = (int)Math.Ceiling((double)totalCount / pageSize);

                // Apply pagination and ordering
                var devices = query
                    .OrderBy(d => d.DisplayOrder)
                    .ThenBy(d => d.Brand)
                    .ThenBy(d => d.ModelName)
                    .Skip(pageNumber * pageSize)
                    .Take(pageSize)
                    .Select(d => new
                    {
                        d.Id,
                        d.Brand,
                        modelName = lang == "en" ? (d.ModelNameEn ?? d.ModelName)
                                  : lang == "vi" ? d.ModelName
                                  : (d.ModelNameLo ?? d.ModelName),
                        d.Category,
                        notes = lang == "en" ? (d.NotesEn ?? d.Notes)
                              : lang == "vi" ? d.Notes
                              : (d.NotesLo ?? d.Notes),
                        supportsEsim = d.SupportsEsim ?? true,
                        isPopular = d.IsPopular ?? false,
                        displayOrder = d.DisplayOrder ?? 999
                    })
                    .ToList();

                return DotnetLib.Http.HttpResponse.BuildResponse(
                    log, url, json,
                    CommonErrorCode.Success,
                    ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
                    new
                    {
                        devices = devices,
                        pagination = new
                        {
                            pageNumber,
                            pageSize,
                            totalCount,
                            totalPages
                        }
                    }
                );
            }
            catch (Exception exception)
            {
                log.Error("Exception: ", exception);
            }
            return DotnetLib.Http.HttpResponse.BuildResponse(
                log, url, json,
                CommonErrorCode.SystemError,
                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
                new { }
            );
        }

        /// <summary>
        /// Get list of device brands and categories (for filters/tabs)
        /// </summary>
        public async Task<IActionResult> GetDeviceBrandsAndCategories(HttpRequest httpRequest)
        {
            var url = httpRequest.Path;
            log.Debug("URL: " + url);
            try
            {
                // Get language from header
                string lang = CommonLogic.GetLanguage(httpRequest);

                // Get all active devices for client-side filtering
                var allDevices = dbContext.DeviceEsimCompatibilities
                    .Where(d => d.Status.HasValue && d.Status.Value && d.SupportsEsim.HasValue && d.SupportsEsim.Value)
                    .OrderBy(d => d.DisplayOrder)
                    .ThenBy(d => d.ModelName)
                    .ToList();

                // Group devices by brand and include full device list
                var brands = allDevices
                    .GroupBy(d => d.Brand)
                    .Select(g => new
                    {
                        brand = g.Key,
                        deviceCount = g.Count(),
                        popularCount = g.Count(d => d.IsPopular.HasValue && d.IsPopular.Value),
                        devices = g.Select(d => new
                        {
                            d.Id,
                            modelName = lang == "en" ? (d.ModelNameEn ?? d.ModelName)
                                      : lang == "vi" ? d.ModelName
                                      : (d.ModelNameLo ?? d.ModelName),
                            d.Category,
                            d.IsPopular,
                            d.DisplayOrder,
                            notes = lang == "en" ? (d.NotesEn ?? d.Notes)
                                  : lang == "vi" ? d.Notes
                                  : (d.NotesLo ?? d.Notes)
                        }).ToList()
                    })
                    .OrderBy(b => b.brand)
                    .ToList();

                // Get distinct categories with device count
                var categories = allDevices
                    .GroupBy(d => d.Category)
                    .Select(g => new
                    {
                        category = g.Key,
                        deviceCount = g.Count()
                    })
                    .OrderBy(c => c.category)
                    .ToList();

                return DotnetLib.Http.HttpResponse.BuildResponse(
                    log, url, "",
                    CommonErrorCode.Success,
                    ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
                    new
                    {
                        brands = brands,
                        categories = categories
                    }
                );
            }
            catch (Exception exception)
            {
                log.Error("Exception: ", exception);
            }
            return DotnetLib.Http.HttpResponse.BuildResponse(
                log, url, "",
                CommonErrorCode.SystemError,
                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
                new { }
            );
        }

    }
}
