using Lada.Framework.Data.Domains.Cms;
using Lada.Framework.DTO.SmartTable;
using Lada.Framework.DTO;
using Lada.Framework.Infrastructures.Helpers;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Cms;
using Lada.Framework.Data.Mappings.DbContexts;
using Lada.Framework.Data.Domains;
using Lada.Framework.Data.Repositories;
using Ladaer.BackEnd.Infrastructures.DTO;
using Microsoft.EntityFrameworkCore;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Cms;
using Ladaer.BackEnd.Infrastructures.DTO.Results.Cms;
using Lada.Framework.Data.Enums;

namespace Ladaer.BackEnd.Infrastructures.Services.Cms
{
    /// <summary>
    /// Giao diện cho dịch vụ quản lý UrlRecord.
    /// </summary>
    public interface IUrlRecordService
    {
        /// <summary>
        /// Lấy thông tin bài viết qua Id.
        /// </summary>
        /// <param name="postId">Id của bài viết.</param>
        /// <returns>Thông tin UrlRecord của bài viết.</returns>
        Task<UrlRecordModel> GetByPostId(int postId);

        /// <summary>
        /// Tạo hoặc cập nhật UrlRecord.
        /// </summary>
        /// <param name="model">Thông tin UrlRecord.</param>
        /// <returns>Kết quả của thao tác.</returns>
        Task<BaseResult> Update(UrlRecordModel model);

        /// <summary>
        /// Tạo slug cho UrlRecord.
        /// </summary>
        /// <param name="slug">Slug cần tạo.</param>
        /// <returns>Slug đã được tạo.</returns>
        Task<string> GenerateUrlRecord(string slug);

        /// <summary>
        /// Tạo slug cho UrlRecord với loại thực thể.
        /// </summary>
        /// <param name="slug">Slug cần tạo.</param>
        /// <param name="urlEntityType">Loại thực thể của UrlRecord.</param>
        /// <returns>Slug đã được tạo.</returns>
        Task<string> GenerateUrlRecord(string slug, UrlEntityType urlEntityType, int currentId = 0);

        /// <summary>
        /// Lấy UrlRecord theo slug.
        /// </summary>
        /// <param name="slug">Slug của UrlRecord.</param>
        /// <returns>Thông tin UrlRecord.</returns>
        Task<UrlRecord> GetUrlRecordBySlug(string slug);

        Task<string> GenerateUrlRecord(string slug, int? currentId);



        /// <summary>
        /// Thêm mới UrlRecord.
        /// </summary>
        /// <param name="urlRecord">Thông tin UrlRecord.</param>
        /// <returns>Kết quả của thao tác.</returns>
        Task<BaseResult> Add(UrlRecord urlRecord);



        /// <summary>
        /// Tìm kiếm UrlRecord.
        /// </summary>
        /// <param name="param">Thông số tìm kiếm.</param>
        /// <returns>Kết quả tìm kiếm UrlRecord.</returns>
        Task<SmartTableResult<UrlRecordItem>> Search(SmartTableParam param);

        /// <summary>
        /// Lấy thông tin UrlRecord theo Id.
        /// </summary>
        /// <param name="id">Id của UrlRecord.</param>
        /// <returns>Thông tin UrlRecord.</returns>
        Task<UrlRecordModel> GetById(int id);

        /// <summary>
        /// Tạo hoặc cập nhật UrlRecord.
        /// </summary>
        /// <param name="urlRecordModel">Thông tin UrlRecord.</param>
        /// <returns>Kết quả của thao tác.</returns>
        Task<UrlRecordResult> CreateOrUpdate(UrlRecordModel urlRecordModel);

        Task<UrlRecordModel> GetByEntityAsync(int id, UrlEntityType entityType);

        /// <summary>
        /// Cập nhật thông tin cơ bản của UrlRecord.
        /// </summary>
        /// <param name="model">Model chứa thông tin cập nhật UrlRecord.</param>
        /// <returns>Kết quả của thao tác.</returns>
        Task<BaseResult> UpdateUrlRecordInfo(UrlRecordUpdateModel model);

    }
    /// <summary>
    /// Triển khai dịch vụ quản lý UrlRecord.
    /// </summary>
    public class UrlRecordService : IUrlRecordService
    {
        private readonly IRepository<UrlRecord> _urlRecordRepository;

