using Hotline.Caching.Interfaces;
using Hotline.CallCenter.Calls;
using Hotline.Orders;
using Hotline.Repository.SqlSugar.DataPermissions;
using Hotline.Share.Dtos.CallCenter;
using Hotline.Share.Enums.CallCenter;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Drawing.Printing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XF.Domain.Dependency;

namespace Hotline.Repository.SqlSugar.CallCenter
{
    public class TrCallRecordRepository : BaseRepository<TrCallRecord>, ITrCallRecordRepository, IScopeDependency
    {
        public TrCallRecordRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder) : base(uow, dataPermissionFilterBuilder)
        {
        }

        public async Task<List<BiCallDto>?> GetQueryCalls(DateTime beginDate,DateTime endDate)
        {
            TimeSpan timeDifference = endDate.Subtract(beginDate).Duration();

            int hourDiff = (int)(timeDifference.TotalHours);

            //计算时间差
            int hour = Convert.ToInt32((endDate - beginDate).TotalHours);

            List<DateTime> dts = new List<DateTime>() { beginDate };
            for (int i = 0; i < hour - 1; i++)
            {
                dts.Add(dts.Last().AddHours(1));
            }

            var list = await Db.Reportable(dts).ToQueryable<DateTime>()
                .LeftJoin<TrCallRecord>((it, o) => o.CreatedTime >= it.ColumnName && o.CreatedTime < it.ColumnName.AddHours(1) && o.CallDirection == ECallDirection.In)
                //.Where((it,o)=> o.CallDirection == ECallDirection.In)
                .GroupBy(it => it.ColumnName)
                .OrderBy(it => it.ColumnName)
                .Select((it, o) => new BiCallDto()
                {
                    Hour = it.ColumnName.Hour, //小时段
                    Total = SqlFunc.AggregateCount(o.Id),
                    Answered = SqlFunc.AggregateSum(SqlFunc.IIF(o.AnsweredTime != null, 1, 0)), //应答数
                    Hanguped = SqlFunc.AggregateSum(SqlFunc.IIF(o.AnsweredTime == null && o.EndBy != null && o.EndBy.Value == EEndBy.To, 1, 0)),//挂断数
                })
                .MergeTable()
                .OrderBy(x => x.Hour)
                .ToListAsync();
            var returnList = list.GroupBy(x => x.Hour)
               .Select(x => new BiCallDto()
               {
                   Hour = x.Key,
                   Total = x.Sum(d=>d.Total),
                   Answered = x.Sum(d=>d.Answered),
                   Hanguped = x.Sum(d=>d.Hanguped),
                   HourRange = x.Key.ToString().PadLeft(2, '0') + ":00 - " + (x.Key + 1).ToString().PadLeft(2, '0') + ":00",
               }).OrderBy(x=>x.Hour).ToList();
            return returnList;
        }

