using System.Numerics;
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Memory;
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
using CounterStrikeSharp.API.Modules.Timers;
using CounterStrikeSharp.API.Modules.Utils;
using CustomRounds.Attributes;
using Microsoft.Extensions.Logging;
using Timer = CounterStrikeSharp.API.Modules.Timers.Timer;
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;

namespace CustomRounds.Rounds;

[CustomRound(Name = nameof(ChickenRound))]
public class ChickenRound : ICustomRound
{
    private const int MaxChickens = 100;

    private readonly Plugin _plugin;
    private readonly ILogger<ChickenRound> _logger;
    private readonly List<CChicken> _chickens = [];

    private readonly MemoryFunctionVoid<CBaseEntity, CBaseEntity, IntPtr, IntPtr> _setParent =
        new("48 85 F6 74 ? 48 8B 47 10 F6 40 31 02 75 ? 48 8B 46 10 F6 40 31 02 75 ? B8 ? ? ? ?");

    // 421, 2688, 256 | 11, -7, 0
    // 402, 2850, 256 | 13, 75, 0
    // 250, 2852, 256 | 17, 130, 0
    // 270, 2691, 256 | 20, -134, 0

    private readonly Vector[] _positions =
    [
        new Vector(750, 2684, 180),
        new Vector(456, 3269, 210),
        new Vector(272, 3175, 220)
    ];

    private readonly Vector[] _spawnPoints =
    [
        new Vector(421, 2688, 256),
        new Vector(402, 2850, 256),
        new Vector(250, 2852, 256),
        new Vector(270, 2691, 256),
    ];

    private int _currentChicken;
    private float _spawnRate = 1;
    private float _spawnInterval = 5;
    private CDynamicProp? _targetEntity;
    private Timer? _spawnTimer;
    private readonly List<Timer?> _gayTimer = [];

    private readonly bool[] _chickenCanJump = new bool[200];
    private readonly int[] _chickenJumpCount = new int[200];

    public ChickenRound(Plugin plugin, ILogger<ChickenRound> logger)
    {
        _plugin = plugin;
        _logger = logger;
        plugin.AddCommand("css_testc", "", (player, info) => CreateChicken());
    }

    public void Start()
    {
        RemoveChickens();
        VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook(OnTakeDamage, HookMode.Pre);

        var players = Utilities.GetPlayers();

        foreach (var (player, spawnPoint) in players.Zip(_spawnPoints, (p, s) => (p, s)))
        {
            var playerPawn = player.PlayerPawn.Value;
            if (playerPawn is null) continue;

            playerPawn.Teleport(spawnPoint);
        }

        _plugin.RegisterEvent<EventRoundFreezeEnd>((@event, info) =>
        {
            _targetEntity = Utilities.CreateEntityByName<CDynamicProp>("prop_dynamic");
            if (_targetEntity is not null)
            {
                _targetEntity.TakesDamage = false;
                _targetEntity.DispatchSpawn();
                _targetEntity.RenderMode = RenderMode_t.kRenderNone;
                _targetEntity.AbsOrigin.X = 345;
                _targetEntity.AbsOrigin.Y = 2770;
                _targetEntity.AbsOrigin.Z = 248;
            }

            Server.PrintToChatAll($"[{ChatColors.Blue}CustomRounds\x01] CHICKEN ROUND");

            _spawnTimer = _plugin.AddTimer(_spawnInterval, Callback);
            return HookResult.Continue;
        });
    }

    private void RemoveChickens()
    {
        foreach (var entityInstance in Utilities.GetAllEntities()
                     .Where(e => e.DesignerName.Contains("chicken") && e.IsValid))
        {
            entityInstance.Remove();
        }
    }

    private HookResult OnTakeDamage(DynamicHook hook)
    {
        var entityInstance = hook.GetParam<CEntityInstance>(0);
        var info = hook.GetParam<CTakeDamageInfo>(1);

        if (!entityInstance.DesignerName.Contains("chicken"))
            return HookResult.Continue;

        if (info.Attacker.Value?.DesignerName.Contains("env_explosion") == false)
            return HookResult.Continue;

        return HookResult.Handled;
    }

