using Lada.Framework.Data.Domains.Cms;
using Lada.Framework.Data.Repositories;
using Lada.Framework.DTO;
using Lada.Framework.DTO.SmartTable;
using Lada.Framework.Infrastructures.Helpers;
using Ladaer.BackEnd.Infrastructures.DTO;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Cms;
using Microsoft.EntityFrameworkCore;

namespace Ladaer.BackEnd.Infrastructures.Services.Cms
{
    public interface ITagService
    {

        Task<List<TagItem>> TagAutocomplete(string keyword);
        Task<SmartTableResult<TagItem>> Search(SmartTableParam param);
        Task<Tag> CreateAsync(string name, int createdBy, string createdByUserName);
        Task<List<Tag>> CreateAsync(List<string> tagNames, int createdBy, string createdByUserName);

        Task<BaseResult> RemoveProductTagByProductIdAsync(int productId);
        Task<BaseResult> RemovePostTagByPostIdAsync(int postId);
        Task<BaseResult> RemoveJobPostTagByJobPostIdAsync(int jobPostId);
    }

    public class TagService : ITagService
    {
        private readonly IRepository<Tag> _tagRepository;
        private readonly IRepository<ProductTag> _productTagRepository;
        private readonly IRepository<PostTag> _postTagRepository;
        private readonly IRepository<JobPostTag> _jobPostTagRepository;
        private readonly IUrlRecordService _urlRecordService;

        public TagService(IRepository<Tag> tagRepository, IUrlRecordService urlRecordService, IRepository<ProductTag> productTagRepository, IRepository<PostTag> postTagRepository, IRepository<JobPostTag> jobPostTagRepository)
        {
            _tagRepository = tagRepository;
            _urlRecordService = urlRecordService;
            _productTagRepository = productTagRepository;
            _postTagRepository = postTagRepository;
            _jobPostTagRepository = jobPostTagRepository;
        }

        public async Task<List<TagItem>> TagAutocomplete(string keyword)
        {

            var result = new List<TagItem>();
            var query = _tagRepository.Query();
            if (string.IsNullOrEmpty(keyword))
            {
                result = await query.Take(25).Select(t => t.ToItem()).ToListAsync();
            }
            else
            {
                result = await query.Where(t => t.Name.Contains(keyword)).Take(25).Select(t => t.ToItem()).ToListAsync();
            }

            return result;
        }

        public async Task<SmartTableResult<TagItem>> Search(SmartTableParam param)
        {
            var query = _tagRepository.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.Name.ToLower().Contains(keyword));
                }
            }
            param.Sort = new Sort() { Predicate = "Id", Reverse = true };

            var gridData = await query.ToSmartTableResultAsync(param, x => x.ToItem());

            return gridData;
        }

        public async Task<Tag> CreateAsync(string name, int createdBy, string createdByUserName)
        {
            var rs = new Tag();
            name = name.ToLower().Trim();
            var slug = name.NormalizeUrl();
            slug = await _urlRecordService.GenerateUrlRecord(slug, UrlEntityType.Tag);
            var currentTime = DateTimeHelper.CurrentTime();
            var tag = new Tag()
            {
                Name = name,
                Description = "",
                UrlRecord = new UrlRecord()
                {
                    MetaTitle = name,
                    MetaDescription = name,
                    MetaKeywords = string.Empty,
                    Slug = slug,
                    CreatedBy = createdBy,
                    CreatedByUserName = createdByUserName,
                    UpdatedBy = createdBy,
                    UpdatedByUserName = createdByUserName,
                    CreatedTime = currentTime,
                    UpdatedTime = currentTime,
                    EntityName = "Tag",
                    EntityDescription = ""
                },
                CreatedBy = createdBy,
                CreatedByUserName = createdByUserName,
                UpdatedBy = createdBy,
                UpdatedByUserName = createdByUserName,
                CreatedTime = currentTime,
                UpdatedTime = currentTime,
            };
            try
            {
                await _tagRepository.InsertAsync(tag);
                rs = tag;
            }
            catch (Exception ex)
            {

            }

            return rs;
        }

        public async Task<List<Tag>> CreateAsync(List<string> tagNames, int createdBy, string createdByUserName)
        {
            var rs = new List<Tag>();
            if (tagNames.Any())
            {
                foreach (var tagName in tagNames)
                {
                    var tagNameIn = tagName.ToLower().Trim();
                    var slug = tagNameIn.NormalizeUrl();
                    slug = await _urlRecordService.GenerateUrlRecord(slug, UrlEntityType.Tag);
                    var currentTime = DateTimeHelper.CurrentTime();
                    var tag = new Tag()
                    {
                        Name = tagNameIn,
                        Description = "",
                        UrlRecord = new UrlRecord()
                        {
                            MetaTitle = tagNameIn,
                            MetaDescription = tagNameIn,
                            MetaKeywords = string.Empty,
                            Slug = slug,
                            CreatedBy = createdBy,
                            CreatedByUserName = createdByUserName,
                            UpdatedBy = createdBy,
                            UpdatedByUserName = createdByUserName,
                            CreatedTime = currentTime,
                            UpdatedTime = currentTime,
                            EntityName = "Tag",
                            EntityDescription = "",
                            IncludeInSiteMap = false
                        },
                        CreatedBy = createdBy,
                        CreatedByUserName = createdByUserName,
                        UpdatedBy = createdBy,
                        UpdatedByUserName = createdByUserName,
                        CreatedTime = currentTime,
                        UpdatedTime = currentTime,
                    };
                    rs.Add(tag);
                }
                await _tagRepository.InsertAsync(rs);
            }


            return rs;
        }


        public async Task<BaseResult> RemoveProductTagByProductIdAsync(int productId)
        {
            var result = new BaseResult();
            var productTags = _productTagRepository.Query().Where(pt => pt.ProductId == productId).ToList();
            try
            {
                if (productTags != null && productTags.Any())
                {
                    foreach (var productTag in productTags)
                    {
                        await _productTagRepository.RemoveAsync(productTag);
                    }
                }
            }
            catch (Exception ex)
            {
                result.Result = Result.Failed;
                result.Message = ex.Message;
            }

            return result;
        }

        public async Task<BaseResult> RemovePostTagByPostIdAsync(int postId)
        {
            var result = new BaseResult();
            var postTags = _postTagRepository.Query().Where(pt => pt.PostId == postId).ToList();
            try
            {
                if (postTags != null && postTags.Any())
                {
                    foreach (var postTag in postTags)
                    {
                        await _postTagRepository.RemoveAsync(postTag);
                    }
                }
            }
            catch (Exception ex)
            {
                result.Result = Result.Failed;
                result.Message = ex.Message;
            }

            return result;
        }


        public async Task<BaseResult> RemoveJobPostTagByJobPostIdAsync(int jobPostId)
        {
            var result = new BaseResult();
            
            try
            {
                var jobPostTags = _jobPostTagRepository.Query().Where(pt => pt.JobPostId == jobPostId).ToList();
                if (jobPostTags != null && jobPostTags.Any())
                {
                    foreach (var jobPostTag in jobPostTags)
                    {
                        await _jobPostTagRepository.RemoveAsync(jobPostTag);
                    }
                }
            }
            catch (Exception ex)
            {
                result.Result = Result.Failed;
                result.Message = ex.Message;
            }

            return result;
        }
    }
}