using Hotline.Api.Controllers;
using Hotline.Caching.Interfaces;
using Hotline.Configurations;
using Hotline.EventBus;
using Hotline.Identity.Accounts;
using Hotline.Identity.Roles;
using Hotline.Orders;
using Hotline.Push.FWMessage;
using Hotline.Push.Notifies;
using Hotline.Settings;
using Hotline.Share.Dtos;
using Hotline.Share.Dtos.Push;
using Hotline.Share.Enums.Order;
using Hotline.Share.Enums.Push;
using Hotline.Share.Tools;
using Hotline.Tests.Mock;
using Hotline.ThirdAccountDomainServices;
using Hotline.ThirdAccountDomainServices.Interfaces;
using Hotline.Users;
using Mapster;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Shouldly;
using XF.Domain.Cache;
using XF.Domain.Repository;

namespace Hotline.Tests.Domain;
public class OrderVisitDomainServiceTest : TestBase
{
    private readonly IOrderVisitDomainService _orderVisitDomainService;
    private readonly IOrderVisitRepository _orderVisitRepository;
    private readonly IRepository<OrderVisitDetail> _orderVisitDetailRepository;
    private readonly Publisher _publisher;
    private readonly IOrderRepository _orderRepository;
    private readonly OrderServiceMock _orderServiceMock;
    private readonly ISettingOrderVisitSmsReplyRuleRepository _settingOrderVisitSmsReplyRuleRepository;
    private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
    private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
    private readonly ISystemLogRepository _logRepository;

    public OrderVisitDomainServiceTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IOrderVisitDomainService orderVisitDomainService, IOrderVisitRepository orderVisitRepository, IRepository<OrderVisitDetail> orderVisitDetailRepository, Publisher publisher, IOrderRepository orderRepository, OrderServiceMock orderServiceMock, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdService, IThirdAccountRepository thirdAccount, ISettingOrderVisitSmsReplyRuleRepository settingOrderVisitSmsReplyRuleRepository, ISystemDicDataCacheManager systemDicDataCacheManager, IOptionsSnapshot<AppConfiguration> appOptions, ISystemLogRepository logRepository, ITypedCache<SystemSetting> cacheSettingData, ThirdAccounSupplierFactory thirdAccountDomainFactory, IServiceProvider serviceProvider) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdService, thirdAccount, cacheSettingData, thirdAccountDomainFactory, serviceProvider)
    {
        _orderVisitDomainService = orderVisitDomainService;
        _orderVisitRepository = orderVisitRepository;
        _orderVisitDetailRepository = orderVisitDetailRepository;
        _publisher = publisher;
        _orderRepository = orderRepository;
        _orderServiceMock = orderServiceMock;
        _settingOrderVisitSmsReplyRuleRepository = settingOrderVisitSmsReplyRuleRepository;
        _systemDicDataCacheManager = systemDicDataCacheManager;
        _appOptions = appOptions;
        _logRepository = logRepository;
    }



    //[Fact]
    public async Task UpdateSmsReplyDefault_Test()
    {
        var visit = await _orderVisitRepository
            .Queryable()
            .Where(m => m.VisitState == EVisitState.SMSVisiting)
            .OrderByDescending(m => m.CreationTime)
            .FirstAsync();
        visit.ShouldNotBeNull("缺少测试数据");

        var msg = new MessageDto()
        {
            ExternalId = visit.Id,
        };

        await _orderVisitDomainService.UpdateSmsReplyDefaultAsync(msg);
        var replyTxt = "默认满意";
        var smsReply = _orderVisitDomainService.GetVisitEvaluateByReplyTxt("默认满意");
        var kv = smsReply.GetOrgProcessingResults(_systemDicDataCacheManager.VisitSatisfaction);
        var order = await _orderRepository.Queryable()
            .Includes(m => m.OrderVisits)
            .Where(m => m.OrderVisits.Any(o => o.Id == visit.Id))
            .FirstAsync();
        order.Status.ShouldBe(EOrderStatus.Visited);

        var visitDetail = await _orderVisitDetailRepository.Queryable()
            .Where(m => m.VisitId == visit.Id)
            .ToListAsync();
        foreach (var detail in visitDetail)
        {
            if (detail.VisitTarget == EVisitTarget.Seat)
            {
                var seatEvaluate = smsReply.SeatEvaluate;
                var voiceEvaluate = smsReply.VoiceEvaluate;

                detail.SeatEvaluate.ShouldBe(seatEvaluate);
                detail.VoiceEvaluate.ShouldBe(voiceEvaluate);
            }
            if (detail.VisitTarget == EVisitTarget.Org)
            {
                detail.OrgProcessingResults.Key.ShouldBe(kv.Key);
                detail.OrgProcessingResults.Value.ShouldBe(kv.Value);

                detail.OrgHandledAttitude.Key.ShouldBe(kv.Key);
                detail.OrgHandledAttitude.Value.ShouldBe(kv.Value);
            }
        }
    }

    //[Fact]
    public async Task OnSmsUpdate_Test()
    {
        var data = new Message() { IsSmsReply = true, SmsReplyContent = "1", PushBusiness = EPushBusiness.VisitSms };
        await _publisher.PublishAsync(data.Adapt<ReceiveMessageNotify>(), PublishStrategy.ParallelNoWait, new CancellationToken());
    }

    [Theory]
    [InlineData("4", "SMSUnsatisfied", "2", "不满意", "不满意", "Published")]
    [InlineData("1", "Visited", "5", "非常满意", "非常满意")]
    [InlineData("2", "Visited", "4", "满意", "满意")]
    [InlineData("3", "Visited", "4", "满意", "一般")]
    [InlineData("5", "SMSUnsatisfied", "2", "不满意", "不满意", "Published")]
    [InlineData("默认满意", "Visited", "0", "默认满意", "超过48小时自动回访")]
    [InlineData("都没有办理好", "SMSUnsatisfied", "", "", "都没有办理好", "Published", "YiBin")]
    [InlineData("1", "Visited", "4", "满意", "满意", "Visited", "YiBin")]
    [InlineData("2", "SMSUnsatisfied", "2", "不满意", "不满意", "Published", "YiBin")]
    [InlineData("智能电话回访满意", "Visited", "4", "满意", "满意", "Visited")]
    [InlineData("智能电话回访不满意", "Visited", "2", "不满意", "不满意", "Visited")]
    [InlineData("智能电话回访不作评价", "Visited", "7", "未做评价", "未做评价", "Visited")]
    public async Task UpdateSmsReply_Test(string content, string visitState, string orgResuktKey, string orgResuktValue, string visitContent, string visited = "Visited", string appScope = "ZiGong")
    {
        if (appScope != "ZiGong")
            ChangeAppScopeYiBin();
        else
            ChangeAppScopeZiGong();
        var appScopeFile = _appOptions.Value.AppScope;
        SetZuoXi();
        var order = _orderServiceMock.CreateOrder()
            .办理到一级部门()
            .办理到二级部门(Set一级部门)
            .办理一级部门汇总(Set二级部门)
            .办理到归档(Set一级部门)
            .发布工单(SetZuoXi)
            .发送回访短信(SetZuoXi)
            .GetCreateResult();
        order.Id.ShouldNotBeNull();

        var visit = await _orderVisitRepository.Queryable()
            .Includes(m => m.Order)
            .Where(m => m.VisitState == EVisitState.SMSVisiting)
            .OrderByDescending(m => m.CreationTime)
            .FirstAsync();
        if (visit == null) return;
        visit.ShouldNotBeNull("缺少测试数据");

        var message = new MessageDto { ExternalId = visit.Id, IsSmsReply = true, SmsReplyContent = content, TelNumber = visit.Order.Contact };
        var dto = new PushReceiveMessageDto();
        await _orderVisitDomainService.UpdateSmsReplyAsync(message);
        visit = _orderVisitRepository.Get(visit.Id);
        visit.VisitState.ShouldBe(visitState.ToEnum<EVisitState>());
        if (orgResuktKey.NotNullOrEmpty())
        {
            visit.NowEvaluate.ShouldNotBeNull();
            visit.NowEvaluate.Key.ShouldBe(orgResuktKey);
            visit.NowEvaluate.Value.ShouldBe(orgResuktValue);
        }
        var orderEntity = await _orderRepository.GetAsync(order.Id);
        orderEntity.ShouldNotBeNull();
        orderEntity.Status.ShouldBe(visited.ToEnum<EOrderStatus>());
        if (content == "4" || content == "5" || content == "不满意" || content == "非常不满意" || content == "都没有办理好")
        {
            visit.VisitType.ShouldBeNull();
        }

        var smsReply = _orderVisitDomainService.GetVisitEvaluateByReplyTxt(content);
        var log = _logRepository.Queryable().Where(m => m.Name == "短信回访-回复内容匹配结果" && m.Remark == order.No).First();
        log.ShouldNotBeNull();
        await _orderVisitDetailRepository.Queryable()
            .Where(m => m.VisitId == visit.Id && m.VisitTarget == EVisitTarget.Org)
            .FirstAsync()
            .Then(org =>
            {
                if (content != "都没有办理好")
                {
                    org.OrgProcessingResults.ShouldNotBeNull();
                    org.OrgProcessingResults.Key.ShouldBe(orgResuktKey);
                    org.OrgProcessingResults.Value.ShouldBe(orgResuktValue);
                    org.VisitContent.ShouldBe(visitContent);

                    // 验证跟新工单上的字段是否成功
                    if (new string[] { "4", "5", "不满意", "非常不满意"}.Contains(content) == false)
                    {
                        if (appScope != "YiBin" && content != "2")
                        {
                            orderEntity.OrgProcessingResults.ShouldNotBeNull();
                            orderEntity.OrgProcessingResults.Key.ShouldBe(orgResuktKey);
                            orderEntity.OrgProcessingResults.Value.ShouldBe(orgResuktValue);
                        }
                    }

                    if (appScope != "YiBin")
                    {
                        org.OrgHandledAttitude.ShouldNotBeNull();
                        org.OrgHandledAttitude.Key.ShouldBe(orgResuktKey);
                        org.OrgHandledAttitude.Value.ShouldBe(orgResuktValue);
                    }
                    if (smsReply.IsReplyToOrgVisitContent == true)
                    {
                        org.VisitContent = content;
                    }
                }
                return Task.CompletedTask;
            });
        await _orderVisitDetailRepository.Queryable()
          .Where(m => m.VisitId == visit.Id && m.VisitTarget == EVisitTarget.Seat)
          .FirstAsync()
          .Then(seat =>
          {
              if (content != "都没有办理好")
              {

                  // 验证跟新工单上的字段是否成功
                  if (new string[] { "4", "5", "不满意", "非常不满意", "都没有办理好" }.Contains(content) == true)
                  {
                      seat.SeatEvaluate.ShouldNotBe(ESeatEvaluate.NoSatisfied);
                      seat.SeatEvaluate.ShouldNotBe(ESeatEvaluate.VeryNoSatisfied);
                      seat.VoiceEvaluate.ShouldNotBe(EVoiceEvaluate.NoSatisfied);
                      seat.VoiceEvaluate.ShouldNotBe(EVoiceEvaluate.VeryNoSatisfied);
                  }
                  else
                  {
                      if (smsReply.SeatEvaluate != null)
                          seat.SeatEvaluate.ShouldBe(smsReply.SeatEvaluate);
                      if (smsReply.VoiceEvaluate != null)
                          seat.VoiceEvaluate.ShouldBe(smsReply.VoiceEvaluate);
                  }

              }
              return Task.CompletedTask;
          });
    }

    [Theory]
    [InlineData("1", "非常满意", "Visited", "", "", "非常满意|5")]
    [InlineData("2", "满意", "Visited", "", "", "满意|4")]
    [InlineData("3", "一般", "Visited", "", "", "满意|4")]
    [InlineData("4", "不满意", "SMSUnsatisfied", "", "", "不满意|2")]
    [InlineData("5", "不满意", "SMSUnsatisfied", "", "", "不满意|2")]
    //[InlineData("默认满意", "超过48小时自动回访", "Visited", "DefaultSatisfied", "DefaultSatisfied", "默认满意|0")]
    [InlineData("默认满意", "超过48小时自动回访", "Visited", "", "", "默认满意|0")]
    [InlineData("1非常满意", "非常满意", "Visited", "", "", "非常满意|5")]
    public void GetVisitEvaluateByReplyTxt_Test(string replyTxt, string assertReplyTxt, string visitState, string seatEvaluate, string voiceEvaluate, string kv)
    {
        var smsReply = _orderVisitDomainService.GetVisitEvaluateByReplyTxt(replyTxt);
        var replyString = smsReply.VisitContent;
        replyString.ShouldBe(assertReplyTxt);

        var visitStateEnum = smsReply.VisitState;
        visitStateEnum.ShouldBe(visitState.ToEnum<EVisitState>());

        if (seatEvaluate.NotNullOrEmpty())
        {
            var seatEvaluateEnum = smsReply.SeatEvaluate;
            seatEvaluateEnum.ShouldBe(seatEvaluate.ToEnum<ESeatEvaluate>());
        }

        if (voiceEvaluate.NotNullOrEmpty())
        {
            var voiceEvaluateEnum = smsReply.VoiceEvaluate;
            voiceEvaluateEnum.ShouldBe(voiceEvaluate.ToEnum<EVoiceEvaluate>());
        }

        var kvResult = smsReply.GetOrgProcessingResults(_systemDicDataCacheManager.VisitSatisfaction);
        var sp = kv.Split('|');
        var kV = new Kv(sp[1].ToString(), sp[0].ToString());
        kvResult.Key.ShouldBe(kV.Key);
        kvResult.Value.ShouldBe(kV.Value);
    }

    [Fact]
    public async Task Init_SettingOrderVisitSmsReplyRule_Data()
    {
        IEnumerable<SettingOrderVisitSmsReplyRule> entities = [
            new () {Name = "非常满意的规则", AppScope = "ZiGong", ReplyRegular = "1", VisitContent = "非常满意", VisitState = EVisitState.Visited, SeatEvaluate = null,VoiceEvaluate = null,OrgProcessingResults=5, OrgHandledAttitude = 5, VisitType = EVisitType.SmsVisit, SortOrder = 1},
            new () {Name = "满意的规则", AppScope = "ZiGong", ReplyRegular = "2", VisitContent = "满意", VisitState = EVisitState.Visited, SeatEvaluate = null,VoiceEvaluate = null,OrgProcessingResults=4, OrgHandledAttitude = 4 , VisitType = EVisitType.SmsVisit, SortOrder = 2},
            new () {Name = "一般的规则", AppScope = "ZiGong", ReplyRegular = "3", VisitContent = "一般", VisitState = EVisitState.Visited, SeatEvaluate = null, VoiceEvaluate = null,OrgProcessingResults= 4, OrgHandledAttitude = 4 , VisitType = EVisitType.SmsVisit, SortOrder = 3},
            new () {Name = "不满意的规则", AppScope = "ZiGong", ReplyRegular = "4", VisitContent = "不满意", VisitState = EVisitState.SMSUnsatisfied, SeatEvaluate = null,VoiceEvaluate = null,OrgProcessingResults=2, OrgHandledAttitude = 2 , VisitType = null, SortOrder = 4},
            new () {Name = "非常不满意的规则", AppScope = "ZiGong", ReplyRegular = "5", VisitContent = "不满意", VisitState = EVisitState.SMSUnsatisfied, SeatEvaluate = null, VoiceEvaluate = null,OrgProcessingResults=2, OrgHandledAttitude = 2, VisitType = null, SortOrder = 5},
            new () {Name = "默认满意的规则", AppScope = "ZiGong", ReplyRegular = "默认满意", VisitContent = "超过48小时自动回访", VisitState = EVisitState.Visited, SeatEvaluate = null, VoiceEvaluate = null,OrgProcessingResults=0, OrgHandledAttitude = 0, VisitType = EVisitType.SmsVisit, SortOrder = 0},
            new () {Name = "用户回答非1,2,3,4,5的匹配规则", AppScope = "ZiGong", ReplyRegular = "^(?!.*[12345]).*$", VisitContent = "默认满意", VisitState = EVisitState.Visited, SeatEvaluate = null, VoiceEvaluate = null,OrgProcessingResults=0, OrgHandledAttitude = 0, VisitType = EVisitType.SmsVisit, SortOrder = 6},
            new () {Name = "对部门处理结果满意", AppScope = "YiBin", ReplyRegular = "1", VisitContent = "满意", VisitState = EVisitState.Visited, SeatEvaluate = null,VoiceEvaluate = null,OrgProcessingResults = 4 , OrgHandledAttitude = null, VisitType = EVisitType.SmsVisit, SortOrder = 1},
            new () {Name = "默认满意的规则", AppScope = "YiBin", ReplyRegular = "默认满意", VisitContent = "超过48小时自动回访", VisitState = EVisitState.Visited, SeatEvaluate = null,VoiceEvaluate = null,OrgProcessingResults=0, OrgHandledAttitude = 0 , VisitType = EVisitType.SmsVisit, SortOrder = 0},
            new () {Name = "对部门处理结果不满意的规则", AppScope = "YiBin", ReplyRegular = "2", VisitContent = "不满意", VisitState = EVisitState.SMSUnsatisfied, SeatEvaluate = null,VoiceEvaluate = null,OrgProcessingResults=2, OrgHandledAttitude = null , VisitType = null, SortOrder = 2},
            new () {Name = "用户回复的非1和2的规则", AppScope = "YiBin", ReplyRegular = "^(?!.*[12]).*$", VisitContent = "不满意", VisitState = EVisitState.SMSUnsatisfied, SeatEvaluate = null,VoiceEvaluate = null,OrgProcessingResults= null, OrgHandledAttitude = null , VisitType = null, SortOrder = 3, IsReplyToOrgVisitContent = true},

            new () {Name = "非常满意的规则", AppScope = "LuZhou", ReplyRegular = "1", VisitContent = "非常满意", VisitState = EVisitState.Visited, SeatEvaluate = null,VoiceEvaluate = null,OrgProcessingResults=5, OrgHandledAttitude = 0, VisitType = EVisitType.SmsVisit, SortOrder = 1},
            new () {Name = "满意的规则", AppScope = "LuZhou", ReplyRegular = "2", VisitContent = "满意", VisitState = EVisitState.Visited, SeatEvaluate = null,VoiceEvaluate = null,OrgProcessingResults=4, OrgHandledAttitude = 0 , VisitType = EVisitType.SmsVisit, SortOrder = 2},
            new () {Name = "一般的规则", AppScope = "LuZhou", ReplyRegular = "3", VisitContent = "一般", VisitState = EVisitState.Visited, SeatEvaluate = null, VoiceEvaluate = null,OrgProcessingResults= 4, OrgHandledAttitude = 0 , VisitType = EVisitType.SmsVisit, SortOrder = 3},
            new () {Name = "不满意的规则", AppScope = "LuZhou", ReplyRegular = "4", VisitContent = "不满意", VisitState = EVisitState.SMSUnsatisfied, SeatEvaluate = null,VoiceEvaluate = null,OrgProcessingResults=2, OrgHandledAttitude = 0 , VisitType = null, SortOrder = 4},
            new () {Name = "非常不满意的规则", AppScope = "LuZhou", ReplyRegular = "5", VisitContent = "不满意", VisitState = EVisitState.SMSUnsatisfied, SeatEvaluate = null, VoiceEvaluate = null,OrgProcessingResults=2, OrgHandledAttitude = 0, VisitType = null, SortOrder = 5},
            new () {Name = "默认满意的规则", AppScope = "LuZhou", ReplyRegular = "默认满意", VisitContent = "超过48小时自动回访", VisitState = EVisitState.Visited, SeatEvaluate = null, VoiceEvaluate = null,OrgProcessingResults=0, OrgHandledAttitude = 0, VisitType = EVisitType.SmsVisit, SortOrder = 0},
            new () {Name = "用户回答非1,2,3,4,5的匹配规则", AppScope = "LuZhou", ReplyRegular = "^(?!.*[12345]).*$", VisitContent = "默认满意", VisitState = EVisitState.Visited, SeatEvaluate = null, VoiceEvaluate = null,OrgProcessingResults=0, OrgHandledAttitude = 0, VisitType = EVisitType.SmsVisit, SortOrder = 6},

            ];

        foreach (var item in entities)
        {
            item.UniqueKey = (item.AppScope + item.ReplyRegular).GetMD5();
            if (await _settingOrderVisitSmsReplyRuleRepository.AnyAsync(m => m.UniqueKey == item.UniqueKey) == false)
                await _settingOrderVisitSmsReplyRuleRepository.AddAsync(item);
        }
    }
}
