using Hotline.CallCenter.Calls;
using Hotline.Orders;
using Hotline.Permissions;
using Hotline.Settings;
using Hotline.Settings.CommonOpinions;
using Hotline.Share.Dtos.Settings;
using Hotline.Share.Enums.FlowEngine;
using MapsterMapper;
using Microsoft.AspNetCore.Mvc;
using MongoDB.Driver;
using SqlSugar;
using System.Reflection.Metadata;
using Hotline.Application.CallCenter;
using Hotline.CallCenter.Configs;
using Hotline.FlowEngine.Workflows;
using Hotline.Settings.TimeLimits;
using Hotline.Share.Enums.CallCenter;
using Hotline.Share.Enums.Order;
using Microsoft.Extensions.Options;
using XF.Domain.Authentications;
using XF.Domain.Exceptions;
using XF.Domain.Repository;
using Hotline.Configurations;

namespace Hotline.Api.Controllers
{
    /// <summary>
    /// 常用意见接口
    /// </summary>
    public class CommonPController : BaseController
    {
        private readonly ISystemCommonOpinionDomainService _commonOpinionDomainService;
        private readonly ISystemAreaDomainService _systemAreaDomainService;
        private readonly IMapper _mapper;
        private readonly ISessionContext _sessionContext;
        // private readonly IRepository<TrCallRecord> _trCallRecordRepository;
        private readonly IOrderRepository _orderRepository;
        private readonly IOrderDelayRepository _orderDelayRepository;
        private readonly ITimeLimitDomainService _timeLimitDomainService;
        private readonly IOrderScreenRepository _orderScreenRepository;
        private readonly IRepository<OrderVisitDetail> _orderVisitedDetailRepository;
        private readonly ICallApplication _callApplication;
        private readonly IOptionsSnapshot<AppConfiguration> _appOptions;

        public CommonPController(
            ISystemCommonOpinionDomainService commonOpinionDomainService,
            ISystemAreaDomainService systemAreaDomainService,
            ISessionContext sessionContext,
            // IRepository<TrCallRecord> trCallRecordRepository,
            IOrderRepository orderRepository,
            IMapper mapper,
            IOrderDelayRepository orderDelayRepository,
            ITimeLimitDomainService timeLimitDomainService,
            IOrderScreenRepository orderScreenRepository,
            IRepository<OrderVisitDetail> orderVisitedDetailRepository,
            ICallApplication callApplication,
            IOptionsSnapshot<AppConfiguration> appOptions)
        {
            _commonOpinionDomainService = commonOpinionDomainService;
            _systemAreaDomainService = systemAreaDomainService;
            _mapper = mapper;
            _sessionContext = sessionContext;
            // _trCallRecordRepository = trCallRecordRepository;
            _orderRepository = orderRepository;
            _orderDelayRepository = orderDelayRepository;
            _timeLimitDomainService = timeLimitDomainService;
            _orderScreenRepository = orderScreenRepository;
            _orderVisitedDetailRepository = orderVisitedDetailRepository;
            _callApplication = callApplication;
            _appOptions = appOptions;
        }


        #region 省市区

        /// <summary>
        /// 获取省市区树形
        /// </summary>
        /// <returns></returns>
        [HttpGet("tree-area")]
        [Obsolete("请调用sys/area/tree")]
        public async Task<List<SystemArea>> GetAearTree()
        {
            return await _systemAreaDomainService.GetAreaTree();
        }

        #endregion

        /// <summary>
        /// 首页基础数据
        /// </summary>
        /// <returns></returns>
        [HttpGet("home_data")]
        public async Task<Object> GetHomeData()
        {
            var tadayTime = DateTime.Now.ToString("yyyy-MM-dd");
            //中心
            if (_sessionContext.OrgIsCenter)
            {
                var orderQuery = _orderRepository.Queryable(false, false, false)
                    .Includes(o => o.Workflow, w => w.Steps);
                //今日来电
                //  var tadayCalls = await _trCallRecordRepository.Queryable()
                //      .Where(x => x.CallDirection == Share.Enums.CallCenter.ECallDirection.In && tadayTime.Equals(x.CreatedTime.ToString("yyyy-MM-dd"))).ToListAsync();
                //  var callNum = tadayCalls.Count();
                //  var validCallNum = tadayCalls.Where(x => x.Duration > 0 || x.QueueTims > 0 || x.RingTimes > 0).Count();
                //  //今日接通率
                //  var answeredNum = tadayCalls.Where(x => x.Duration > 0).Count();
                // var answeredRate = validCallNum > 0 ? Math.Round((double.Parse(answeredNum.ToString()) / double.Parse(validCallNum.ToString())) * 100, 2) + "%" : "-";

                int callNum = 0, validCallNum = 0, answeredNum = 0;
                var answeredRate = string.Empty;
                var today = DateTime.Today.Date;
                if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.TianRun)
                {
                    var calls = await _callApplication.QueryTianrunCallsAsync(
                        direction: ECallDirection.In,
                        callStartTimeStart: today,
                        callStartTimeEnd: today.AddDays(1).AddSeconds(-1),
                        cancellationToken: HttpContext.RequestAborted);
                    callNum = calls.Count();
                    validCallNum = calls.Where(x => x.Duration > 0 || x.QueueTims > 0 || x.RingTimes > 0).Count();
                    //今日接通率
                    answeredNum = calls.Where(x => x.Duration > 0).Count();
                    answeredRate = validCallNum > 0
                        ? Math.Round((double.Parse(answeredNum.ToString()) / double.Parse(validCallNum.ToString())) * 100, 2) + "%"
                        : "-";
                }
                else if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.XingTang)
                {
                    var calls = await _callApplication.QueryCallsAsync(
                        callStartTimeStart: today,
                        callStartTimeEnd: today.AddDays(1).AddSeconds(-1),
                        cancellationToken: HttpContext.RequestAborted);
                    callNum = calls.Count();
                    validCallNum = calls.Where(x => x.Duration > 0 || x.WaitDuration > 0 || x.RingDuration > 0).Count();
                    //今日接通率
                    answeredNum = calls.Where(x => x.Duration > 0).Count();
                    answeredRate = validCallNum > 0
                        ? Math.Round((double.Parse(answeredNum.ToString()) / double.Parse(validCallNum.ToString())) * 100, 2) + "%"
                        : "-";
                }

