using CounterStrikeSharp.API.Core;
using FabiusTimer.Helpers;
using System.Text;
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Modules.Commands;
using FabiusTimer.Configs;
using FabiusTimer.Player;
using FabiusTimer.Player.Replay;
using FabiusTimerApi.Models;
using Microsoft.Extensions.Localization;

namespace FabiusTimer.Managers;

public class HudManager
{
    private readonly Plugin _plugin;
    private readonly PlayersManager _playersManager;
    private readonly IMapManager _mapManager;
    private readonly Playback _playback;
    private readonly StyleConfig _styleConfig;
    private readonly IStringLocalizer _localizer;

    public HudManager(Plugin plugin, PlayersManager playersManager, EventManager eventManager,
        Config<StyleConfig> styleConfig, IMapManager mapManager, Playback playback)
    {
        _plugin = plugin;
        _playersManager = playersManager;
        _mapManager = mapManager;
        _playback = playback;
        _styleConfig = styleConfig.Value;
        _localizer = plugin.Localizer;

        plugin.AddCommand("css_hud", "", ToggleHud);
        plugin.AddCommand("css_showkeys", "", ToggleHudKeys);
        plugin.AddCommand("css_keys", "", ToggleHudKeys);

        plugin.RegisterListener<Listeners.OnTick>(OnTick);
    }

    private void ToggleHud(CCSPlayerController? player, CommandInfo _)
    {
        if (player == null) return;

        var timerPlayer = _playersManager.Players[player];

        var data = timerPlayer?.Data;
        if (data is null) return;

        data.IsHudEnabled ^= true;
        timerPlayer?.PrintToChat(data.IsHudEnabled ? "hud.enabled" : "hud.disabled");

        timerPlayer?.SetPlayerCookie("hud_enabled", data.IsHudEnabled);
    }

    private void ToggleHudKeys(CCSPlayerController? player, CommandInfo _)
    {
        if (player == null) return;

        var timerPlayer = _playersManager.Players[player];

        var data = timerPlayer?.Data;
        if (data is null) return;

        data.IsHudKeysEnabled ^= true;
        timerPlayer?.PrintToChat(data.IsHudKeysEnabled ? "hud_keys.enabled" : "hud_keys.disabled");

        timerPlayer?.SetPlayerCookie("hud_keys_enabled", data.IsHudKeysEnabled);
    }

    private void OnTick()
    {
        foreach (var player in Utilities.GetPlayers().Where(u => u.IsValidPlayer()))
        {
            try
            {
                if (!_playersManager.TryGetPlayer(player, out var timerPlayer)) return;

                var data = timerPlayer.Data;
                if (data is null) return;

                CalculateHud(timerPlayer, data);
                if (data.TimerStarted)
                {
                    StopTimerIfInNoClip(player, data);
                }

                DisplayHud(timerPlayer, data);
            }
            catch (Exception)
            {
                // ignore
            }
        }
    }

    private void StopTimerIfInNoClip(CCSPlayerController player, Data data)
    {
        var playerPawn = player.PlayerPawn.Value;
        if (playerPawn != null && playerPawn.IsNoClip())
        {
            data.TimerStarted = false;
            data.Time = 0;
        }
    }

    private void DisplayHud(TimerPlayer timerPlayer, Data data)
    {
        var controller = timerPlayer.Controller!;

        if (controller.PawnIsAlive)
        {
            // if (data.IsHudKeysEnabled)
            //     controller.PrintToCenter(data.HudKeysText);
            if (data.IsHudEnabled)
                controller.PrintToCenterHtml(data.HudText);
        }
        else
        {
            DisplayObserverHud(controller, timerPlayer);
        }
    }

    private void DisplayObserverHud(CCSPlayerController player, TimerPlayer timerPlayer)
    {
        try
        {
            var observerServices = player.ObserverPawn?.Value?.ObserverServices;
            if (observerServices == null || observerServices.ObserverMode == (int)ObserverMode_t.OBS_MODE_NONE) return;

            if (observerServices.ObserverMode is (int)ObserverMode_t.OBS_MODE_IN_EYE
                or (int)ObserverMode_t.OBS_MODE_CHASE)
            {
                var targetController = new CCSPlayerController(observerServices.ObserverTarget?.Value?.Handle ?? 0);

                var text = string.Empty;
                if (targetController.IsBot)
                {
                    var replayBot = _playback.ReplayBot;
                    var controller = replayBot.Controller;
                    if (controller == targetController)
                    {
                        text = ;
                    }
                }
                else
                {
                    var data = _playersManager.Players[targetController]?.Data;
                    if (data is null) return;

                    text = data.HudText;
                }

                player.PrintToCenterHtml(text);
            }
        }
        catch (Exception e)
        {
            // ignore yomayo
        }
    }