        public async Task<List<TrCallHourDto>?> GetCallHourList(DateTime beginDate,DateTime? endDate,int noConnectByeTimes,int effectiveTimes,int connectByeTimes, string source)
        {
            //计算小时差
            if (!endDate.HasValue)
            {
                endDate = beginDate.Date.AddDays(1).AddSeconds(-1);
            }
            else
            {
                endDate = endDate.Value.Date.AddDays(1).AddSeconds(-1);
            }
            TimeSpan timeDifference = endDate.Value.Subtract(beginDate).Duration();

            int hourDiff = (int)(timeDifference.TotalHours);
           
            //计算时间差
            int hour = Convert.ToInt32((endDate - beginDate).Value.TotalHours);

            List<DateTime> dts = new List<DateTime>() { beginDate };
            for (int i = 0; i < hour - 1; i++)
            {
                dts.Add(dts.Last().AddHours(1));
            }

            var list = await Db.Reportable(dts).ToQueryable<DateTime>()
                .LeftJoin<TrCallRecord>((it, o) => o.CreatedTime >= it.ColumnName && o.CreatedTime < it.ColumnName.AddHours(1) && o.CallDirection == ECallDirection.In)
				 //.Where((it, o) => o.CallDirection == ECallDirection.In)
				 .WhereIF(!string.IsNullOrEmpty(source), (it,o) => o.CDPN == source)
				.GroupBy((it,o) => it.ColumnName)
                .Select((it, o) => new TrCallHourDto()
                {
                    DateTimeTo = it.ColumnName, 
                    Hour = it.ColumnName.Hour, //小时段
                    EffectiveCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.Duration >= effectiveTimes, 1, 0)),//有效接通
                    ConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.Duration > 0 && o.Duration <= connectByeTimes, 1, 0)), //接通秒挂
                    NoConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.Duration == 0 && o.RingTimes <= noConnectByeTimes && o.RingTimes>0, 1, 0)), //未接通秒挂
                    QueueByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.QueueTims > 0 && o.RingTimes == 0, 1, 0)), //队列挂断
                    IvrByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.BeginIvrTime.HasValue && !o.BeginQueueTime.HasValue && !o.BeginRingTime.HasValue && o.OnState == EOnState.NoOn, 1, 0)), //IVR挂断
                })
                .MergeTable()
                .OrderBy(x=>x.Hour)
                .ToListAsync();

           var resultList = list.GroupBy(x => x.Hour)
                .Select(x=> new TrCallHourDto() { 
                    Hour = x.Key,
                    HourTo = x.Key.ToString().PadLeft(2, '0') + ":00 - " + (x.Key).ToString().PadLeft(2, '0') + ":59",
                    StartHourTo= x.Key.ToString().PadLeft(2, '0') + ":00",
                    EndHourTo = x.Key.ToString().PadLeft(2, '0') + ":59",
					EffectiveCount = x.Sum(d=>d.EffectiveCount),
                    ConnectByeCount = x.Sum(d=>d.ConnectByeCount),
                    NoConnectByeCount = x.Sum(d=>d.NoConnectByeCount),
                    QueueByeCount = x.Sum(d=>d.QueueByeCount),
                    IvrByeCount = x.Sum(d=>d.IvrByeCount),
                }).OrderBy(x=>hour).ToList();

            return resultList;
        }

		/// <summary>
		/// 通话时段统计明细
		/// </summary>
		/// <returns></returns>
        public async Task<object> GetCallList(DateTime beginDate, DateTime? endDate, int noConnectByeTimes, int effectiveTimes, int connectByeTimes, string type, string source , TimeSpan? startHourTo, int pageIndex, int pageSize)
        {
            TimeSpan endHourTo = DateTime.Now.TimeOfDay;
			if (startHourTo.HasValue)
	        {
                 endHourTo = startHourTo.Value.Add(new TimeSpan(1, 0, 0));
			}
	        endDate = endDate.Value.Date.AddDays(1).AddSeconds(-1);
	        RefAsync<int> total = 0;
			var res = await Db.Queryable<TrCallRecord>()
                .Where(x => x.CreatedTime >= beginDate && x.CreatedTime <= endDate)
                .Where(x => x.CallDirection == ECallDirection.In)
                .WhereIF(!string.IsNullOrEmpty(source), x => x.CDPN == source)
                .WhereIF(!string.IsNullOrEmpty(type) && ("QueueBye".Equals(type) || "queueByeCount".Equals(type)), x => x.QueueTims > 0 && x.RingTimes == 0) //队列挂断
				.WhereIF(!string.IsNullOrEmpty(type) &&("IvrBye".Equals(type)|| "ivrByeCount".Equals(type)) , x => x.BeginIvrTime.HasValue && !x.BeginQueueTime.HasValue && !x.BeginRingTime.HasValue && x.OnState == EOnState.NoOn)//IVR挂断
				.WhereIF(!string.IsNullOrEmpty(type) && ("Effective".Equals(type) || "effectiveCount".Equals(type)), x => x.Duration >= effectiveTimes) //有效接通
				.WhereIF(!string.IsNullOrEmpty(type) && "Invalid".Equals(type) , x => x.Duration > 0 && x.Duration < effectiveTimes)//无效接通
				.WhereIF(!string.IsNullOrEmpty(type) && "connectByeCount".Equals(type) , x => x.Duration > 0 && x.Duration <= connectByeTimes)  //接通秒挂
				.WhereIF(!string.IsNullOrEmpty(type) && "noConnectByeCount".Equals(type), x => x.Duration == 0 && x.RingTimes <= noConnectByeTimes && x.RingTimes > 0)  //未接通秒挂
				.WhereIF(!string.IsNullOrEmpty(type) && "count".Equals(type), x => 
                (x.Duration == 0 && x.RingTimes <= noConnectByeTimes && x.RingTimes > 0)  //未接通秒挂
				|| (x.Duration > 0 && x.Duration <= connectByeTimes)  //接通秒挂
				|| (x.Duration >= effectiveTimes)//有效接通
				|| (x.BeginIvrTime.HasValue && !x.BeginQueueTime.HasValue && !x.BeginRingTime.HasValue && x.OnState == EOnState.NoOn) //IVR挂断
				|| (x.QueueTims > 0 && x.RingTimes == 0))//队列挂断
				.WhereIF(startHourTo.HasValue, x=>SqlFunc.ToTime(x.CreatedTime.ToString("HH:mm:ss")) >= startHourTo.Value && SqlFunc.ToTime(x.CreatedTime.ToString("HH:mm:ss")) < endHourTo)
				.Select(x=> new { 
                    CPN = x.CPN,
                    CDPN= x.CDPN,
					CreatedTime = x.CreatedTime
				})
                .ToPageListAsync(pageIndex, pageSize, total);
            return new { Data = res , Total = total.Value};
		}

		public async Task<List<CallHotLineDto>> GetCallHotLineList(DateTime beginDate, DateTime endDate,string lineNum, int noConnectByeTimes, int effectiveTimes, int connectByeTimes,int ringTims)
        {
            endDate = endDate.AddDays(1).AddSeconds(-1);
            var list =await Db.Queryable<TrCallRecord>()
                .Where(x => x.CreatedTime >= beginDate && x.CreatedTime <= endDate)
                .WhereIF(!string.IsNullOrEmpty(lineNum), x => x.Gateway == lineNum)
                .GroupBy(x => x.Gateway)
                .Select(x => new CallHotLineDto()
                {
                    GateWay = x.Gateway,
                    CallInCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.CallDirection == ECallDirection.In, 1, 0)),//接通
                    ConnectCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.CallDirection == ECallDirection.In && x.OnState == EOnState.On, 1, 0)),//接通
                    NoConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.CallDirection == ECallDirection.In && x.Duration == 0 && x.RingTimes <= noConnectByeTimes && x.RingTimes > 0, 1, 0)), //未接通秒挂
                    EffectiveCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.CallDirection == ECallDirection.In && x.Duration >= effectiveTimes, 1, 0)),//有效接通
                    DurationSum = SqlFunc.AggregateSum(SqlFunc.IIF(x.CallDirection == ECallDirection.In && x.OnState == EOnState.On,x.Duration,0)),//通话总时长
                    ConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.CallDirection == ECallDirection.In && x.Duration > 0 && x.Duration <= connectByeTimes, 1, 0)), //接通秒挂
                    TimelyAnswerCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.CallDirection == ECallDirection.In && x.OnState == EOnState.On && x.RingTimes<= ringTims,1,0))//及时应答
                }).ToListAsync();

            return list;
        }


    }
}
