using Myshipping.Core;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using System.Linq;
using System.Threading.Tasks;
using Furion.Logging;
using Microsoft.Extensions.Logging;
using Myshipping.Core.Entity;
using Furion.FriendlyException;
using System;
using Furion.EventBus;

namespace Myshipping.Core.Service
{
    /// <summary>
    /// 大简云消息服务
    /// </summary>
    [ApiDescriptionSettings(Name = "DjyMessage", Order = 1)]
    public class DjyMessageService : IDjyMessageService, IDynamicApiController, ITransient
    {
        private readonly SqlSugarRepository<DjyMessage> _rep;
        private readonly ISysCacheService _cacheService;
        private readonly ILogger<DjyMessageService> _logger;
        private readonly IEventPublisher _publisher;

        public DjyMessageService(SqlSugarRepository<DjyMessage> rep, ILogger<DjyMessageService> logger, ISysCacheService cacheService,
            IEventPublisher publisher)
        {
            _rep = rep;
            _logger = logger;
            _cacheService = cacheService;
            this._publisher = publisher;
        }

        /// <summary>
        /// 消息列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("/DjyMessage/Page")]
        public async Task<SqlSugarPagedList<DjyMessageListOutput>> Page(DjyMessageQueryInput input)
        {
            var query = _rep.AsQueryable()
                .Where(x => x.TenantId == UserManager.TENANT_ID && (x.ToId == null || x.ToId == UserManager.UserId))
                .WhereIF(!string.IsNullOrEmpty(input.TypeCode), x => x.TypeCode == input.TypeCode)
                .WhereIF(!string.IsNullOrEmpty(input.Module), x => x.Module == input.Module)
                .WhereIF(input.IsRead.HasValue, x => x.IsRead == input.IsRead)
                .WhereIF(!string.IsNullOrEmpty(input.ProcStatus), x => x.ProcStatus == input.ProcStatus)
                .WhereIF(!string.IsNullOrEmpty(input.RelativeCode), x => x.RelativeCode.Contains(input.RelativeCode))
                .WhereIF(input.CreateTimeStart.HasValue, x => x.CreatedTime >= input.CreateTimeStart)
                .WhereIF(input.CreateTimeEnd.HasValue, x => x.CreatedTime < input.CreateTimeEnd.Value.AddDays(1))
                .WhereIF(!string.IsNullOrEmpty(input.FromName), x => x.FromName.Contains(input.FromName));

            if (!string.IsNullOrEmpty(input.SortField) || input.MultiSort == null || input.MultiSort.Count == 0)
            {
                query = query.OrderBy(PageInputOrder.OrderBuilder(input.SortField, input.DescSort));
            }
            else
            {
                query = query.OrderBy(PageInputOrder.MultiOrderBuilder(input.MultiSort));
            }

            var entities = await query.ToPagedListAsync(input.PageNo, input.PageSize);
            var list = entities.Adapt<SqlSugarPagedList<DjyMessageListOutput>>();
            return list;
        }



        /// <summary>
        /// 消息删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost("/DjyMessage/Delete")]
        public async Task Delete(long id)
        {
            await _rep.AsUpdateable(new DjyMessage() { Id = id, IsDeleted = true }).UpdateColumns(x => new { x.IsDeleted }).ExecuteCommandAsync();
        }

        /// <summary>
        /// 保存消息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("/DjyMessage/Save")]
        public Task<long> Save(DjyMessageSaveInput input)
        {
            throw new System.NotImplementedException();
        }

        /// <summary>
        /// 消息详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost("/DjyMessage/Get")]
        public async Task<DjyMessageDetailOutput> Get(long id)
        {
            var msg = await _rep.FirstOrDefaultAsync(x => x.Id == id);
            return msg.Adapt<DjyMessageDetailOutput>();
        }

        /// <summary>
        /// 读取消息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost("/DjyMessage/Read")]
        public async Task Read(long id)
        {
            await _rep.AsUpdateable(new DjyMessage()
            {
                Id = id,
                IsRead = true,
                ReadTime = DateTime.Now,
                ReadUser = UserManager.Name
            }).UpdateColumns(x => new { x.IsRead, x.ReadTime, x.ReadUser }).ExecuteCommandAsync();
        }

        /// <summary>
        /// 处理消息
        /// </summary>
        /// <returns></returns>
        [HttpPost("/DjyMessage/Process")]
        public async Task Process(DjyMessageProcessInput input)
        {
            var msg = await _rep.FirstOrDefaultAsync(x => x.Id == input.Id);
            if (msg.ProcStatus != MessageProcessStatus.UnProcess.ToString())
            {
                throw Oops.Bah($"当前消息已被{msg.ProcUser}在{(msg.ProcTime.HasValue ? msg.ProcTime.Value.ToString("yyyy-MM-dd HH:mm:ss") : "")}处理过");
            }

            msg.ProcStatus = input.ProcStatus.ToString();
            msg.ProcResult = input.Comment;
            msg.ProcUser = UserManager.Name;
            msg.ProcTime = DateTime.Now;
            if (!msg.IsRead) //处理消息时,自动已读
            {
                msg.IsRead = true;
                msg.ReadTime = DateTime.Now;
                msg.ReadUser = UserManager.Name;
            }

            await _rep.AsUpdateable(msg).UpdateColumns(x => new { x.ProcStatus, x.ProcResult, x.ProcUser }).ExecuteCommandAsync();

            //发布已处理事件消息
            await _publisher.PublishAsync(new ChannelEventSource($"Message:Process:{msg.Module}:{msg.TypeCode}", input.Id));
        }

        /// <summary>
        /// 获取消息数量统计
        /// </summary>
        /// <returns></returns>
        [HttpPost("/DjyMessage/GetNumSum")]
        public async Task<DjyMessageProcessNum> GetNumSum(string module)
        {
            var rtn = new DjyMessageProcessNum();
            rtn.UnreadCount = await _rep.CountAsync(x => x.Module == module && x.IsRead == false && x.TenantId == UserManager.TENANT_ID && (x.ToId == null || x.ToId == UserManager.UserId));
            var strStaUnproc = MessageProcessStatus.UnProcess.ToString();
            rtn.UnprocessCount = await _rep.CountAsync(x => x.Module == module && x.ProcStatus == strStaUnproc && x.TenantId == UserManager.TENANT_ID && (x.ToId == null || x.ToId == UserManager.UserId));
            return rtn;
        }
    }
}