    private void Callback()
    {
        if (_currentChicken >= MaxChickens)
            return;

        VirtualFunctions.ClientPrintAll(HudDestination.Alert, $"Kуриц осталось: {MaxChickens - _currentChicken}", 0, 0,
            0, 0);

        _spawnInterval *= 0.9f;
        if (_spawnInterval < 1)
            _spawnInterval = 1;

        _spawnRate += 0.1f;

        for (int i = 0; i < _spawnRate; i++)
        {
            CreateChicken();
        }

        _spawnTimer = _plugin.AddTimer(_spawnInterval, Callback);
    }

    private void CreateChicken()
    {
        var chicken = Utilities.CreateEntityByName<CChicken>("chicken");
        if (chicken is null) return;

        var raw = _targetEntity?.EntityHandle.Raw;
        if (raw is null) return;

        chicken.Leader.Raw = raw.Value;
        chicken.DispatchSpawn();
        chicken.Leader.Raw = raw.Value;

        var position = _positions[Random.Shared.Next(_positions.Length)];
        chicken.Teleport(position);

        var timer = _plugin.AddTimer(0.5f, () =>
        {
            if (!chicken.IsValid || _targetEntity?.IsValid == false) return;

            var players = Utilities.GetPlayers().Where(u => u is { PawnIsAlive: true, IsValid: true });

            var nearestPlayer = players
                .Select(u => new
                {
                    Player = u,
                    Distance = Vector3.Distance(chicken.AbsOrigin!.ToVector3(),
                        u.PlayerPawn.Value.AbsOrigin!.ToVector3())
                })
                .OrderBy(u => u.Distance)
                .FirstOrDefault();

            if (nearestPlayer != null)
            {
                if (nearestPlayer.Distance < 60)
                {
                    Explode(chicken);
                }
                else if (nearestPlayer.Distance < 120)
                {
                    JumpAtPlayer(chicken, nearestPlayer.Player);
                }
            }
        }, TimerFlags.REPEAT | TimerFlags.STOP_ON_MAPCHANGE);

        _gayTimer.Add(timer);

        _currentChicken++;
        _chickens.Add(chicken);
        _chickenJumpCount[chicken.Index] = 0;
    }

    private void JumpAtPlayer(CChicken chicken, CCSPlayerController player)
    {
        if (_chickenJumpCount[chicken.Index] == 2)
        {
            _chickenJumpCount[chicken.Index] = 0;
            return;
        }

        _chickenJumpCount[chicken.Index]++;

        var direction =
            Vector3.Normalize(player.PlayerPawn.Value!.AbsOrigin!.ToVector3() - chicken.AbsOrigin!.ToVector3());

        const float jumpSpeed = 300.0f;

        var jumpVelocity = new Vector(direction.X * jumpSpeed, direction.Y * jumpSpeed, 240.0f);

        jumpVelocity.X += Random.Shared.NextSingle() * 20 - 10;
        jumpVelocity.Y += Random.Shared.NextSingle() * 20 - 10;

        chicken.Teleport(new Vector(chicken.AbsOrigin.X, chicken.AbsOrigin.Y, chicken.AbsOrigin.Z + 20),
            velocity: jumpVelocity);
    }

    private void Explode(CBaseEntity entity)
    {
        var explosion = Utilities.CreateEntityByName<CEnvExplosion>("env_explosion");
        if (explosion is null || !explosion.IsValid)
            return;

        explosion.RadiusOverride = 100;
        explosion.Magnitude = 1000;
        explosion.PlayerDamage = 50;
        explosion.DamageForce = 50;
        explosion.DispatchSpawn();

        explosion.Teleport(entity.AbsOrigin);
        Server.NextFrame(() => { explosion.AcceptInput("Explode"); });
        if (entity.IsValid)
        {
            entity.Remove();
        }
    }

    public void End()
    {
        _currentChicken = 0;
        _spawnInterval = 5;
        _spawnRate = 1;

        _spawnTimer?.Kill();
        foreach (var timer in _gayTimer)
        {
            timer?.Kill();
        }

        if (_targetEntity?.IsValid == true)
        {
            _targetEntity.Remove();
        }

        foreach (var chicken in _chickens.Where(cChicken => cChicken.IsValid))
        {
            chicken.Remove();
        }

        VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Unhook(OnTakeDamage, HookMode.Pre);
    }
}

public static class VectorUtils
{
    public static Vector ToVector(this Vector3 v)
    {
        return new Vector(v.X, v.Y, 0);
    }

    public static Vector3 ToVector3(this Vector v)
    {
        return new Vector3(v.X, v.Y, 0);
    }
}

как сделать чтобы курица прыгала только 1 раз например раз в 2 секунды