        /// <summary>
        /// Khởi tạo một thể hiện của <see cref="UrlRecordService"/>.
        /// </summary>
        /// <param name="urlRecordRepository">Đối tượng IRepository của UrlRecord.</param>
        public UrlRecordService(IRepository<UrlRecord> urlRecordRepository)
        {
            _urlRecordRepository = urlRecordRepository;
        }

        /// <summary>
        /// Tạo hoặc cập nhật UrlRecord.
        /// </summary>
        /// <param name="model">Thông tin UrlRecord.</param>
        /// <returns>Kết quả của thao tác.</returns>
        public async Task<BaseResult> Update(UrlRecordModel model)
        {
            var urlRecord = model.ToEntity();
            var result = new BaseResult() { Result = Result.Success };
            var urlRecordForUpdate = _urlRecordRepository.Query().FirstOrDefault(c => c.Id == urlRecord.Id);
            if (urlRecordForUpdate == null || urlRecord.Id <= 0)
            {
                result.Result = Result.Failed;
                result.Message = "Không tìm thấy bài viết yêu cầu!";
                return result;
            }

            try
            {
                // Cập nhật thông tin của bài viết
                urlRecordForUpdate.MetaTitle = urlRecord.MetaTitle.Trim();
                urlRecordForUpdate.MetaDescription = urlRecord.MetaDescription.Trim();
                urlRecordForUpdate.MetaKeywords = urlRecord.MetaKeywords;

                // Cập nhật thông tin chung của thực thể
                urlRecordForUpdate = urlRecordForUpdate.UpdateCommonInt();
                await _urlRecordRepository.UpdateAsync(urlRecordForUpdate);
            }
            catch (Exception e)
            {
                result.Result = Result.SystemError;
                result.Message = e.ToString();
            }

            return result;
        }

        /// <summary>
        /// Lấy thông tin bài viết qua Id.
        /// </summary>
        /// <param name="postId">Id của bài viết.</param>
        /// <returns>Thông tin UrlRecord của bài viết.</returns>
        public async Task<UrlRecordModel> GetByPostId(int postId)
        {
            var model = new UrlRecordModel();
            if (postId <= 0) return model;
            var urlRecord = await _urlRecordRepository.Query().FirstOrDefaultAsync(c => c.PostId == postId && c.EntityName == "Post");
            if (urlRecord != null && urlRecord.Id > 0)
            {
                model = urlRecord.ToModel();
            }
            return model;
        }


        public async Task<UrlRecordModel> GetByEntityAsync(int id, UrlEntityType entityType)
        {
            var model = new UrlRecordModel();
            if (id <= 0) return model;

            IQueryable<UrlRecord> query = _urlRecordRepository.Query();

            switch (entityType)
            {
                case UrlEntityType.Post:
                    query = query.Where(x => x.PostId == id && x.EntityName == "Post");
                    break;
                case UrlEntityType.Tag:
                    query = query.Where(x => x.TagId == id && x.EntityName == "Tag");
                    break;
                case UrlEntityType.Category:
                    query = query.Where(x => x.CategoryId == id && x.EntityName == "Category");
                    break;
                case UrlEntityType.Topic:
                    query = query.Where(x => x.TopicId == id && x.EntityName == "Topic");
                    break;
                case UrlEntityType.Product:
                    query = query.Where(x => x.ProductId == id && x.EntityName == "Product");
                    break;
                case UrlEntityType.JobPost:
                    query = query.Where(x => x.JobPostId == id && x.EntityName == "JobPost");
                    break;
                default:
                    return null;
            }
            var urlRecord = await query.FirstOrDefaultAsync();
            if (urlRecord != null && urlRecord.Id > 0)
            {
                model = urlRecord.ToModel();
            }
            return model;
        }

