using Fantasy;
using Fantasy.Async;
using Fantasy.Entitas;
using Fantasy.Network;
using Fantasy.Platform.Net;
using NB.Game;

namespace NB.Gate;

public static class GateUnitManageComponentSystem
{
    public static GateUnit Online(this GateUnitManageComponent self, Session session, long accountId)
    {
        if (self.Units.TryGetValue(accountId, out var unit))
        {
            unit.Session = session;
            return unit;
        }

        unit = Entity.Create<GateUnit>(self.Scene, accountId, true, true);
        unit.AccountID = accountId;
        unit.Session = session;
        self.Units.Add(accountId, unit);
        return unit;
    }

    public static GateUnit? Get(this GateUnitManageComponent self, long accountId)
    {
        return self.Units.GetValueOrDefault(accountId);
    }

    public static bool TryGet(this GateUnitManageComponent self, long accountId, out GateUnit? unit)
    {
        return self.Units.TryGetValue(accountId, out unit);
    }

    public static async FTask Offline(this GateUnitManageComponent self, long accountId, long sessionId,
        bool isDispose = true)
    {
        if (!self.Units.TryGetValue(accountId, out var unit)) return;
        //通知其他服务器下线
        var result = await GateLoginHelper.Offline(unit, sessionId);
        if (result != 0)
        {
            Log.Error($"通知其他服务器下线失败，错误码：{result}");
            return;
        }

        Log.Info($"accountId:{accountId} 下线成功");
        self.Units.Remove(accountId);
        if (isDispose)
        {
            unit.Dispose();
        }
    }


    /// <summary>
    /// 会话迭代器
    /// </summary>
    /// <param name="self"></param>
    /// <returns></returns>
    public static IEnumerable<Session> ForEachUnitSession(this GateUnitManageComponent self)
    {
        foreach (var (_, gateUnit) in self.Units)
        {
            Session gateSession = gateUnit.Session;
            if (gateSession == null) continue;
            yield return gateSession;
        }
    }
}