using Exam.Application;
using Exam.Infrastructure.Data.Entity;
using Exam.Infrastructure.Data.Interface;
using Exam.Infrastructure.Extensions;
using Exam.Infrastructure.Validation.Constants;
using Hotline.Exams.Sourcewares;
using Hotline.Repository.SqlSugar;
using Hotline.Repository.SqlSugar.DataPermissions;
using Hotline.Repository.SqlSugar.Exam.Interfaces.Sourcewares;
using Hotline.Share.Dtos.Sourcewares;
using Hotline.Share.Requests.Sourceware;
using Hotline.Share.ViewResponses.Sourcewares;
using Mapster;
using MapsterMapper;
using SqlSugar;
using System.ComponentModel;
using Hotline.Application.Exam.Interface.Sourcewares;
using Hotline.Application.Exam.QueryExtensions.Sourcewares;
using XF.Domain.Dependency;
using Hotline.Repository.SqlSugar.Exam.Service;

namespace Hotline.Application.Exam.Service.Sourcewares
{
    /// <summary>
    /// 课件服务
    /// </summary>
    [Description("课件服务")]
    public class SourcewareService : ApiService<ExamSourceware, AddSourcewareDto,UpdateSourcewareDto,HotlineDbContext>,ISourcewareService, IScopeDependency
    {
        private readonly ISourcewareRepository _repository;
        private readonly IDataPermissionFilterBuilder _datePermissionFilterBuilder;
        private readonly IServiceProvider _serviceProvider;
        private readonly IMapper _mapper;
        public SourcewareService(ISourcewareRepository repository, IDataPermissionFilterBuilder dataPermissionFilterBuilder, IServiceProvider serviceProvider,IMapper mapper) : base(repository, mapper)
        {
            _repository = repository;
            _datePermissionFilterBuilder = dataPermissionFilterBuilder;
            _serviceProvider = serviceProvider;
            _mapper = mapper;
        }

        #region public method
        public async Task<SourcewareDto> GetAsync(EntityQueryRequest entityQueryRequest)
        {
            var entity = await _repository.GetAsync(entityQueryRequest.Id);

            return _mapper.Map<SourcewareDto>(entity);
        }

        public async Task<(int, List<SourcewareViewResponse>)> GetListAsync(SourcewarePagedRequest queryRequest)
        {
            ISugarQueryable<SourcewareViewResponse> queryable = QueryResult(queryRequest);

            var result = await queryable.ToListAsync();

            var total = await queryable.CountAsync();

            return (total, result);
        }

        public async Task<PageViewResponse<SourcewareViewResponse>> GetPagedListAsync(SourcewarePagedRequest queryRequest)
        {
            ISugarQueryable<SourcewareViewResponse> queryable = QueryResult(queryRequest);

            var list = await queryable.ToPageListAsync(queryRequest.PageIndex, queryRequest.PageSize);
            var total = await queryable.CountAsync();

            var result = new SourcewarePageViewResponse
            {
                Items = list,
                Pagination = new Pagination(queryRequest.PageIndex, queryRequest.PageSize, total)
            };

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="actionRequest"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public override async Task<string> AddAsync(AddSourcewareDto actionRequest, CancellationToken cancellationToken)
        {
            await SetDefaultCategory(actionRequest);

            return await base.AddAsync(actionRequest, cancellationToken);
        }

        /// <summary>
        /// 更新课件分类
        /// </summary>
        /// <param name="actionRequest"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public override async Task UpdateAsync(UpdateSourcewareDto actionRequest, CancellationToken cancellationToken)
        {
            await SetDefaultCategory(actionRequest);

            await base.UpdateAsync(actionRequest, cancellationToken);
        }
        #endregion

        #region private method
        /// <summary>
        /// 设置默认分类
        /// </summary>
        /// <param name="actionRequest"></param>
        /// <returns></returns>
        private async Task SetDefaultCategory(AddSourcewareDto actionRequest)
        {
            var category = await new BaseRepository<ExamSourcewareCategory>(_uow, _datePermissionFilterBuilder, _serviceProvider).Queryable().FirstAsync(x => x.Name == InfrastructureConstant.NoCategory);

            if (actionRequest.CategoryId.IsNullOrEmpty())
            {
                actionRequest.CategoryId = category != null ? category.Id : string.Empty;
            }
        }
        /// <summary>
        /// 获取查询结果
        /// </summary>
        /// <param name="queryRequest"></param>
        /// <returns></returns>
        private ISugarQueryable<SourcewareViewResponse> QueryResult(SourcewarePagedRequest queryRequest)
        {
            var expression = queryRequest.GetExpression();
            var query = _repository.Queryable().Where(expression);
            var sourcewareCategoryTable = new BaseRepository<ExamSourcewareCategory>(_uow, _datePermissionFilterBuilder, _serviceProvider).Queryable();
            var querable = query.OrderBy(o=>o.SortIndex).Select(m => new SourcewareViewResponse
            {
                Name = m.Name,
                CategoryId = m.CategoryId,
                AttachmentId = m.AttachmentId,
                SourcewareType = m.SourcewareType,
                Id = m.Id,
                Status = m.Status,
                CreatorId = m.CreatorId,
                CreatorName = m.CreatorName,
                CreationTime = m.CreationTime
            }).LeftJoin(sourcewareCategoryTable, (s, c) => s.CategoryId == c.Id).Select((s, c) =>
            new SourcewareViewResponse
            {
                Name = s.Name,
                CategoryId = s.CategoryId,
                AttachmentId = s.AttachmentId,
                SourcewareType = s.SourcewareType,
                CategoryName = c.Name,
                Id = s.Id,
                Status = s.Status,
                CreatorId = s.CreatorId,
                CreatorName = s.CreatorName,
                CreationTime = s.CreationTime
            });
            return querable;
        } 
        #endregion
    }
}