        /// <summary>
        /// Tạo slug cho UrlRecord.
        /// </summary>
        /// <param name="slug">Slug cần tạo.</param>
        /// <returns>Slug đã được tạo.</returns>
        public async Task<string> GenerateUrlRecord(string slug)
        {
            var urlRecords = await _urlRecordRepository.QueryAll().Where(u => u.Slug == slug).ToListAsync();
            if (urlRecords.Count > 0)
            {
                var count = urlRecords.Count;
                return slug += "-" + count;
            }
            else return slug;
        }

        /// <summary>
        /// Tạo slug cho UrlRecord.
        /// </summary>
        /// <param name="slug">Slug cần tạo.</param>
        /// <returns>Slug đã được tạo.</returns>
        public async Task<string> GenerateUrlRecord(string slug, int? currentId)
        {
            var query = _urlRecordRepository.QueryAll().Where(u => u.Slug == slug);
            if (currentId.HasValue && currentId.Value > 0)
            {
                query = query.Where(u => u.Id != currentId);
            }


            var urlRecords = await query.ToListAsync();
            if (urlRecords.Count > 0)
            {
                var count = urlRecords.Count;
                return slug += "-" + count;
            }
            else return slug;
        }

        /// <summary>
        /// Tạo slug cho UrlRecord với loại thực thể.
        /// </summary>
        /// <param name="slug">Slug cần tạo.</param>
        /// <param name="urlEntityType">Loại thực thể của UrlRecord.</param>
        /// <param name="currentId">UrlRecordId hiện tại</param>
        /// <returns>Slug đã được tạo.</returns>
        public async Task<string> GenerateUrlRecord(string slug, UrlEntityType urlEntityType, int currentId = 0)
        {
            var slugPrefix = "";
            switch (urlEntityType)
            {
                case UrlEntityType.Post:
                    slugPrefix = "";
                    break;
                case UrlEntityType.Tag:
                    slugPrefix = "tu-khoa/";
                    break;
                case UrlEntityType.Category:
                    slugPrefix = "chuyen-muc/";
                    break;
                case UrlEntityType.Topic:
                    slugPrefix = "";
                    break;
                case UrlEntityType.Product:
                    slugPrefix = "dich-vu/";
                    break;
                case UrlEntityType.JobPost:
                    slugPrefix = "tuyen-dung/";
                    break;

                default:
                    slugPrefix = "";
                    break;
            }
            slug = slugPrefix + slug;
            var query = _urlRecordRepository.QueryAll().Where(u => u.Slug == slug);
            if (currentId > 0)
            {
                query = query.Where(u => u.Id != currentId);
            }
            var urlRecords = await query.ToListAsync();
            if (urlRecords.Count > 0)
            {
                var count = urlRecords.Count;
                return slug += "-" + count;
            }
            else return slug;
        }

        /// <summary>
        /// Lấy UrlRecord theo slug.
        /// </summary>
        /// <param name="slug">Slug của UrlRecord.</param>
        /// <returns>Thông tin UrlRecord.</returns>
        public async Task<UrlRecord> GetUrlRecordBySlug(string slug)
        {
            var urlRecord = await _urlRecordRepository.Query().FirstOrDefaultAsync(u => u.Slug == slug);
            if (urlRecord != null && urlRecord.Id > 0)
            {
                return urlRecord;
            }
            else
            {
                return new UrlRecord();
            }
        }

        /// <summary>
        /// Thêm mới UrlRecord.
        /// </summary>
        /// <param name="urlRecord">Thông tin UrlRecord.</param>
        /// <returns>Kết quả của thao tác.</returns>
        public async Task<BaseResult> Add(UrlRecord urlRecord)
        {
            var result = new BaseResult();
            try
            {
                // Cập nhật thông tin chung của thực thể
                urlRecord = urlRecord.UpdateCommonInt();
                await _urlRecordRepository.InsertAsync(urlRecord);
            }
            catch (Exception e)
            {
                result.Result = Result.SystemError;
                result.Message = e.ToString();
            }

            return result;
        }

