using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.BossRoom.Gameplay.GameplayObjects.Character;
using Unity.Netcode;
using UnityEngine;

namespace Unity.Multiplayer.Samples.BossRoom
{
    public class PlatformManager : NetworkBehaviour
    {
        public static PlatformManager Instance { get; private set; }
        public List<Platform> m_Platforms;
        public Transform centerPoint;
        public float shapeRadius = 5f;

        private void Awake()
        {
            if (Instance != null && Instance != this)
            {
                Destroy(gameObject);
            }
            else
            {
                Instance = this;
            }
        }

        private void Start()
        {
            if (IsServer)
            {
                InitializePlatforms();
                StartCoroutine(DelayedServerSetup());
            }
        }

        private void InitializePlatforms()
        {
            m_Platforms = GetComponentsInChildren<Platform>(true).ToList();
            for (int i = 0; i < m_Platforms.Count; i++)
            {
                m_Platforms[i].AssignID(i + 1);
            }
        }

        private IEnumerator DelayedServerSetup()
        {
            yield return new WaitForSeconds(0.5f);
            PlatformSelection();
        }

        private void PlatformSelection()
        {
            int platformsToSpawn = PlayerPrefs.GetInt("NumberOfLobbyPlayers", 1) - 1;

            // Disable all platforms initially
            foreach (var platform in m_Platforms)
            {
                platform.gameObject.SetActive(false);
            }

            // Enable required platforms
            for (int i = 0; i < platformsToSpawn; i++)
            {
                m_Platforms[i].gameObject.SetActive(true);
            }

            // Filter only active platforms
            m_Platforms = m_Platforms.Where(platform => platform.gameObject.activeSelf).ToList();
            int[] platformIDs = m_Platforms.Select(p => p.PlatformID.Value).ToArray();

            // Arrange the active platforms
            List<Vector3> arrangedPositions = ArrangePlatforms(m_Platforms);

            // Ensure positions are not empty before sending RPC
            if (platformIDs.Length != arrangedPositions.Count || arrangedPositions.Count == 0)
            {
                Debug.LogError($"[PlatformSelection] ERROR: Mismatch! platformIDs: {platformIDs.Length}, positions: {arrangedPositions.Count}");
                return; // Prevent sending incorrect RPC
            }

            for (int i = 0; i < m_Platforms.Count; i++)
            {
                m_Platforms[i].transform.position = arrangedPositions[i];
                m_Platforms[i].RefreshCollider();
            }
            
            // Send the data to all clients
            SyncPlatformsClientRpc(platformIDs, arrangedPositions.ToArray());
        }


        private List<Vector3> ArrangePlatforms(List<Platform> activePlatforms)
        {
            int platformCount = activePlatforms.Count;

            if (platformCount == 0) 
            {
                Debug.LogError($"[ArrangePlatforms] No active platforms found!");
                return new List<Vector3>(); 
            }

            float startAngle = 90f; // Start from top
            List<Vector3> arrangedPositions = new List<Vector3>();

            // Special case: If 2 platforms, place them opposite to each other
            if (platformCount == 2)
            {
                arrangedPositions.Add(centerPoint.position + new Vector3(shapeRadius, 0, 0)); // Right side
                arrangedPositions.Add(centerPoint.position + new Vector3(-shapeRadius, 0, 0)); // Left side
            }
            else
            {
                float angleStep = 360f / platformCount;

                for (int i = 0; i < platformCount; i++)
                {
                    float angle = startAngle + (i * angleStep);
                    float radians = angle * Mathf.Deg2Rad;

                    Vector3 newPosition = new Vector3(
                        centerPoint.position.x + shapeRadius * Mathf.Cos(radians),
                        centerPoint.position.y,
                        centerPoint.position.z + shapeRadius * Mathf.Sin(radians)
                    );

                    arrangedPositions.Add(newPosition);
                    Debug.Log($"[ArrangePlatforms] Assigned position {i}: {newPosition} to Platform ID: {activePlatforms[i].PlatformID.Value}");
                }
            }

            Debug.Log($"[ArrangePlatforms] Successfully arranged {arrangedPositions.Count} platforms.");
            return arrangedPositions;
        }


        [ClientRpc]
        private void SyncPlatformsClientRpc(int[] platformIDs, Vector3[] positions)
        {
            Debug.Log($"[SyncPlatformsClientRpc] Received {platformIDs.Length} platforms to activate.");

            if (platformIDs.Length != positions.Length)
            {
                Debug.LogError($"[SyncPlatformsClientRpc] Data mismatch! Platform IDs: {platformIDs.Length}, Positions: {positions.Length}");
                return;
            }

            m_Platforms = GetComponentsInChildren<Platform>(true).ToList();

            foreach (var platform in m_Platforms)
            {
                platform.gameObject.SetActive(false);
            }

            List<Platform> activatedPlatforms = m_Platforms
                .Where(p => platformIDs.Contains(p.PlatformID.Value))
                .OrderBy(p => p.PlatformID.Value)
                .ToList();

            if (activatedPlatforms.Count != platformIDs.Length)
            {
                Debug.LogError($"[SyncPlatformsClientRpc] ERROR: Expected {platformIDs.Length} platforms but found {activatedPlatforms.Count} on the client.");
                return;
            }

            for (int i = 0; i < activatedPlatforms.Count; i++)
            {
                activatedPlatforms[i].gameObject.SetActive(true);
                activatedPlatforms[i].transform.position = positions[i];

                // Force Collider Refresh
                activatedPlatforms[i].RefreshCollider();

                Debug.Log($"[SyncPlatformsClientRpc] Activated Platform ID: {activatedPlatforms[i].PlatformID.Value} at {positions[i]}");
            }

            Debug.Log($"[SyncPlatformsClientRpc] Successfully activated {activatedPlatforms.Count} platforms.");
        }



        public Platform FindNearestUnoccupiedPlatform(Vector3 position)
        {
            if (!IsServer) return null;

            return m_Platforms
                .Where(platform => !platform.IsOccupied)
                .OrderBy(platform => Vector3.Distance(position, platform.transform.position))
                .FirstOrDefault();
        }

        public bool AreAllPlatformsOccupied()
        {
            return m_Platforms.All(platform => platform.IsOccupied);
        }

        public Platform GetPlatformOccupiedByPlayer(ServerCharacter player)
        {
            return m_Platforms.FirstOrDefault(p => p.IsOccupied && p.GetOccupierId() == player.OwnerClientId);
        }

        public bool IsPlatformOccupied(Platform platform)
        {
            return platform.IsOccupied;
        }

        public Vector3 GetPlatformPosition(int platformId)
        {
            var platform = m_Platforms.FirstOrDefault(p => p.PlatformID.Value == platformId);
            return platform ? platform.transform.position : Vector3.zero;
        }

        public Platform GetPlatformById(int platformId)
        {
            return m_Platforms.FirstOrDefault(p => p.PlatformID.Value == platformId);
        }
    }
}