using AutoFixture;
using Castle.DynamicProxy;
using Hotline.Api.Controllers;
using Hotline.Application.Tests.Infrastructure;
using Hotline.Application.Tests.Mock;
using Hotline.Caching.Interfaces;
using Hotline.Caching.Services;
using Hotline.FlowEngine.Notifications;
using Hotline.FlowEngine.WorkflowModules;
using Hotline.Identity.Accounts;
using Hotline.Identity.Roles;
using Hotline.Orders;
using Hotline.Settings;
using Hotline.Settings.Hotspots;
using Hotline.Share.Dtos.File;
using Hotline.Share.Dtos.FlowEngine;
using Hotline.Share.Dtos.Order;
using Hotline.Share.Dtos.Users;
using Hotline.Share.Enums.FlowEngine;
using Hotline.Share.Enums.Order;
using Hotline.Share.Enums.Settings;
using Hotline.Share.Tools;
using Hotline.Users;
using MediatR;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Shouldly;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XF.Domain.Authentications;
using XF.Domain.Repository;

namespace Hotline.Application.Tests.Controller;
public class OrderControllerTest : TestBase
{
    private readonly OrderController _orderController;
    private readonly IRepository<Hotspot> _hotspotRepository;
    private readonly IOrderRepository _orderRepository;
    private readonly OrderServiceMock _orderServiceMock;
    private readonly IRepository<OrderPublish> _orderPublishRepository;
    private readonly INotificationHandler<EndWorkflowNotify> _orderPublishEndWorkflowHandler;
    private readonly IOrderVisitRepository _orderVisitRepository;
    private readonly IRepository<SystemSetting> _systemSettingRepository;
    private readonly ISystemSettingCacheManager _systemSettingCacheManager;

