using System.Collections;
using System.Collections.Generic;
using Unity.Multiplayer.Samples.BossRoom;
using UnityEngine;
using Unity.Netcode;
using System;
using Unity.Services.Lobbies.Models;

public class ScoreManager : NetworkBehaviour
{
    public static ScoreManager Instance { get; private set; }

    public Dictionary<ulong, int> playerScores = new Dictionary<ulong, int>();
    public Dictionary<ulong, string> playerNames = new Dictionary<ulong, string>();
    public static Action<ulong, int,Color> OnScoreUpdated;
    private void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
            return;
        }
        Instance = this;
    }

    public override void OnNetworkSpawn()
    {
        if (IsServer)
        {
            StartCrowPenaltyCoroutine();
        }
    }

    [ServerRpc(RequireOwnership = false)]
    public void InitializeAndSyncPlayerServerRpc(ulong ownerClientId, string playerName)
    {
        if (!playerScores.ContainsKey(ownerClientId))
        {
            playerScores[ownerClientId] = 200;
            playerNames[ownerClientId] = playerName;
        }
        Debug.Log($"[ScoreManager] Player {ownerClientId} initialized with a starting score of {playerScores[ownerClientId]} and name '{playerName}'.");
        SyncPlayerDataClientRpc(ownerClientId, playerName, playerScores[ownerClientId]);
    }
    [ClientRpc]
    public void SyncPlayerDataClientRpc(ulong ownerClientId, string playerName, int score)
    {
        // Update local data
        if (!playerScores.ContainsKey(ownerClientId))
        {
            playerScores[ownerClientId] = score;
            playerNames[ownerClientId] = playerName;
        }
        else
        {
            playerScores[ownerClientId] = score;
        }

        Debug.Log($"[ScoreManager] Synced Player {ownerClientId} data: Name = {playerName}, Score = {score}");

        // Update the scoreboard
        Scoreboard.Instance.InitializeScoreboardItem(ownerClientId, score, playerName);
    }

    public void UpdatePlayerScore(ulong ownerClientId, int newScore)
    {
        if (playerScores.ContainsKey(ownerClientId))
        {
            playerScores[ownerClientId] = newScore;
            Debug.Log($"[ScoreManager] Updating Player {ownerClientId} score to {newScore}.");
            UpdatePlayerScoreClientRpc(ownerClientId, newScore);
        }
        else
        {
            Debug.LogWarning($"[ScoreManager] No entry found for Player {ownerClientId}. Cannot update score.");
        }
    }

    [ClientRpc]
    public void UpdatePlayerScoreClientRpc(ulong ownerClientId, int newScore)
    {
        if (playerNames.TryGetValue(ownerClientId, out var playerName))
        {
            Debug.Log($"[ScoreManager] Received score update for Player {ownerClientId} (Name: {playerName}): {newScore}");
            Scoreboard.Instance.UpdateScoreboard(ownerClientId, newScore);
        }
        else
        {

            Debug.LogWarning($"[ScoreManager] Player name not found for Player {ownerClientId}. Cannot update scoreboard.");
        }
    }

    public void AddPlayerScore(ulong ownerClientId, int scoreToAdd, Color color = default)
    {
        if (playerScores.ContainsKey(ownerClientId))
        {
            OnScoreUpdateInvokerClientRpc(ownerClientId, scoreToAdd, color);
            //OnScoreUpdated?.Invoke(ownerClientId, playerScores[ownerClientId]);
            playerScores[ownerClientId] += scoreToAdd;
            UpdatePlayerScore(ownerClientId, playerScores[ownerClientId]);
        }
    }

    public void SubtractPlayerScore(ulong ownerClientId, int scoreToSubtract, Color color = default)
    {
        if (playerScores.TryGetValue(ownerClientId, out var score))
        {
            OnScoreUpdateInvokerClientRpc(ownerClientId, -scoreToSubtract, color);
            int newScore = Mathf.Max(0, score - scoreToSubtract);
            UpdatePlayerScore(ownerClientId, newScore);
        }
    }
    [ClientRpc]
    void OnScoreUpdateInvokerClientRpc(ulong id, int score, Color color = default)
    {
        OnScoreUpdated?.Invoke(id, score,color);
    }
    public void StartCrowPenaltyCoroutine()
    {
        StartCoroutine(ApplyCrowPenaltyCoroutine());
    }

    private IEnumerator ApplyCrowPenaltyCoroutine()
    {
        yield return new WaitUntil(() => PlatformManager.Instance != null && PlatformManager.Instance.AreAllPlatformsOccupied());

        while (true)
        {
            // Create a list to store client IDs whose scores need to be updated
            List<ulong> clientsToModify = new List<ulong>();

            foreach (var entry in playerScores)
            {
                ulong ownerClientId = entry.Key;

                if (CrowManager.Instance != null && CrowManager.Instance.GetCurrentCrow().OwnerClientId == ownerClientId)
                {
                    clientsToModify.Add(ownerClientId);
                }
            }

            // Apply the penalties after the iteration
            foreach (ulong clientId in clientsToModify)
            {
                SubtractPlayerScore(clientId, 2,Color.red);
                Debug.Log($"[ScoreManager] Applied crow penalty to Player {clientId}. New score: {playerScores[clientId]}");
            }

            yield return new WaitForSeconds(5f);
        }
    }
}