using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Hotline.CallCenter.Calls;
using Hotline.Orders;
using SqlSugar;
using XF.Domain.Dependency;
using XF.Domain.Repository;

namespace Hotline.Application.Bigscreen
{
    public abstract class SeatStateDataServiceBase
    {
        private readonly IRepository<CallNative> _callRepository;

        public SeatStateDataServiceBase(IRepository<CallNative> callRepository)
        {
            _callRepository = callRepository;
        }

        public virtual async Task<object> GetCall24(CancellationToken stoppingToken)
        {
            List<string> timeList = new List<string>();
            for (int i = 0;i < 24;i++)
            {
                var time = i < 10 ? $"0{i}" : i.ToString();
                timeList.Add(time);
            }
            var now = DateTime.Now.Date;
            var call24 = await _callRepository.Queryable()
                .LeftJoin<Order>((x, o) => x.Id == o.CallId)
                .Where((x, o) => x.CreationTime.Date == DateTime.Now.Date
                    && string.IsNullOrEmpty(o.Id) == false && x.Direction == Share.Enums.CallCenter.ECallDirection.In
                )
                .Select(x => new { time = x.CreationTime.ToString("hh"), x.Direction }).MergeTable()
                .GroupBy(x => x.time)
                .Select(x => new
                {
                    Time = x.time.ToString(),
                    In = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == Share.Enums.CallCenter.ECallDirection.In, 1, 0)),
                    //Out = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == Share.Enums.CallCenter.ECallDirection.Out, 1, 0)),
                }).MergeTable().ToListAsync(stoppingToken);

            var callOut24 = await _callRepository.Queryable()
                .Where(x => x.CreationTime.Date == DateTime.Now.Date && x.Direction == Share.Enums.CallCenter.ECallDirection.Out
                )
                .Select(x => new { time = x.CreationTime.ToString("hh"), x.Direction }).MergeTable()
                .GroupBy(x => x.time)
                 .Select(x => new
                 {
                     Time = x.time.ToString(),
                     //In = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == Share.Enums.CallCenter.ECallDirection.In, 1, 0)),
                     Out = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == Share.Enums.CallCenter.ECallDirection.Out, 1, 0)),
                 }).MergeTable().ToListAsync(stoppingToken);

            var call24List = (from t1 in timeList
                              join t2 in call24 on t1 equals t2.Time into t1_t2
                              join t3 in callOut24 on t1 equals t3.Time into t1_t3
                              from item in t1_t3.DefaultIfEmpty()
                              select new
                              {
                                  Time = t1 + ":00",
                                  In = t1_t2.Select(x => x.In).FirstOrDefault(),
                                  Out = t1_t3.Select(x => x.Out).FirstOrDefault()
                              }).ToList();
            return call24List;
        }

        public virtual async Task<object> GetCallTop10(CancellationToken stoppingToken)
        {
            var callTop10 = await _callRepository.Queryable()
                .LeftJoin<Order>((x, o) => x.Id == o.CallId)
                .Where((x, o) => x.CreationTime.Date == DateTime.Now.Date
                    && string.IsNullOrEmpty(o.Id) == false
                )
                .GroupBy(x => x.UserName)
                .Select(x => new
                {
                    UserName = x.UserName,
                    In = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == Share.Enums.CallCenter.ECallDirection.In, 1, 0))
                }).MergeTable().OrderByDescending(x => x.In).Take(10).ToListAsync(stoppingToken);
            return callTop10;
        }

        public virtual async Task<object> GetCallList(CancellationToken stoppingToken)
        {
            var callList = await _callRepository.Queryable()
                .LeftJoin<Order>((x, o) => x.Id == o.CallId)
                .Where((x, o) => x.CreationTime.Date == DateTime.Now.Date
                    && string.IsNullOrEmpty(o.Id) == false
                )
                .Select(x => new
                {
                    InOn = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == Share.Enums.CallCenter.ECallDirection.In && x.AnsweredTime != null, 1, 0)),
                    ValidOn = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == Share.Enums.CallCenter.ECallDirection.In && x.AnsweredTime != null && x.Duration > 5, 1, 0)),
                    InNoOn = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == Share.Enums.CallCenter.ECallDirection.In && x.AnsweredTime == null, 1, 0)),
                    OutOn = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == Share.Enums.CallCenter.ECallDirection.Out && x.AnsweredTime != null, 1, 0)),
                    InQueueNoOn = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == Share.Enums.CallCenter.ECallDirection.In && x.AnsweredTime == null && x.WaitDuration > 0, 1, 0)),
                }).MergeTable().ToListAsync(stoppingToken);
            return callList;
        }

        public virtual async Task<object> GetCallAverage(CancellationToken stoppingToken)
        {
            List<string> timeList = new List<string>();
            for (int i = 0;i < 24;i++)
            {
                var time = i < 10 ? $"0{i}" : i.ToString();
                timeList.Add(time);
            }
            var callAverage = await _callRepository.Queryable()
                .LeftJoin<Order>((x, o) => x.Id == o.CallId)
                .Where((x, o) => x.CreationTime.Date == DateTime.Now.Date
                    && string.IsNullOrEmpty(o.Id) == false
                )
                .Select(x => new { time = x.CreationTime.ToString("hh"), x.Direction }).MergeTable()
                .GroupBy(x => x.time)
                .Select(x => new
                {
                    Time = x.time.ToString(),
                    In = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == Share.Enums.CallCenter.ECallDirection.In, 1, 0)),
                    InAverag = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == Share.Enums.CallCenter.ECallDirection.In, 1, 0)) / 60,
                    Out = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == Share.Enums.CallCenter.ECallDirection.Out, 1, 0)),
                    OutAverag = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == Share.Enums.CallCenter.ECallDirection.Out, 1, 0)) / 60,
                }).MergeTable().ToListAsync(stoppingToken);
            var callAverageList = (from t1 in timeList
                                   join t2 in callAverage on t1 equals t2.Time into t1_t2
                                   from item in t1_t2.DefaultIfEmpty()
                                   select new
                                   {
                                       Time = t1 + ":00",
                                       In = t1_t2.Select(x => x.In).FirstOrDefault(),
                                       InAverag = t1_t2.Select(x => x.InAverag).FirstOrDefault(),
                                       Out = t1_t2.Select(x => x.Out).FirstOrDefault(),
                                       OutAverag = t1_t2.Select(x => x.OutAverag).FirstOrDefault()
                                   }).ToList();
            return callAverageList;
        }
    }
}
