using Fantasy;
using Fantasy.Async;
using Fantasy.Network;
using Fantasy.Network.Interface;
using Fantasy.Platform.Net;
using NB.Authentication.Jwt;

namespace NB.Authentication.Handler;

public class C2A_LoginRequestHandler : MessageRPC<C2A_LoginRequest, A2C_LoginResponse>
{
    protected override async FTask Run(Session session, C2A_LoginRequest request, A2C_LoginResponse response,
        Action reply)
    {
        if (!session.CheckInterval(2000))
        {
            // 返回这个3代表操作过于频繁。
            response.ErrorCode = ErrorCode.ErrFrequent;
            return;
        }

        session.SetTimeout(3000);
        var scene = session.Scene;
        Log.Info($"登录服场景 {scene.Id} {scene.RouteId} {scene.SceneConfigId}");
        var result = await AuthenticationHelper.Login(scene, request.Username, request.Password);

        if (result.ErrorCode != ErrorCode.Successful && result.AccountId == -1)
        {
            if (request.Region == 0)
            {
                request.Region = RegionDef.CN;
            }
            //开始注册账号
            var regErrorCode =
                await AuthenticationHelper.Register(session.Scene, request.Username, request.Region, "用户注册");
            if (regErrorCode != ErrorCode.Successful)
            {
                result.ErrorCode = regErrorCode;
            }
            else
            {
                Log.Debug($"Register 当前的服务器是:{scene.SceneConfigId}");
                //注册完毕，执行登录
                result = await AuthenticationHelper.Login(scene, request.Username, request.Password);
            }
        }

        if (result.ErrorCode == ErrorCode.Successful)
        {
            // 通过配置表或其他方式拿到Gate服务器组的信息
            var gates = SceneConfigData.Instance.GetSceneBySceneType(SceneType.Gate);
            // 通过当前账号的ID拿到要分配Gate服务器
            var gatePosition = result.AccountId % gates.Count;
            // 通过计算出来的位置下标拿到Gate服务器的配置
            var gateSceneConfig = gates[(int)gatePosition];
            // 通过Gate的SceneConfig文件拿到外网的ID地址和端口
            var outerPort = gateSceneConfig.OuterPort;
            var processConfig = ProcessConfigData.Instance.Get(gateSceneConfig.ProcessConfigId);
            var machineConfig = MachineConfigData.Instance.Get(processConfig.MachineId);
            // 颁发一个ToKen令牌给客户端
            response.ToKen = AuthenticationJwtHelper.GetToken(scene, result.AccountId,
                $"{machineConfig.OuterIP}:{outerPort}", gateSceneConfig.Id, result.region);
        }

        response.ErrorCode = result.ErrorCode;
        Log.Debug($"Login 当前的服务器是:{scene.SceneConfigId}");
    }
}