using Hotline.Caching.Interfaces;
using Hotline.Orders;
using Hotline.Repository.SqlSugar.Snapshot;
using Hotline.Settings;
using Hotline.Share.Dtos.Snapshot;
using Hotline.Share.Enums.Snapshot;
using Hotline.Share.Enums.User;
using Hotline.Share.Tools;
using Hotline.Snapshot;
using Hotline.Snapshot.IRepository;
using Hotline.ThirdAccountDomainServices;
using Hotline.ThirdAccountDomainServices.Interfaces;
using IdentityModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using XF.Domain.Dependency;

namespace Hotline.Application.Snapshot;
public class SnapshotThirdAccountSupplier : IThirdAccountSupplier, IScopeDependency
{
    private readonly IThirdAccountRepository _thirdAccountRepository;
    private readonly IThirdAccountDomainService _thirdAccountDomainService;
    private readonly IVolunteerRepository _volunteerRepository;
    private readonly ISystemSettingCacheManager _systemSettingCacheManager;
    private readonly ISystemLogRepository _systemLog;
    private readonly ICitizenRepository _citizenRepository;

    public SnapshotThirdAccountSupplier(IThirdAccountRepository thirdAccountRepository, IVolunteerRepository volunteerRepository, ISystemSettingCacheManager systemSettingCacheManager, ISystemLogRepository systemLog, IThirdAccountDomainService thirdAccountDomainService, ICitizenRepository citizenRepository)
    {
        _thirdAccountRepository = thirdAccountRepository;
        _volunteerRepository = volunteerRepository;
        _systemSettingCacheManager = systemSettingCacheManager;
        _systemLog = systemLog;
        _thirdAccountDomainService = thirdAccountDomainService;
        _citizenRepository = citizenRepository;
    }

    public async Task<string> GetClaimAsync(ThirdAccount account, List<Claim> claims, CancellationToken token)
    {
        var userInfo = await _citizenRepository.GetAsync(account.ExternalId);
        if (userInfo == null)
            return string.Empty;
        claims.Add(new(JwtClaimTypes.Subject, userInfo.Id));
        return userInfo.Id;
    }

    public async Task<Dictionary<string, object>> GetLoginOutDataAsync(ThirdAccount thirdAccount, Dictionary<string, object> dicOutData, CancellationToken cancel)
    {
        var isVolunteer = await _volunteerRepository.IsVolunteerAsync(thirdAccount.PhoneNumber);
        var user = await _citizenRepository.GetAsync(thirdAccount.ExternalId);
        if (user == null || thirdAccount.ExternalId.IsNullOrEmpty())
        {
            user = new Citizen
            {
                CitizenType = EReadPackUserType.Citizen,
                Name = thirdAccount.UserName,
                PhoneNumber = thirdAccount.PhoneNumber,
            };
            user.Id = await _citizenRepository.AddAsync(user);
            await _thirdAccountDomainService.UpdateExternalIdAsync(thirdAccount.Id, thirdAccount.ExternalId, user.Id, cancel);
        }
        dicOutData.Add("userType", user.CitizenType);
        dicOutData.Add("isVolunteer", isVolunteer);
        dicOutData.Add("invitationCode", user.InvitationCode);
        return dicOutData;
    }

    public async Task<ThirdTokenDto> GetThirdParameterAsync(ThirdTokenDto thirdDto, CancellationToken token)
    {
        if (thirdDto.ThirdType == EThirdType.WeChat)
        {
            thirdDto.AppId = _systemSettingCacheManager.WxOpenAppId;
            thirdDto.Secret = _systemSettingCacheManager.WxOpenAppSecret;
            thirdDto.WebApiHost = _systemSettingCacheManager.WxApiHost;
        }
        return await Task.FromResult(thirdDto);
    }

    public async Task RegisterAsync(ThirdAccount thirdAccount, CancellationToken token)
    {
        var userInfo = await _citizenRepository.GetByPhoneNumberAsync(thirdAccount.PhoneNumber);
        if (userInfo != null)
        {
            userInfo.CitizenType = EReadPackUserType.Guider;
            await _citizenRepository.UpdateAsync(userInfo);
            await _thirdAccountDomainService.UpdateExternalIdAsync(thirdAccount.Id, thirdAccount.ExternalId, userInfo.Id, token);
        }
        else
        {
            userInfo = new Citizen
            {
                PhoneNumber = thirdAccount.PhoneNumber,
                CitizenType = EReadPackUserType.Citizen,
            };
            userInfo.Id = await _citizenRepository.AddAsync(userInfo);
            await _thirdAccountDomainService.UpdateExternalIdAsync(thirdAccount.Id, thirdAccount.ExternalId, userInfo.Id, token);
        }
    }
}

