using DotNetCore.CAP;
using Hotline.File;
using Hotline.Orders;
using Hotline.Share.Enums.JudicialManagement;
using MapsterMapper;
using Microsoft.Extensions.Logging;
using XF.Domain.Authentications;
using XF.Domain.Cache;
using XF.Domain.Dependency;
using XF.Domain.Repository;

namespace Hotline.JudicialManagement
{
    public class JudicialManagementOrdersService : IJudicialManagementOrdersService, IScopeDependency
    {
        private readonly ISessionContext _sessionContext;
        private readonly ICapPublisher _capPublisher;
        private readonly IMapper _mapper;
        private readonly ILogger<OrderDomainService> _logger;
        private readonly IFileRepository _fileRepository;
        private readonly ITypedCache<CacheOrderNO> _cacheOrderNo;
        private readonly IRepository<JudicialManagementOrders> _judicialManagementOrdersRepository;

        public JudicialManagementOrdersService(ISessionContext sessionContext,
               ICapPublisher capPublisher,
               IMapper mapper,
               ILogger<OrderDomainService> logger,
               IFileRepository fileRepository,
               ITypedCache<CacheOrderNO> cacheOrderNo,
               IRepository<JudicialManagementOrders> judicialManagementOrdersRepository)
        {
            _sessionContext = sessionContext;
            _capPublisher = capPublisher;
            _mapper = mapper;
            _logger = logger;
            _fileRepository = fileRepository;
            _cacheOrderNo = cacheOrderNo;
            _judicialManagementOrdersRepository = judicialManagementOrdersRepository;
        }

        public async Task<string> AddAsync(JudicialManagementOrders order, bool autoAccept = false, CancellationToken cancellationToken = default)
        {
            if (autoAccept)
            {
                order.AutoAccept(_sessionContext.RequiredUserId, _sessionContext.UserName, _sessionContext.StaffNo, _sessionContext.RequiredOrgId, _sessionContext.OrgName);
            }
            order.Init();
            var no = GenerateNewOrderNoSF();
            order.No = no + "SF";
            order.Password = Random.Shared.Next(100000, 1000000).ToString();
            order.ProvinceNo ??= GenerateNewProvinceNoSF(no, order.SourceChannelCode);
            order.OrderSoure = EOrderSoure.Enforcement;
            return await _judicialManagementOrdersRepository.AddAsync(order, cancellationToken);
        }

        private string GenerateNewOrderNoSF()
        {
            var today = DateTime.Today;
            var cacheKey = $"{today:yyyyMMdd}SF";
            var cacheOrderNo = _cacheOrderNo.GetOrSet(cacheKey, f =>
            {
                var todayOrderCount = _judicialManagementOrdersRepository.Queryable()
                    .CountAsync(d => d.CreationTime.Date == today.Date)
                    .GetAwaiter()
                    .GetResult();
                return new CacheOrderNO { TotalCount = todayOrderCount };
            }, TimeSpan.FromDays(1));
            cacheOrderNo!.TotalCount += 1;
            var no = GenerateOrderNo(today, cacheOrderNo.TotalCount);
            _cacheOrderNo.Set(cacheKey, cacheOrderNo);
            return no;
        }

        private string GenerateNewProvinceNoSF(string no, string sourceChannelCode)
        {
            //诉求渠道+成员单位标识+行政区划代码+年月日+流水号
            //成员单位标识  99
            //宜宾市 511500  市级
            var today = DateTime.Today;
            //var count = no.Substring(no.Length - 5);

            //todo 双系统并行暂时执行此方案
            var count = no.Substring(no.Length - 4);
            count = (Convert.ToInt32(count) + 500000).ToString();

            var provinceCodes = new[] { "RGDH", "WX", "WB", "AP", "WZ", "YJ", "SCZWFWW", "XCX", "QT" };
            var prefix = provinceCodes.Any(d => d.Equals(sourceChannelCode))
                ? sourceChannelCode
                : "QT";
            return $"{prefix}99511500{today:yyMMdd}{count}";
        }


        private string GenerateOrderNo(DateTime today, int count)
        {
            return $"{today:yyyyMMdd}{count:000000}";
        }

    }

    public class CacheOrderNO
    {
        public int TotalCount { get; set; }
    }
}

