using DocumentFormat.OpenXml.Spreadsheet;
using Fw.Utility.ConfigClient;
using Hotline.Api.Filter;
using Hotline.Application.Identity;
using Hotline.Application.Systems;
using Hotline.Application.Tools;
using Hotline.Authentications;
using Hotline.Caching.Interfaces;
using Hotline.Caching.Services;
using Hotline.FlowEngine.Workflows;
using Hotline.Identity.Accounts;
using Hotline.Orders;
using Hotline.Settings;
using Hotline.Share.Dtos.Identity;
using Hotline.Share.Dtos.Order;
using Hotline.Share.Enums.FlowEngine;
using Hotline.Share.Enums.Order;
using Hotline.Share.Tools;
using Hotline.Users;
using IdentityModel;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MongoDB.Bson.IO;
using NewRock.Sdk.Extensions;
using NPOI.POIFS.Macros;
using SqlSugar;
using System.Security.Claims;
using System.Threading;
using XF.Domain.Authentications;
using XF.Domain.Entities;
using XF.Domain.Exceptions;
using XF.Domain.Repository;

namespace Hotline.Api.Controllers
{
    public class OldHotlineController: BaseController
    {
        private readonly IIdentityAppService _identityAppService;
        private readonly ISystemLogApplication _iSystemLogApplication;
        private readonly IOrderRepository _orderRepository;
        private readonly IOrderVisitRepository _orderVisitRepository;
        private readonly IOrderDelayRepository _orderDelayRepository;
        private readonly IOrderScreenRepository _orderScreenRepository;
        private readonly IRepository<OrderSendBackAudit> _orderSendBackAuditRepository;
        private readonly IRepository<OrderVisitDetail> _orderVisitedDetailRepository;
        private readonly ISessionContext _sessionContext;
        private readonly IRepository<Account> _accountRepository;
        private readonly IHttpClientFactory _httpClientFactory;
        private readonly ISystemSettingCacheManager _systemSettingCacheManager;
        private readonly IOrderDomainService _orderDomainService;

        public OldHotlineController(IIdentityAppService identityAppService, ISystemLogApplication iSystemLogApplication,
            IOrderRepository orderRepository, IOrderVisitRepository orderVisitRepository,
            IOrderDelayRepository orderDelayRepository, IOrderScreenRepository orderScreenRepository,
            IRepository<OrderSendBackAudit> orderSendBackAuditRepository, IRepository<OrderVisitDetail> orderVisitedDetailRepository,
            IRepository<Account> accountRepository, IHttpClientFactory httpClientFactory, ISystemSettingCacheManager systemSettingCacheManager, ISessionContext sessionContext, IOrderDomainService orderDomainService)
        {
            _identityAppService = identityAppService;
            _iSystemLogApplication = iSystemLogApplication;
            _orderRepository = orderRepository;
            _orderVisitRepository = orderVisitRepository;
            _orderDelayRepository = orderDelayRepository;
            _orderScreenRepository = orderScreenRepository;
            _orderSendBackAuditRepository = orderSendBackAuditRepository;
            _orderVisitedDetailRepository = orderVisitedDetailRepository;
            _accountRepository = accountRepository;
            _httpClientFactory = httpClientFactory;
            _systemSettingCacheManager = systemSettingCacheManager;
            _sessionContext = sessionContext;
            _orderDomainService = orderDomainService;
        }

        /// <summary>
        /// 老系统登录新系统
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("loing-oldtonew")]
        [LogFilter("",false)]
        public async Task<string> HotlineLoginOldToNew([FromBody] HotlineLoginOldToNewDto dto)
        {
            try
            {
                dto.UserName = RSA.RSADecrypt(dto.UserName, RSA_Create.RSA_PRIVATE_KEY, "PEM");
            }
            catch 
            {
                throw UserFriendlyException.SameMessage("帐号解密失败");
            }
            var res = await _identityAppService.OldToNewLoginAsync(dto, HttpContext.RequestAborted);
            await _iSystemLogApplication.AddLog("账号登录", res, dto, HttpContext, dto.UserName);
            return res;
        }

