using IRaCIS.Core.Application.Helper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IRaCIS.Core.Application.Service.BusinessFilter;

#region minimalapi 流程


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

    public async ValueTask<object?> InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next)
    {
        var minutes = _verifyConfig.CurrentValue.AutoLoginOutMinutes;

        if (_verifyConfig.CurrentValue.OpenLoginLimit)
        {
            // 如果此请求允许匿名访问，不进行处理
            var endpoint = context.HttpContext.GetEndpoint();
            if (endpoint?.Metadata?.GetMetadata<IAllowAnonymous>() != null)
            {
                return await next(context);
            }

            // 没有从请求中取到 token
            if (string.IsNullOrWhiteSpace(_userInfo.UserToken))
            {
                context.HttpContext.Response.ContentType = "application/json";
                return Results.Json(ResponseOutput.NotOk(_localizer["LimitUser_AuthTokenMissing"]), statusCode: StatusCodes.Status200OK);
            }

            // 获取缓存中的用户 token
            var cacheUserToken = await _fusionCache.GetOrDefaultAsync<string>(CacheKeys.UserToken(_userInfo.IdentityUserId));

            // 缓存中没有取到 token
            if (string.IsNullOrWhiteSpace(cacheUserToken))
            {
                // 设置当前用户最新 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";
                    return Results.Json(ResponseOutput.NotOk(_localizer["LimitUser_AccountAuto_LoginOut"], ApiResponseCodeEnum.AutoLoginOut), statusCode: StatusCodes.Status403Forbidden);
                }
                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";
                return Results.Json(ResponseOutput.NotOk(_localizer["LimitUser_AccountLoggedInElsewhere"], ApiResponseCodeEnum.LoginInOtherPlace), statusCode: StatusCodes.Status403Forbidden);
            }
        }

        // 如果通过授权，继续执行请求管道
        return await next(context);

    }


}

#endregion