using Hotline.Api.Controllers;
using Hotline.Application.Snapshot.Contracts;
using Hotline.Caching.Interfaces;
using Hotline.Identity.Accounts;
using Hotline.Identity.Roles;
using Hotline.Orders;
using Hotline.Settings;
using Hotline.Share.Dtos.Snapshot;
using Hotline.Share.Tools;
using Hotline.Snapshot;
using Hotline.Snapshot.IRepository;
using Hotline.ThirdAccountDomainServices;
using Hotline.ThirdAccountDomainServices.Interfaces;
using Hotline.Users;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using XF.Domain.Cache;
using XF.Domain.Repository;

namespace Hotline.Tests.Application;

public class SnapshotUserApplicationTest : TestBase
{
    private readonly ISnapshotUserApplication _snapshotUserApplication;
    private readonly ISystemDicDataCacheManager _dicData;
    private readonly ICitizenRepository _citizenRepository;
    private readonly ISafetyTypeRepository _safetyTypeRepository;
    public SnapshotUserApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, ITypedCache<SystemSetting> cacheSettingData, ThirdAccounSupplierFactory thirdAccountDomainFactory, IServiceProvider serviceProvider, ISnapshotUserApplication snapshotUserApplication, ISystemDicDataCacheManager dicData, ICitizenRepository citizenRepository, ISafetyTypeRepository safetyTypeRepository) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository, cacheSettingData, thirdAccountDomainFactory, serviceProvider)
    {
        _snapshotUserApplication = snapshotUserApplication;
        _dicData = dicData;
        _citizenRepository = citizenRepository;
        _safetyTypeRepository = safetyTypeRepository;
    }

    [Fact]
    public async Task SnapshotUserApplication_Test()
    {
        var searchInDto = new GetThirdCitizenInDto
        {
            PhoneNumber = "33"
        };
        var citizenSearchItems = await _snapshotUserApplication.GetThirdCitizenAsync(searchInDto).ToListAsync();
        citizenSearchItems.ShouldNotBeNull();
        citizenSearchItems.Count.ShouldNotBe(0);
        var newSafetyType = new SafetyType { Name = "安全卫士" };
        var safetyType = await _safetyTypeRepository.Queryable().Where(m => m.Name == newSafetyType.Name).FirstAsync();
        safetyType ??= new SafetyType
            {
                Id = await _safetyTypeRepository.AddAsync(newSafetyType)
            };

        var citizen = await _citizenRepository.Queryable()
            .LeftJoin<CitizenRelationSafetyType>((citizen, relation) => relation.CitizenId == citizen.Id)
            .Where((citizen, relation) => relation.CitizenId == null)
            .FirstAsync();
        var addDto = new AddCitizenRelationSafetyTypeInDto
        {
            CitizenIds = [citizen.Id],
            SafetyTypeId = safetyType.Id,
        };

        await _snapshotUserApplication.AddCitizenRelationSafetyType(addDto, CancellationToken.None);

        var inDto = new CitizenRelationSafetyTypeInDto
        {
            SafetyTypeId = safetyType.Id
        };
        var items = await _snapshotUserApplication.GetCitizenRelationSafetyType(inDto).ToListAsync();
        var item = items.FirstOrDefault(m => m.CitizenId == citizen.Id && m.SafetyTypeId == safetyType.Id);
        item.ShouldNotBeNull();
        item.SafetyTypeName.ShouldBe(safetyType.Name);
        item.SafetyTypeId.ShouldBe(safetyType.Id);
        item.CitizenId.ShouldBe(citizen.Id);
        item.CitizenName.ShouldBe(citizen.Name);

        var newSafetyTypeXuanChuan = new SafetyType { Name = "宣传员" };
        var safetyTypeXuanChuan = await _safetyTypeRepository.Queryable()
            .Where(m => m.Name == newSafetyTypeXuanChuan.Name).FirstAsync();
        safetyTypeXuanChuan ??= new SafetyType
            {
                Id = await _safetyTypeRepository.AddAsync(newSafetyTypeXuanChuan)
            };
        addDto = new AddCitizenRelationSafetyTypeInDto
        {
            CitizenIds = [citizen.Id],
            SafetyTypeId = safetyTypeXuanChuan.Id,
        };
        await _snapshotUserApplication.AddCitizenRelationSafetyType(addDto, CancellationToken.None);
        var deleteInDto = new DeleteCitizenRelationSafetyTypeInDto
        {
            Items =
            [
                new() {
                    CitizenId = citizen.Id,
                    SafetyTypeId = safetyType.Id
                }
            ]
        };
        await _snapshotUserApplication.DeleteCitizenRelationSafetyAsync(deleteInDto);

        items = await _snapshotUserApplication.GetCitizenRelationSafetyType(inDto).ToListAsync();
        items.Any(m => m.SafetyTypeId.IsNullOrEmpty()).ShouldBeFalse();
        item = items.FirstOrDefault(m => m.CitizenId == citizen.Id && m.SafetyTypeId == safetyType.Id);
        item.ShouldBeNull();
        inDto = new CitizenRelationSafetyTypeInDto
        {
            SafetyTypeId = safetyTypeXuanChuan.Id
        };
        items = await _snapshotUserApplication.GetCitizenRelationSafetyType(inDto).ToListAsync();
        item = items.FirstOrDefault(m => m.CitizenId == citizen.Id && m.SafetyTypeId == safetyTypeXuanChuan.Id);
        item.SafetyTypeName.ShouldBe(safetyTypeXuanChuan.Name);
        item.SafetyTypeId.ShouldBe(safetyTypeXuanChuan.Id);
        item.CitizenId.ShouldBe(citizen.Id);
        item.CitizenName.ShouldBe(citizen.Name);
    }
}