        /// <summary>
        /// 是否存在可办信息
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("ishas_canhandler")]
        public async Task<bool> IsHasCanHandler()
        {
            var isHas = false;
            var isAdmin = _orderDomainService.IsCheckAdmin();
            var IsCenter = _sessionContext.OrgIsCenter;
            if (IsCenter)
            {
                #region 待办
                //待办
                var waitedDataList = await _orderRepository
                    .Queryable(hasHandled: false, isAdmin: isAdmin)
                    .Where(d => SqlFunc.Subqueryable<WorkflowStep>()
                        .Where(step => step.ExternalId == d.Id && step.Status != EWorkflowStepStatus.Handled &&
                                       ((step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) && step.HandlerId == _sessionContext.RequiredUserId) ||
                                        (step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == _sessionContext.RequiredOrgId) ||
                                        (step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) && _sessionContext.Roles.Contains(step.RoleId))))
                        .Any())
                    .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))
                    .OrderByDescending(d => new { d.IsUrgent, d.StartTime })
                    .Select(d => new HomeOrderDto
                    {
                        No = d.No,
                        OrderId = d.Id,
                        Title = d.Title,
                        AcceptType = d.AcceptType,
                        HotspotName = d.HotspotName,
                        Type = "Waited",
                        Time = d.ExpiredTime,
                        Status = d.Status,
                        ActualHandleTime = d.ActualHandleTime,
                        CounterSignType = d.CounterSignType
                    })
                    .ToListAsync();
                isHas = waitedDataList.Any();

                //待办是否有数据
                if (isHas)
                {
                    return isHas;
                }
                #endregion

                #region 已超期
                // 已超期
                isHas = waitedDataList.Any(x => (x.Time < DateTime.Now && x.Status < EOrderStatus.Filed) ||
                                                                      (x.Time < x.ActualHandleTime && x.Status >= EOrderStatus.Filed));
                //超期是否有待办
                if (isHas)
                {
                    return isHas;
                }
                #endregion

                #region 回访待办
                //回访待办
                isHas = await _orderVisitRepository.Queryable()
                    .AnyAsync(d => (d.VisitState == EVisitState.WaitForVisit || d.VisitState == EVisitState.NoSatisfiedWaitForVisit) && d.EmployeeId == _sessionContext.RequiredUserId);

                //回访待办是否有数据
                if (isHas)
                {
                    return isHas;
                }
                #endregion

                #region 会签待办
                //会签待办
                isHas = waitedDataList.Any(x => x.CounterSignType == ECounterSignType.Center || x.CounterSignType == ECounterSignType.Department);

                //会签待办是否有数据
                if (isHas)
                {
                    return isHas;
                }
                #endregion

                #region 延期待审批
                //延期待审批
                isHas = await _orderDelayRepository.Queryable(canView: true, isAdmin: isAdmin)
                    .AnyAsync(d => d.DelayState == EDelayState.Examining);

                //延期待审批是否有数据
                if (isHas)
                {
                    return isHas;
                }

                #endregion

                #region 部门即将超期
                //部门即将超期
                isHas = await _orderRepository.Queryable(canView: !IsCenter)
                .AnyAsync(d => SqlFunc.Subqueryable<WorkflowStep>()
                        .Where(step => step.ExternalId == d.Id && step.Status != EWorkflowStepStatus.Handled &&
                                       ((step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) && step.HandlerId == _sessionContext.RequiredUserId) ||
                                        (step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == _sessionContext.RequiredOrgId) ||
                                        (step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) && _sessionContext.Roles.Contains(step.RoleId))))
                        .Any()
                    && d.Status < EOrderStatus.Filed && DateTime.Now > d.NearlyExpiredTime && DateTime.Now < d.ExpiredTime);

                //部门即将超期是否有数据
                if (isHas)
                {
                    return isHas;
                }
                #endregion

                #region 甄别待审批
                //甄别待审批
                isHas = await _orderScreenRepository.Queryable(hasHandled: !true, isAdmin: isAdmin)
                    .Includes(d => d.Order)
                    .Includes(d => d.ScreenDetails.Where(sd => sd.AuditUserId == _sessionContext.RequiredUserId).OrderByDescending(sd => sd.AuditTime).Take(1).ToList())
                    .AnyAsync(d => (d.Status == EScreenStatus.Apply || d.Status == EScreenStatus.Approval || (d.Status == EScreenStatus.SendBack && d.SendBackApply == false)));

                //甄别待审批是否有数据
                if (isHas)
                {
                    return isHas;
                }
                #endregion

                #region 退回待审批
                //退回待审批
                isHas = await _orderSendBackAuditRepository.Queryable()
                    .Where(d => d.State == ESendBackAuditState.Apply)
                    .WhereIF(_sessionContext.Roles.Contains("role_sysadmin") == false, x => x.SendBackOrgId == _sessionContext.RequiredUserId) // 123 系统管理员;
                    .AnyAsync();

                if (isHas)
                {
                    return isHas;
                }
                #endregion
            }
            else
            {
                #region 待办
                //待办
                var waitedDataList = await _orderRepository
                    .Queryable(hasHandled: false, isAdmin: isAdmin)
                    .Where(d => SqlFunc.Subqueryable<WorkflowStep>()
                        .Where(step => step.ExternalId == d.Id && step.Status != EWorkflowStepStatus.Handled &&
                                       ((step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) && step.HandlerId == _sessionContext.RequiredUserId) ||
                                        (step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == _sessionContext.RequiredOrgId) ||
                                        (step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) && _sessionContext.Roles.Contains(step.RoleId))))
                        .Any())
                    .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))
                    .OrderByDescending(d => new { d.IsUrgent, d.StartTime })
                    .Select(d => new HomeOrderDto
                    {
                        No = d.No,
                        OrderId = d.Id,
                        Title = d.Title,
                        AcceptType = d.AcceptType,
                        HotspotName = d.HotspotName,
                        Type = "Waited",
                        Time = d.ExpiredTime,
                        Status = d.Status,
                        ActualHandleTime = d.ActualHandleTime,
                        CounterSignType = d.CounterSignType
                    })
                    .ToListAsync();
                isHas = waitedDataList.Any();
                if (isHas)
                {
                    return isHas;
                }
                #endregion

                #region 已超期
                //已超期
                isHas = waitedDataList.Any(x => (x.Time < DateTime.Now && x.Status < EOrderStatus.Filed) ||
                                                                      (x.Time < x.ActualHandleTime && x.Status >= EOrderStatus.Filed));
                //超期是否有待办
                if (isHas)
                {
                    return isHas;
                }
                #endregion

                #region 会签待办
                //会签待办
                isHas = waitedDataList.Any(x => x.CounterSignType == ECounterSignType.Center || x.CounterSignType == ECounterSignType.Department);

                if (isHas)
                {
                    return isHas;
                }
                #endregion

                #region 甄别待审批
                //甄别待审批
                isHas = await _orderScreenRepository.Queryable(hasHandled: !true, isAdmin: isAdmin)
                    .Includes(d => d.Order)
                    .Includes(d => d.ScreenDetails.Where(sd => sd.AuditUserId == _sessionContext.RequiredUserId).OrderByDescending(sd => sd.AuditTime).Take(1).ToList())
                    .AnyAsync(d => (d.Status == EScreenStatus.Apply || d.Status == EScreenStatus.Approval || (d.Status == EScreenStatus.SendBack && d.SendBackApply == false)));

                if (isHas)
                {
                    return isHas;
                }

                #endregion

                #region 延期待审批
                //延期待审批
                isHas = await _orderDelayRepository.Queryable(canView: true, isAdmin: isAdmin)
                    .AnyAsync(d => d.DelayState == EDelayState.Examining);

                if (isHas)
                {
                    return isHas;
                }
                #endregion

                #region 甄别待申请
                //甄别待申请
                isHas = await _orderVisitedDetailRepository.Queryable(false, true)
                .Includes(x => x.OrderVisit)
                .Includes(x => x.OrderVisit, y => y.Order)
                .Includes(x => x.OrderVisit, y => y.Employee)
                .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.RequiredUserId && (
                    SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "1" ||
                    SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2" ||
                    SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "1" ||
                    SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "2"
                ))
               .AnyAsync();

                if (isHas)
                {
                    return isHas;
                }
                #endregion

                #region 退回待审批
                //退回待审批
                isHas = await _orderSendBackAuditRepository.Queryable()
                    .Where(d => d.State == ESendBackAuditState.Apply)
                    .WhereIF(_sessionContext.Roles.Contains("role_sysadmin") == false, x => x.SendBackOrgId == _sessionContext.RequiredOrgId) // 123 系统管理员;
                    .AnyAsync();
                if (isHas)
                {
                    return isHas;
                }

                #endregion

                #region 部门即将超期
                //部门即将超期
                isHas = await _orderRepository.Queryable(canView: !IsCenter)
                .Includes(d => d.OrderDelays)
                .Where(d => SqlFunc.Subqueryable<WorkflowStep>()
                        .Where(step => step.ExternalId == d.Id && step.Status != EWorkflowStepStatus.Handled &&
                        ((step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) && step.HandlerId == _sessionContext.RequiredUserId) ||
                        (step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == _sessionContext.RequiredOrgId) ||
                                        (step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) && _sessionContext.Roles.Contains(step.RoleId))))
                        .Any())
                    .Where(d => d.Status < EOrderStatus.Filed && DateTime.Now > d.NearlyExpiredTime && DateTime.Now < d.ExpiredTime)
                    .AnyAsync();
                if (isHas)
                {
                    return isHas;
                }

                #endregion
            }
            return isHas;
        }


        /// <summary>
        /// 获取用户加密后的用户名
        /// </summary>
        /// <returns></returns>
        [HttpGet("get_rsa_loginname")]
        public async Task<string> GetRASLoginName([FromQuery]bool IsUrlEncode)
        {
            var account = await _accountRepository.GetAsync(_sessionContext.RequiredUserId,HttpContext.RequestAborted);
            if (account == null)
            {
                throw UserFriendlyException.SameMessage("获取用户加密失败");
            }
            try
            {
                string userName = String.Empty;
                userName = System.Web.HttpUtility.UrlEncode(RSA.RSAEncrypt(account.UserName, RSA_Create.RSA_PUBLIC_KEY, "PEM"));
                return userName;
            }
            catch
            {
                throw UserFriendlyException.SameMessage("账号加密失败!");
            }
        }

        /// <summary>
        /// 获取老系统状态
        /// </summary>
        /// <returns></returns>
        [HttpGet("ishas_canhandler_old")]
        public async Task<bool?> IsHasCanHandlerOld()
        {
            var OldHotlineOrderState = _systemSettingCacheManager.GetSetting(SettingConstants.OldHotlineOrderState).SettingValue[0];

            var account = await _accountRepository.GetAsync(_sessionContext.RequiredUserId, HttpContext.RequestAborted);
            if (account == null)
            {
                throw UserFriendlyException.SameMessage("获取用户加密失败");
            }
            try
            {
                string userName = String.Empty;
                userName = System.Web.HttpUtility.UrlEncode(RSA.RSAEncrypt(account.UserName, RSA_Create.RSA_PUBLIC_KEY, "PEM"));
                var client = _httpClientFactory.CreateClient();
                client.DefaultRequestHeaders.ConnectionClose = true;
                using var responseMessage = await client.GetAsync(OldHotlineOrderState + userName,HttpContext.RequestAborted);
                using var respContent = responseMessage.Content;
                var respContentString = await respContent.ReadAsStringAsync(HttpContext.RequestAborted);
                var result = Newtonsoft.Json.JsonConvert.DeserializeObject<HotlineStateResult>(respContentString);
                return result?.Result;
            }
            catch (Exception ex)
            {
                throw UserFriendlyException.SameMessage("账号加密失败!"+ex.Message);
            }
        }
    }
}