    public OrderControllerTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IRepository<Hotspot> hotspotRepository, OrderController orderController, IOrderRepository orderRepository, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, OrderServiceMock orderServiceMock, IRepository<OrderPublish> orderPublishRepository, INotificationHandler<EndWorkflowNotify> orderPublishEndWorkflowHandler, IOrderVisitRepository orderVisitRepository, IRepository<SystemSetting> systemSettingRepository, ISystemSettingCacheManager systemSettingCacheManager) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository)
    {
        _hotspotRepository = hotspotRepository;
        _orderController = orderController;
        _orderController.ControllerContext = new ControllerContext
        {
            HttpContext = new DefaultHttpContext()
        };
        _orderRepository = orderRepository;
        _orderServiceMock = orderServiceMock;
        _orderPublishRepository = orderPublishRepository;
        _orderPublishEndWorkflowHandler = orderPublishEndWorkflowHandler;
        _orderVisitRepository = orderVisitRepository;
        _systemSettingRepository = systemSettingRepository;
        _systemSettingCacheManager = systemSettingCacheManager;
    }


    /// <summary>
    /// 创建工单并派送给派单员
    /// </summary>
    /// <returns></returns>
    [Fact]
    public async Task ToPaiDanYuan_Test()
    {
        SetZuoXi();
        var order = _orderServiceMock.CreateOrder()
            .办理到派单员()
            .GetCreateResult();
        order.ShouldNotBeNull();
    }

    /// <summary>
    /// 验证中心直办工单归档后自动发布
    /// 是否推诿, 是否不积极
    /// </summary>
    /// <returns></returns>
    [Fact]
    public async Task AutoPublish_Test()
    {
        SetZuoXi();
        var order = _orderServiceMock.CreateOrder()
            .办理到派单员()
            .办理到归档(SetPaiDanYuan, data =>
            {
                data.IsEvasive = true;
                data.IsInactively = true;
            })
            .GetCreateResult();
        var publish = await _orderPublishRepository.GetAsync(m => m.No == order.No);
        publish.ShouldNotBeNull(order.No);
        var orderEntity = await _orderRepository.GetAsync(order.Id);
        orderEntity.ShouldNotBeNull();
        orderEntity.IsEvasive.ShouldBeTrue();
        orderEntity.IsInactively.ShouldBeTrue();
    }

    [Fact]
    public void Set一级部门_Test()
    {
        Set一级部门();
    }

    [Fact]
    public async Task IsStepUrgent_True_Test()
    {
        SetZuoXi();
        var order = _orderServiceMock.CreateOrder()
            .办理到派单员()
            .办理到归档(SetPaiDanYuan, data => data.IsStepUrgent = true, workflow =>
            {
                workflow.BusinessType = EBusinessType.DepartmentLeader;
                workflow.Opinion = "测试保存勾选紧急";
            })
            .GetCreateResult();
        order.ShouldNotBeNull();
        order.Id.ShouldNotBeNull();
        var orderDto = await _orderController.Get(order.Id);
        orderDto.IsStepUrgent.ShouldBeTrue();
        orderDto.IsStepUrgenText.ShouldBe("紧急");
    }

    /// <summary>
    /// 测试在办理的过程中能正确保存 
    /// 1.与市民电话联系
    /// 2.已赴现场处置
    /// 3.其他
    /// 4.其他原因
    /// 5.经办人
    /// 6.经办人电话
    /// 7.沟通时间
    /// 8.沟通地点
    /// </summary>
    /// <returns></returns>
    [Fact]
    public async Task CreateOrder_Test()
    {
        SetZuoXi();
        var order = _orderServiceMock.CreateOrder()
            .办理到一级部门()
            .办理到二级部门(Set一级部门)
            .办理一级部门汇总(Set二级部门)
            .GetCreateResult();
        order.Id.ShouldNotBeNull();
        var orderEntity = await _orderRepository.GetAsync(order.Id);
        orderEntity.RealCommunicationAddress.ShouldNotBeNull();
        orderEntity.RealCommunicationTime.ShouldNotBeNull();
        orderEntity.RealContactLocale.ShouldNotBeNull();
        orderEntity.RealContactLocale.ShouldBe(true);
        orderEntity.RealHandlerName.ShouldNotBeNull();
        orderEntity.RealHandlerPhone.ShouldNotBeNull();
    }

    [Fact]
    public async Task GetOrderHandleTimeConfigByAcceptType_Test()
    {
        var result = await _orderController.GetOrderHandleTimeConfigByAcceptType(Share.Enums.FlowEngine.EFlowDirection.OrgToCenter, "10");
        result.Count.ShouldBe(1);
        result.TimeText.ShouldBe("1个工作日");
        result.TimeType.ShouldBe(ETimeType.WorkDay);
    }


    /// <summary>
    /// 测试取消发布功能
    /// </summary>
    /// <returns></returns>
    [Fact]
    public async Task CancelOrderPublish_Test()
    {
        var system = await _systemSettingRepository.Queryable()
            .Where(m => m.Code == SettingConstants.CancelPublishOrderEnabled)
            .FirstAsync();
        system.SettingValue[0] = "true";
        await _systemSettingRepository.UpdateAsync(system);
        _systemSettingCacheManager.DelSystemSetting(SettingConstants.CancelPublishOrderEnabled);

        SetZuoXi();
        var order = _orderServiceMock.CreateOrder()
            .办理到派单员()
            .办理到归档(SetPaiDanYuan, data =>
            {
                data.IsEvasive = true;
                data.IsInactively = true;
            })
            .GetCreateResult();
        var publish = await _orderPublishRepository.GetAsync(m => m.No == order.No);
        publish.ShouldNotBeNull(order.No);
        var orderEntity = await _orderRepository.GetAsync(order.Id);
        orderEntity.ShouldNotBeNull();
        orderEntity.IsEvasive.ShouldBeTrue();
        orderEntity.IsInactively.ShouldBeTrue();

        await _orderController.PublishCancelAsync(new PublishCancelInDto { OrderPublishId = publish.Id });
        var visit = await _orderVisitRepository.GetAsync(m => m.OrderId == order.Id);
        var publishCount = await _orderPublishRepository.Queryable().Where(m => m.OrderId == order.Id && m.IsDeleted == false).CountAsync();
        publishCount.ShouldBe(0);
        visit.ShouldNotBeNull();
        visit.VisitState.ShouldBe(EVisitState.Visited);
    }
}
