Sboku/Arena/RoundManager.cs
using Sandbox.Events;
using SWB.Demo;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Sandbox.Sboku.Arena;

[Group("Sboku Arena")]
public sealed class RoundManager : Component,
	IGameEventHandler<RoundManager.UpgradeScreenClosed>,
	IGameEventHandler<RoundManager.GameOver>
{
 

    [Property]
    public bool AutoStartRounds { get; set; } = true;
    [Property]
	public int EnemiesPerSpawner { get; set; } = 3;
	[Property]
	public int StartCountdown { get; set; } = 5;
    [Property]
    public int EndCountdown { get; set; } = 5;
    [Property]
    public int BotCap { get; set; } = 3;
    [Property]
    public int TotalRounds { get; set; } = 10;

    [Sync]
	public int RoundNumber { get; set; } = 1;
	[Sync]
	public int BotsNumber { get; private set; }
	[Sync]
	public int Timer { get; private set; }

    [Property]
    public bool EnableUpgrades { get; set; } = true;

    private TimeSince timer = new();
	private Action callback;

	private bool isRoundStarted = false;
	private Spawner spawner;
    
	[Rpc.Host]
    protected override void OnAwake()
    {
        
        spawner = Scene.GetComponentInChildren<Spawner>();
    }

    protected override void OnStart()
    {
        base.OnStart();
        

        if (AutoStartRounds && !isRoundStarted)
        {
            Log.Info("[Round] Auto-starting first round");
            SetCallback(StartCountdown, StartRound);
        }
    }


    [Rpc.Host]
    protected override void OnFixedUpdate()
    {
        
        BotsNumber = Scene.GetAllComponents<SbokuBase>().Count();
        if (isRoundStarted && BotsNumber == 0 && AreSpawnersDone())
		{
			isRoundStarted = false;
            SetCallback(EndCountdown, FinishRound);
        }

        if (timer > 1f)
		{
			OnTimer();
			timer = 0f;
		}
    }

	private void OnTimer()
	{
		if (Timer > 0)
		{
			Timer--;
            if (Timer == 0)
			{
				OnTimerExpire();
			}
		}
	}
	private void OnTimerExpire()
	{
		if (callback != null)
		{
			callback();
		}
		else
		{
			Log.Error("Callback is null!");
		}
	}

    private bool AreSpawnersDone()
    {
		if (!spawner.IsDone())
				return false;

		return true;
    }

    private void SetCallback(int time,  Action callback)
	{
		Timer = time;
		this.callback = callback;
	}


    private bool navMeshGenerated = false;

    private void StartRound()
    {
        Log.Info($"[RoundManager] StartRound called | Host={Networking.IsHost}");
        if (isRoundStarted)
            return;

        if (!navMeshGenerated)
        {
            if (Scene.NavMesh != null)
            {
                Scene.NavMesh.Generate(Scene.PhysicsWorld);
                navMeshGenerated = true;
                Log.Info("[NavMesh] Generated before first round");
            }
        }

        spawner.RequestSpawn();
        

        isRoundStarted = true;
    }


    [Rpc.Host]
	public void RemoveEntities()
	{
        foreach (var ad in Scene.GetComponentsInChildren<BotAdapter>(includeDisabled: true))
            ad.GameObject.Destroy();
    }

    [Rpc.Host]
    private void FinishRound()
    {
        isRoundStarted = false;
        RoundNumber++;

        RemoveEntities();

        foreach (var ply in Scene.GetAllComponents<DemoPlayer>())
        {
            ply.Respawn();

            if (ply.UsesUpgrades)
            {
                ply.GetComponent<UpgradeHolder>().FreePoints++;
            }
        }

        if (RoundNumber <= TotalRounds)
        {
            if (EnableUpgrades)
            {
                Scene.Dispatch<OpenUpgradeScreen>(new());
            }
            else
            {
                SetCallback(StartCountdown, StartRound);
            }
        }
        else
        {
            Scene.Dispatch<Victory>(new());
        }
    }

    public void OnGameEvent(UpgradeScreenClosed eventArgs)
    {
		if (!isRoundStarted)
            SetCallback(StartCountdown, StartRoundHost);
    }

    [Rpc.Host]
    public void OnGameEvent(GameOver eventArgs)
    {
        isRoundStarted = false;

        //spawners.ForEach(x => x.ClearQueue());
        RemoveEntities();

        foreach (var pl in Scene.GetComponentsInChildren<DemoPlayer>())
        {
            pl.Respawn();
        }

        if (AutoStartRounds)
        {
            // 🔁 Aloita peli uudelleen alusta
            RoundNumber = 1;
            Log.Info("[Round] GameOver → restarting automatically");

            SetCallback(StartCountdown, StartRound);
        }
        else
        {
            // Arena / FPS -moodi
            foreach (var pl in Scene.GetComponentsInChildren<DemoPlayer>())
            {
                pl.DestroyAllUIAsync(); // 🔑 OIKEA AIKOITUS(); // 🔑 TÄRKEIN RIVI
                //pl.CreateFailScreen();
            }
        }
    }
    private void StartRoundHost()
    {
        if (!Networking.IsHost)
            return;

        StartRound();
    }
    public record OpenUpgradeScreen() : IGameEvent;
	public record UpgradeScreenClosed() : IGameEvent;
	public record GameOver() : IGameEvent;
	public record Victory() : IGameEvent;
}