        /// <summary>
        /// Tìm kiếm UrlRecord.
        /// </summary>
        /// <param name="param">Thông số tìm kiếm.</param>
        /// <returns>Kết quả tìm kiếm UrlRecord.</returns>
        public async Task<SmartTableResult<UrlRecordItem>> Search(SmartTableParam param)
        {
            var query = _urlRecordRepository.Query();
            if (param.Search.PredicateObject != null)
            {
                dynamic search = param.Search.PredicateObject;
                if (search.Keyword != null)
                {
                    string keyword = search.Keyword;
                    keyword = keyword.Trim().ToLower();
                    query = query.Where(x => x.Slug.ToLower().Contains(keyword) || x.MetaTitle.ToLower().Contains(keyword)
                    || x.MetaDescription.ToLower().Contains(keyword) || x.MetaKeywords.ToLower().Contains(keyword));
                }
                if (search.CreatedStart != null && search.CreatedEnd != null)
                {
                    DateTimeOffset start = search.CreatedStart;
                    DateTimeOffset end = search.CreatedEnd;
                    DateTimeOffset startParam = start.StartOfDay();
                    DateTimeOffset endParam = end.EndOfDay();
                    query = query.Where(x => (x.CreatedTime >= startParam) && (x.CreatedTime <= endParam));
                }
                if (search.EntityType != null)
                {
                    int entityType = search.EntityType;
                    string entityName = "";
                    switch (entityType)
                    {
                        case 1: entityName = "Post"; break;
                        case 2: entityName = "Tag"; break;
                        case 3: entityName = "Category"; break;
                        case 4: entityName = "Topic"; break;
                        case 5: entityName = "Product"; break;
                        case 6: entityName = "JobPost"; break;
                    }
                    if (!string.IsNullOrEmpty(entityName))
                        query = query.Where(x => x.EntityName == entityName);
                }
                if (search.CategoryId != null)
                {
                    int catId = search.CategoryId;
                    if (catId > 0)
                        query = query.Where(x => x.CategoryId == catId);
                }
                if (search.PostId != null)
                {
                    int postId = search.PostId;
                    if (postId > 0)
                        query = query.Where(x => x.PostId == postId);
                }
                if (search.Frequency != null)
                {
                    SitemapFrequency frequency = search.Frequency;
                    query = query.Where(x => x.Frequency == frequency);

                }
                if (search.IncludeInSiteMap != null)
                {
                    bool includeInSiteMap = search.IncludeInSiteMap;
                    query = query.Where(x => x.IncludeInSiteMap == includeInSiteMap);
                }
            }
            param.Sort = new Sort() { Predicate = "UpdatedTime", Reverse = true };
            var gridData = await query.ToSmartTableResultAsync(param, x => x.ToItem());

            return gridData;
        }

        /// <summary>
        /// Lấy thông tin UrlRecord theo Id.
        /// </summary>
        /// <param name="id">Id của UrlRecord.</param>
        /// <returns>Thông tin UrlRecord.</returns>
        public async Task<UrlRecordModel> GetById(int id)
        {
            var model = new UrlRecordModel();
            if (id <= 0) return model;
            var urlRecord = await _urlRecordRepository.Query().FirstOrDefaultAsync(c => c.Id == id);
            if (urlRecord != null && urlRecord.Id > 0)
            {
                model = urlRecord.ToModel();
            }
            return model;

        }

        /// <summary>
        /// Tạo hoặc cập nhật UrlRecord.
        /// </summary>
        /// <param name="urlRecordModel">Thông tin UrlRecord.</param>
        /// <returns>Kết quả của thao tác.</returns>
        public async Task<UrlRecordResult> CreateOrUpdate(UrlRecordModel urlRecordModel)
        {
            var urlRecord = urlRecordModel.ToEntity();
            // Cập nhật thông tin chung của thực thể
            urlRecord = urlRecord.UpdateCommonInt(urlRecordModel.UpdatedBy, urlRecordModel.UpdatedByUserName);
            if (urlRecord.Id > 0)
            {
                // Cập nhật
                return await Update(urlRecord);
            }
            else
            {
                // Thêm mới
                return await Create(urlRecord);
            }
        }