                //今日受理工单
                var tadayOrders = await orderQuery
                    .Where(o => tadayTime.Equals(o.CreationTime.ToString("yyyy-MM-dd"))).ToListAsync();
                var orderNum = tadayOrders.Count();
                var directlyNum = tadayOrders.Where(o => o.ProcessType == Share.Enums.Order.EProcessType.Zhiban).Count();
                return new
                {
                    CallNum = callNum, ValidCallNum = validCallNum, AnsweredNum = answeredNum, AnsweredRate = answeredRate, OrderNum = orderNum,
                    DirectlyNum = directlyNum
                };
            }

            //部门
            //今日待办 tasksOkNum
            //var time = DateTime.Parse(tadayTime);
            //工单
            var order = await _orderRepository.Queryable(hasHandled: false)
	            .Includes(d => d.OrderSpecials)
	            .Where(d => d.Status != EOrderStatus.WaitForAccept && d.Status != EOrderStatus.BackToUnAccept && d.Status != EOrderStatus.SpecialToUnAccept && d.Status !=  EOrderStatus.HandOverToUnAccept)
				.Where(d => d.Source < ESource.MLSQ || d.Source > ESource.WZSC)
	            .Where(d => d.Status != EOrderStatus.BackToProvince && d.Status < EOrderStatus.Filed)
	            .Where(d => d.OrderSpecials.Any() == false || d.OrderSpecials.Any(s => s.State > 0))
				.GroupBy(o => new { o.Id,o.Status })
                .Select(o => new
                {
                    aboutExpire = SqlFunc.AggregateSum(SqlFunc.IIF(DateTime.Now > o.NearlyExpiredTime!.Value && DateTime.Now < o.ExpiredTime!.Value,
                        1, 0)),
                    havExpired = SqlFunc.AggregateSum(SqlFunc.IIF(DateTime.Now > o.ExpiredTime!.Value , 1, 0)),
                    countersignHandle = SqlFunc.AggregateSum(SqlFunc.IIF(o.CounterSignType.HasValue, 1, 0)),
                }).ToListAsync();
            var aboutExpire = order?.Sum(x=>x.aboutExpire) ?? 0;
            var havExpired = order?.Sum(x=>x.havExpired) ?? 0;
            var countersignHandle = order?.Sum(x=> x.countersignHandle) ?? 0;
            //延期
            var delay = await _orderDelayRepository.Queryable(hasHandled: false)
                .Where(d => d.DelayState == EDelayState.Examining).CountAsync();
            //甄别
            var screenAudit = await _orderScreenRepository.Queryable(hasHandled: false)
                .Where(x=>x.CreationTime < DateTime.Now && x.CreationTime > DateTime.Now.AddMonths(-2))
                .Where(x => (x.Status == EScreenStatus.Apply || x.Status == EScreenStatus.Approval || (x.Status == EScreenStatus.SendBack && x.SendBackApply == false)))
                //.Where(d => d.Status == EScreenStatus.Apply)
                .CountAsync();
            //var workTime = _timeLimitDomainService.CalcWorkTimeReduce(DateTime.Now, 5);
            var screenHandle = await _orderVisitedDetailRepository.Queryable(false, true)
                .Includes(x => x.OrderVisit)
                .Includes(x => x.OrderScreens)
				.Where(x => x.OrderScreens.Any(s => s.Status == EScreenStatus.SendBack && s.SendBackApply == true) || x.OrderScreens.Any(s => (s.Status != EScreenStatus.SendBack && s.SendBackApply != true)) == false)
                .Where(x => x.OrderVisit.VisitState == EVisitState.Visited && x.OrderVisit.IsCanHandle)
                .Where(x=> x.VisitTarget == EVisitTarget.Org && x.VisitOrgCode == _sessionContext.OrgId && (
                    SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "1" || SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2" ||
                    SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "1" || SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "2")).CountAsync();
            return new
            {
                AboutExpire = aboutExpire, HavExpired = havExpired, CountersignHandle = countersignHandle, ScreenAudit = screenAudit, Delay = delay,
                ScreenHandle = screenHandle
            };
        }
    }
}