    public void CalculateHud(TimerPlayer timerPlayer, Data data)
    {
        var controller = timerPlayer.Controller;
        if (controller?.Connected != PlayerConnectedState.PlayerConnected) return;

        if (data.IsHudEnabled)
        {
            var wrTime = _mapManager.GetWorldRecord(timerPlayer.CurrentStyle, timerPlayer.Route)?.Time ?? 0;
            var totalRecords = _mapManager.GetTotalRecordCount(timerPlayer.CurrentStyle, timerPlayer.Route);

            var pbTime = timerPlayer.PersonalBestTime;

            var buttons = controller.Buttons;

            var currentFormatTime = Utils.FormatTicksToTime(data.Time);
            var pbFormatTime = Utils.FormatTicksToTime(pbTime);
            var wrFormatTime = Utils.FormatTicksToTime(wrTime);
            var formattedSpeed = controller.PlayerPawn.Value?.AbsVelocity.Length2D().ToString("000") ?? "000";

            var stringBuilder = new StringBuilder();
            var timeColor = GetTimeColor(timerPlayer, wrTime);
            
            stringBuilder.AppendLine(
                $"<font class='fontSize-m' color='#818181'>{timerPlayer.Route} | [{timerPlayer.Position}/{(totalRecords > 0 ? totalRecords : "-")}] | Tier {_mapManager.Tier}</font><br>");

            stringBuilder.AppendLine(data.TimerStarted
                ? $"<font class='fontSize-l' color='{timeColor}'>{currentFormatTime}</font><br>"
                : "<font class='fontSize-l' color='white'>▬▬▬▬▬▬</font><br>");
            stringBuilder.AppendLine(
                $"<font class='fontSize-sm' color='#818181'>PB: {(pbTime != 0 ? pbFormatTime : "N/A")} | WR: {(wrTime != 0 ? wrFormatTime : "N/A")}</font><br>");
            stringBuilder.AppendLine($"<font class='fontSize-l' color='#beefc7'>{formattedSpeed}</font><br>");

            var style = timerPlayer.CurrentStyle;
            if (style != null)
            {
                stringBuilder.AppendLine(
                    $"<font class='fontSize-m' color='{style.HtmlColor ?? "white"}'>{style.Name}</font><br>");
            }

            if (data.IsHudKeysEnabled)
            {
                stringBuilder.AppendLine($"<font class='fontSize-m'>{data.HudKeysText}</font>");

                data.HudKeysText = GetHudKeysText(buttons);
            }

            data.HudText = $"<span>{stringBuilder}</span>";
        }

        if (data.TimerStarted)
        {
            data.Time++;
        }
    }

    private string GetTimeColor(TimerPlayer timerPlayer, int wrTime)
    {
        var time = timerPlayer.Data?.Time;
        var pbTime = timerPlayer.PersonalBestTime;

        return time > pbTime && pbTime != 0
            ? "#ff0000"
            : time > wrTime && wrTime != 0
                ? "#d5ffba"
                : "#00ff00";
    }

    private string GetHudKeysText(PlayerButtons buttons)
    {
        return $"{((buttons & PlayerButtons.Moveleft) != 0 ? "A" : "_")} " +
               $"{((buttons & PlayerButtons.Forward) != 0 ? "W" : "_")} " +
               $"{((buttons & PlayerButtons.Moveright) != 0 ? "D" : "_")} " +
               $"{((buttons & PlayerButtons.Back) != 0 ? "S" : "_")} - " +
               $"{((buttons & PlayerButtons.Jump) != 0 ? "J" : "_")} " +
               $"{((buttons & PlayerButtons.Duck) != 0 ? "C" : "_")}";
    }
}

public static class Extensions
{
    public static bool IsValidPlayer(this CCSPlayerController player)
    {
        return player.PlayerPawn.Value != null && player.IsValid && player.PlayerPawn.Value.IsValid;
    }

    public static bool IsNoClip(this CCSPlayerPawn playerPawn)
    {
        return playerPawn.MoveType is MoveType_t.MOVETYPE_NOCLIP ||
               playerPawn.ActualMoveType is MoveType_t.MOVETYPE_NOCLIP;
    }
}

мне короче нужно красиво прям очень красиво помечать худ если типо реплей делать его красивым типо шаришть бро

если не реплей такой как щас
а если реплей то

первая строка как щас, но по центру место позиции писать REPLAY, ну и не показывать там PB и WR time

а кнопки получать также, только

GetHudKeysText(ReplayBot.Buttons); но я не знаю как это все дслетаь красиво