using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
using ZiggyCreatures.Caching.Fusion;

namespace IRaCIS.Core.Application.Filter;




public class LimitUserRequestAuthorization(
    IFusionCache _fusionCache, IUserInfo _userInfo, IStringLocalizer _localizer,
    IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig) : IAsyncAuthorizationFilter
{

    public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
    {
        var minutes = _verifyConfig.CurrentValue.AutoLoginOutMinutes;

        if (_verifyConfig.CurrentValue.OpenLoginLimit)
        {
            if (context.ActionDescriptor.EndpointMetadata.Any(item => item is IAllowAnonymous))
            {

                return;
                //匿名访问的不处理
            }
            else
            {
                //1、用户登陆的时候，设置缓存

                //没有从请求中取到token
                if (string.IsNullOrWhiteSpace(_userInfo.UserToken))
                {
                    context.HttpContext.Response.ContentType = "application/json";
                    context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
                    //---当前请求未从Header/Url取到用户Token,请联系开发者
                    //await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk(_localizer["LimitUser_AuthTokenMissing"])));

                    context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AuthTokenMissing"]));
                }



                //2、在这里取缓存  进行比较  看是否有其他人进行了登陆，如果其他人登陆了，就把之前用户挤掉
                var cacheUserToken = await _fusionCache.GetOrDefaultAsync<string>(CacheKeys.UserToken(_userInfo.IdentityUserId));



                //缓存中没有取到Token
                if (string.IsNullOrWhiteSpace(cacheUserToken))
                {
                    cacheUserToken = _userInfo.UserToken;

                    //设置当前用户最新Token
                    await _fusionCache.SetAsync(CacheKeys.UserToken(_userInfo.IdentityUserId), _userInfo.UserToken, TimeSpan.FromDays(7));

                    //重启应用程序，所有人续期，不一下子踢出所有人
                    await _fusionCache.SetAsync(CacheKeys.UserAutoLoginOut(_userInfo.IdentityUserId), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(minutes));

                }
                //是同一个人  
                else if (cacheUserToken == _userInfo.UserToken)
                {

                    var cacheTime = await _fusionCache.GetOrDefaultAsync<string>(CacheKeys.UserAutoLoginOut(_userInfo.IdentityUserId));

                    //过期了 需要自动退出
                    if (string.IsNullOrEmpty(cacheTime))
                    {
                        context.HttpContext.Response.ContentType = "application/json";
                        context.HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden;

                        context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AccountAuto_LoginOut"], ApiResponseCodeEnum.AutoLoginOut));
                    }
                    else
                    {
                        await _fusionCache.SetAsync(CacheKeys.UserAutoLoginOut(_userInfo.IdentityUserId), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(minutes));
                    }
                }
                else
                {
                    context.HttpContext.Response.ContentType = "application/json";
                    context.HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
                    //---您的账户在其他地方已登陆，您被迫下线。

                    context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AccountLoggedInElsewhere"], ApiResponseCodeEnum.LoginInOtherPlace));

                }

                //用户或者角色禁用，那么操作的人退出

                var isDisable = await _fusionCache.GetOrDefaultAsync<bool>(CacheKeys.UserDisable(_userInfo.IdentityUserId),false);

                var isRoleDisable = await _fusionCache.GetOrDefaultAsync<bool>(CacheKeys.UserRoleDisable(_userInfo.UserRoleId),false);

                if (isDisable == true || isRoleDisable == true)
                {
                    context.HttpContext.Response.ContentType = "application/json";
                    context.HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
                    // 用户或者角色被禁用。

                    context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AccountOrRoleDisable"], ApiResponseCodeEnum.AutoLoginOut));
                }

            }
        }


    }
}