        /// <summary>
        /// Thêm mới UrlRecord.
        /// </summary>
        /// <param name="urlRecord">Thông tin UrlRecord.</param>
        /// <returns>Kết quả của thao tác.</returns>
        private async Task<UrlRecordResult> Create(UrlRecord urlRecord)
        {
            var result = new UrlRecordResult();
            try
            {
                await _urlRecordRepository.InsertAsync(urlRecord);
                result.Id = urlRecord.Id;
            }
            catch (Exception e)
            {
                result.Result = Result.SystemError;
                result.Message = e.ToString();
                result.Id = 0;
            }
            return result;
        }

        /// <summary>
        /// Cập nhật UrlRecord.
        /// </summary>
        /// <param name="urlRecord">Thông tin UrlRecord.</param>
        /// <returns>Kết quả của thao tác.</returns>
        private async Task<UrlRecordResult> Update(UrlRecord urlRecord)
        {
            var result = new UrlRecordResult() { Result = Result.Success };
            var urlRecordForUpdate = _urlRecordRepository.Query().FirstOrDefault(c => c.Id == urlRecord.Id);
            if (urlRecordForUpdate == null || urlRecord.Id <= 0)
            {
                result.Result = Result.Failed;
                result.Message = "Không tìm thấy bài viết yêu cầu!";
                return result;
            }

            try
            {
                // Cập nhật thông tin của bài viết
                urlRecordForUpdate.MetaTitle = urlRecord.MetaTitle.Trim();
                urlRecordForUpdate.MetaDescription = urlRecord.MetaDescription.Trim();
                urlRecordForUpdate.MetaKeywords = urlRecord.MetaKeywords;
                urlRecordForUpdate.Slug = urlRecord.Slug;
                urlRecordForUpdate.Priority = urlRecord.Priority;
                urlRecordForUpdate.IncludeInSiteMap = urlRecord.IncludeInSiteMap;
                urlRecordForUpdate.Frequency = urlRecord.Frequency;
                await _urlRecordRepository.UpdateAsync(urlRecordForUpdate);
                result.Id = urlRecordForUpdate.Id;
            }
            catch (Exception e)
            {
                result.Result = Result.SystemError;
                result.Message = e.ToString();
            }

            return result;
        }

        /// <summary>
        /// Cập nhật thông tin cơ bản của UrlRecord.
        /// </summary>
        /// <param name="model">Model chứa thông tin cập nhật UrlRecord.</param>
        /// <returns>Kết quả của thao tác.</returns>
        public async Task<BaseResult> UpdateUrlRecordInfo(UrlRecordUpdateModel model)
        {
            var result = new BaseResult();
            try
            {
                var urlRecord = await _urlRecordRepository.Query().FirstOrDefaultAsync(c => c.Id == model.Id);
                if (urlRecord == null || urlRecord.Id <= 0)
                {
                    result.Result = Result.Failed;
                    result.Message = "Không tìm thấy bài viết yêu cầu!";
                    return result;
                }

                urlRecord.MetaTitle = model.MetaTitle.Trim();
                urlRecord.MetaDescription = model.MetaDescription.Trim();
                urlRecord.MetaKeywords = model.MetaKeywords;
                urlRecord.IncludeInSiteMap = model.IncludeInSiteMap;
                urlRecord.Priority = model.Priority;
                urlRecord.Frequency = model.Frequency;

                await _urlRecordRepository.UpdateAsync(urlRecord);
                result.Result = Result.Success;
            }
            catch (Exception e)
            {
                result.Result = Result.SystemError;
                result.Message = e.ToString();
            }

            return result;
        }

    }

    /// <summary>
    /// Enum đại diện cho loại thực thể của UrlRecord.
    /// </summary>
    public enum UrlEntityType
    {
        Post = 1,
        Tag = 2,
        Category = 3,
        Topic = 4,
        Product = 5,
        JobPost = 6
    }
}
