using AutoFixture;
using Hotline.Api.Controllers;
using Hotline.Application.CallCenter;
using Hotline.CallCenter.Calls;
using Hotline.CallCenter.Tels;
using Hotline.Identity.Accounts;
using Hotline.Identity.Roles;
using Hotline.Orders;
using Hotline.Repository.SqlSugar.Extensions;
using Hotline.Settings;
using Hotline.Share.Dtos.CallCenter;
using Hotline.Share.Dtos.Order;
using Hotline.Share.Enums.CallCenter;
using Hotline.ThirdAccountDomainServices;
using Hotline.ThirdAccountDomainServices.Interfaces;
using Hotline.Users;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using SqlSugar.Extensions;
using XF.Domain.Cache;
using XF.Domain.Repository;

namespace Hotline.Tests.Application;
public class DefaultCallApplicationTest : TestBase
{
    private readonly XingTangCallApplication _defaultCallApplication;
    private readonly IOrderVisitRepository _orderVisitRepository;
    private readonly IRepository<CallNative> _callNativeRepository;
    public readonly IFixture _fixture;
    private readonly IOrderRepository _orderRepository;
    private readonly ICallTelClient _callTelClient;

    public DefaultCallApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, XingTangCallApplication defaultCallApplication, IOrderVisitRepository orderVisitRepository, IRepository<CallNative> callNativeRepository, IOrderRepository orderRepository, IThirdIdentiyService thirdService, IThirdAccountRepository thirdAccount, ITypedCache<SystemSetting> cacheSettingData, ICallTelClient callTelClient, ThirdAccounSupplierFactory thirdAccountDomainFactory, IServiceProvider serviceProvider) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdService, thirdAccount, cacheSettingData, thirdAccountDomainFactory, serviceProvider)
    {
        _fixture = new Fixture();
        _defaultCallApplication = defaultCallApplication;
        _orderVisitRepository = orderVisitRepository;
        _callNativeRepository = callNativeRepository;
        _orderRepository = orderRepository;
        _callTelClient = callTelClient;
    }

    [Theory]
    [InlineData(16, 0)]
    [InlineData(0, 100)]
    [InlineData(1, 301)]
    [InlineData(2, 202)]
    [InlineData(3, 200)]
    [InlineData(17, 303)]
    [InlineData(30, 400)]
    public async Task GetStatus_Test(int xingtang, int hotline)
    { 
        var result = await _callTelClient.GetStatusAsync(hotline);
        result.ShouldBe(xingtang);
    }

    [Fact]
    public async Task QueryCallsFixed_Test()
    {
        var inDto = new QueryCallsFixedDto();
        //inDto.CallStartTimeEnd = DateTime.Now;
        //inDto.CallStartTimeStart = "2024/10/01 00:00:00".ObjToDate();
        //inDto.StaffNo = "8029";
        inDto.Type = 2;
        inDto.ToNo = "15892228077";

        var items = await _defaultCallApplication.QueryCallsFixedAsync(inDto, new CancellationToken()).ToPageListWithoutTotalAsync(inDto, CancellationToken.None);
        items.ShouldNotBeNull();
    }

    [Fact]
    public async Task QueryCallsFixedThree_Test()
    {
        var inDto = new QueryCallsFixedDto();
        inDto.CallStartTimeEnd = DateTime.Now;
        inDto.CallStartTimeStart = "2024/11/08 00:00:00".ObjToDate();
        inDto.FromNo = "8205175";

        var items1 = await _defaultCallApplication.QueryCallsFixedAsync(inDto, new CancellationToken()).ToPageListWithoutTotalAsync(inDto, CancellationToken.None);
        items1.ShouldNotBeNull();
        foreach (var item in items1.Where(m => m.IsOrder))
        {
            item.Title.ShouldNotBeNull();
            item.OrderId.ShouldNotBeNull();
            item.OrderNo.ShouldNotBeNull();
        }

        inDto.ToNo = "13990006670";
        inDto.FromNo = null;
        inDto.Type = 2;
        var items = await _defaultCallApplication.QueryCallsFixedAsync(inDto, new CancellationToken()).ToPageListWithoutTotalAsync(inDto, CancellationToken.None);
        items.ShouldNotBeNull();
        items.Count().ShouldNotBe(0, "通过被叫号码查询失败");
        foreach (var item in items.Where(m => m.IsVisit))
        {
            item.Title.ShouldNotBeNull();
            item.OrderId.ShouldNotBeNull();
            item.OrderNo.ShouldNotBeNull();
        }
    }

    [Fact]
    public async Task GetCall_Test()
    {
        var result = await _defaultCallApplication.GetCallAsync("01J2ZP7J6X3K5FXN4B5KD54FBA", CancellationToken.None);
        result.ShouldNotBeNull();
        result = await _defaultCallApplication.GetCallAsync("2024062419085100943CTI", CancellationToken.None);
        result.ShouldNotBeNull();
    }

    [Fact]
    public async Task OrderVisitRelevanceCallId_Test()
    {
        var inDto = new VisitDto();
        inDto.CallId = "202411151100300273100069FLOW";
        inDto.Id = "08dd046b-b3b3-4ccf-8a15-09133d27dce0";
        await _defaultCallApplication.OrderVisitRelevanceCallIdAsync(inDto, CancellationToken.None);

        var visit = await _orderVisitRepository.GetAsync(inDto.Id);
        visit.CallId.ShouldBe("01JCPW9ZJ2683ZVN69ZGNZ0A4B");
    }

    /// <summary>
    /// 测试三方通话后, 工单保存时没有关联到正确的通话记录, 使用本方法能不能修复
    /// 测试如果通话记录有两通都是呼入的,就不需要修复了
    /// </summary>
    /// <returns></returns>
    [Fact]
    public async Task OrderRelateCallHandler_Test()
    {
        var callNo = DateTime.Now.ToString("yyyyMMddhhmmss") + "Flow";
        var inDto = _fixture.Build<CallNative>()
            .With(m => m.Id, Ulid.NewUlid().ToString())
            .With(m => m.CallNo, callNo)
            .With(m => m.Direction, ECallDirection.In)
            .With(m => m.IsDeleted, false)
            .Create();
        await _callNativeRepository.AddAsync(inDto);

        var inDto2 = _fixture.Build<CallNative>()
            .With(m => m.Id, Ulid.NewUlid().ToString())
            .With(m => m.Direction, ECallDirection.Out)
            .With(m => m.CallNo, callNo)
            .With(m => m.IsDeleted, false)
            .Create();
        await _callNativeRepository.AddAsync(inDto2);

        var orderId = await _orderRepository.Queryable()
            .Where(m => string.IsNullOrEmpty(m.CallId))
            .OrderByDescending(m => m.CreationTime)
            .Select(m => m.Id)
            .FirstAsync();

        await _orderRepository.Updateable()
            .SetColumns(m => m.CallId == inDto2.Id)
            .Where(m => m.Id == orderId)
            .ExecuteCommandAsync();

        await _defaultCallApplication.OrderRelateCallHandlerAsync(orderId, CancellationToken.None);
        (await _orderRepository.Queryable().Where(m => m.Id == orderId).Select(m => m.CallId).FirstAsync())
            .ShouldBe(inDto.Id);

        // 测试如果通话记录有两通都是呼入的,就不需要修复了

        callNo = DateTime.Now.ToString("yyyyMMddhhmmss") + "Flow";
        inDto = _fixture.Build<CallNative>()
            .With(m => m.Id, Ulid.NewUlid().ToString())
            .With(m => m.CallNo, callNo)
            .With(m => m.Direction, ECallDirection.In)
            .With(m => m.Duration, 20)
            .With(m => m.IsDeleted, false)
            .Create();
        await _callNativeRepository.AddAsync(inDto);

        inDto2 = _fixture.Build<CallNative>()
            .With(m => m.Id, Ulid.NewUlid().ToString())
            .With(m => m.Direction, ECallDirection.In)
            .With(m => m.CallNo, callNo)
            .With(m => m.Duration, 10)
            .With(m => m.IsDeleted, false)
            .Create();
        await _callNativeRepository.AddAsync(inDto2);

        orderId = await _orderRepository.Queryable()
            .Where(m => string.IsNullOrEmpty(m.CallId))
            .OrderByDescending(m => m.CreationTime)
            .Select(m => m.Id)
            .FirstAsync();

        await _orderRepository.Updateable()
            .SetColumns(m => m.CallId == inDto2.Id)
            .Where(m => m.Id == orderId)
            .ExecuteCommandAsync();

        await _defaultCallApplication.OrderRelateCallHandlerAsync(orderId, CancellationToken.None);
        (await _orderRepository.Queryable().Where(m => m.Id == orderId).Select(m => m.CallId).FirstAsync())
            .ShouldBe(inDto2.Id);
    }

    //[Fact]
    public async Task OrderRelateCallHandler2_Test()
    {
        var orderId = "08dd0d21-0221-43cf-8230-3179dc6aefca";
        await _defaultCallApplication.OrderRelateCallHandlerAsync(orderId, CancellationToken.None);
    }
}
