using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class BattleSetup : MonoBehaviour
{
    List<GameObject> unplacedEnemyCharacters = new List<GameObject>();
    List<GameObject> placedPlayerCharacters = new List<GameObject>();
    List<GameObject> placedEnemyCharacters = new List<GameObject>();
    private List<GameObject> playerCharacters = new List<GameObject>();
    private List<GameObject> enemyCharacters = new List<GameObject>();
    private List<CharacterSelection> playerSelections = new List<CharacterSelection>();
    private List<CharacterSelection> enemySelections = new List<CharacterSelection>();

    [Tooltip("Select the layer(s) that represent the ground for raycasting.")]
    public LayerMask groundLayerMask;

    public GameObject playerPrefab; // Assign in the inspector or through GameManager
    public GameObject enemyPrefab; // Assign in the inspector or through GameManager
    public GameObject SwordPrefab; // Assign in the inspector or through GameManager
    public GameObject BowPrefab; // Assign in the inspector or through GameManager


    GameObject playerSpawnArea;
    GameObject enemySpawnArea;
    Bounds playerSpawnBounds;

    private Camera mainCamera;
    private GameObject currentPlacingCharacterInstance;
    private int nextPlayerCharacterPrefabIndex = 0;
    private bool isPlacingPlayerCharacters = false;
    void Awake()
    {
        mainCamera = Camera.main;
        if (mainCamera == null)
        {
            Debug.LogError("Main camera not found. Please ensure there is a camera tagged as 'MainCamera' in the scene.");
            enabled = false;
            return;
        }

        playerCharacters.Clear();
        enemyCharacters.Clear();

        // Store the selections for use during placement
        playerSelections = new List<CharacterSelection>(BattleSetupData.playerSelections);
        enemySelections = new List<CharacterSelection>(BattleSetupData.enemySelections);

        // Initialize the lists with characters from the game manager or other sources
        playerSpawnArea = GameObject.Find("PlayerSpawnArea");
        enemySpawnArea = GameObject.Find("EnemySpawnArea");

        if (playerSpawnArea == null)
        {
            Debug.LogError("PlayerSpawnArea GameObject not found in scene. Please ensure there is a GameObject named 'PlayerSpawnArea' in the scene.");
            enabled = false;
            return;
        }
        Collider playerSpawnAreaCollider = playerSpawnArea.GetComponent<Collider>();
        if (playerSpawnAreaCollider == null)
        {
            Debug.LogError("PlayerSpawnArea does not have a collider component.");
            enabled = false;
            return;
        }
        playerSpawnBounds = playerSpawnAreaCollider.bounds;
        if (enemySpawnArea == null)
        {
            // Enemy placement might still work if unplacedEnemyCharacters is empty
            Debug.LogWarning("EnemySpawnArea GameObject not found in the scene. Enemy placement might be affected.");
        }

        // Call the setup methods to place characters
        PlaceEnemyCharacters();
        InitiatePlayerCharacterPlacement();
    }

    void EquipWeapon(Character character, string weaponType)
    {
        Weapon weapon = null;
        if (weaponType == "Sword")
        {
            var weaponObj = Instantiate(SwordPrefab, character.transform);
            weapon = weaponObj.GetComponent<Weapon>();
        }
        else if (weaponType == "Bow")
        {
            var weaponObj = Instantiate(BowPrefab, character.transform);
            weapon = weaponObj.GetComponent<Weapon>();
        }
        else
        {
            Debug.LogWarning($"Unknown weapon type: {weaponType}. No weapon equipped.");
        }

        if (weapon != null)
        {
            Transform attachPoint = character.transform.Find("WeaponAttachPoint");
            if (attachPoint != null)
            {
                weapon.transform.SetParent(attachPoint, false);
                weapon.transform.localPosition = Vector3.zero;
                weapon.transform.localRotation = Quaternion.identity;
            }
            else
            {
                weapon.transform.SetParent(character.transform, false);
                weapon.transform.localPosition = new Vector3(0.5f, 0, 0);
            }

            character.Weapon = weapon;
            weapon.SetWielder(character);
        }
    }

    void Update()
    {
        if (!isPlacingPlayerCharacters || currentPlacingCharacterInstance == null)
        {
            return;
        }
        HandleCharacterPlacement();
    }

    private void InitiatePlayerCharacterPlacement()
    {
        if (playerSelections.Count == 0)
        {

            return;
        }
        isPlacingPlayerCharacters = true;
        nextPlayerCharacterPrefabIndex = 0;
        SpawnNextPlayerCharacterForPlacement();
    }

    private void SpawnNextPlayerCharacterForPlacement()
    {
        if (currentPlacingCharacterInstance != null)
        {
            // This case should ideally not happen if logic flows correctly,
            // but as a safeguard if a previous instance wasn't cleaned up.
            Destroy(currentPlacingCharacterInstance);
            currentPlacingCharacterInstance = null;
        }

        if (nextPlayerCharacterPrefabIndex < playerSelections.Count)
        {
            var selection = playerSelections[nextPlayerCharacterPrefabIndex];
            currentPlacingCharacterInstance = Instantiate(playerPrefab);
            currentPlacingCharacterInstance.name = selection.characterName;

            var character = currentPlacingCharacterInstance.GetComponent<Character>();
            if (character != null)
            {
                EquipWeapon(character, selection.weaponType);
                character.CharacterName = selection.characterName + " " + (nextPlayerCharacterPrefabIndex + 1);
            }
            currentPlacingCharacterInstance.GetComponent<NavMeshAgent>().enabled = false;
            // Optionally disable AI or other components that might interfere with placement
            // e.g., currentPlacingCharacterInstance.GetComponent<AIController>()?.enabled = false;

        }
        else
        {
            FinalizePlayerPlacement();
        }
    }

    private void HandleCharacterPlacement()
    {
        Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
        Debug.DrawRay(ray.origin, ray.direction * 200f, Color.yellow); // Visualize the ray
        if (Physics.Raycast(ray, out RaycastHit hit, 200f, groundLayerMask))
        {
            Vector3 targetPosition = hit.point;
            // Clamp position to playerSpawnArea bound (X and Z axis)
            targetPosition.x = Mathf.Clamp(targetPosition.x, playerSpawnBounds.min.x, playerSpawnBounds.max.x);
            targetPosition.z = Mathf.Clamp(targetPosition.z, playerSpawnBounds.min.z, playerSpawnBounds.max.z);
            // Y is determined by the raycast hit on the ground

            // --- Direct Y Position Calculation for Mouse-Following Character ---
            // This approach was found to be more stable than repeatedly calling AdjustCharacterOnGround.
            // It assumes a standard Unity CapsuleCollider where the pivot is at the center.
            Vector3 finalCharacterPosition = targetPosition; // targetPosition.y is from the ground hit (hit.point.y)

            CapsuleCollider capCollider = currentPlacingCharacterInstance.GetComponent<CapsuleCollider>();
            if (capCollider != null)
            {
                // For a capsule, its pivot is typically at its center.
                // To place its bottom on targetPosition.y (ground level),
                // its center (pivot) needs to be at targetPosition.y + (height / 2).
                // We also account for the character's local scale.
                finalCharacterPosition.y = targetPosition.y + (capCollider.height * currentPlacingCharacterInstance.transform.localScale.y / 2f);
            }
            else
            {
                // Fallback if not a capsule or if a different pivot is used.
                // This might need adjustment based on your character's actual pivot and collider.
                Debug.LogWarning($"'{currentPlacingCharacterInstance.name}' does not have a CapsuleCollider. Using default Y offset for placement. Adjust if incorrect.");
                finalCharacterPosition.y = targetPosition.y + 0.5f; // Example offset, adjust as needed
            }
            currentPlacingCharacterInstance.transform.position = finalCharacterPosition;
            // AdjustCharacterOnGround(currentPlacingCharacterInstance); // No longer called every frame for mouse-follow
        }
        else
        {

        }
        // Else mouse is not over valid ground, character stays at last valid position or initial spawn

        if (Input.GetMouseButtonDown(0))
        { // Left-click to place character
            // Check if the current position is valid (within bounds and not overlapping)
            // The position is already clamped and on ground due to the logic above.
            // We primarily need to check for overlaps.
            if (!IsOverlappingOtherCharacters(currentPlacingCharacterInstance))
            {
                PlaceCurrentCharacter();
            }
            else
            {
                Debug.LogWarning("Cannot place character: Overlapping with another character.");
                // Optionally, you could provide feedback to the player about the overlap (e.g. change color?).
            }
        }
        if (Input.GetMouseButtonDown(1))
        { // Right-click to cancel placement
            if (placedPlayerCharacters.Count > 0)
            {
                FinalizePlayerPlacement();
            }
            else
            {

            }
        }
    }

    private void PlaceCurrentCharacter()
    {

        placedPlayerCharacters.Add(currentPlacingCharacterInstance);
        currentPlacingCharacterInstance = null;
        nextPlayerCharacterPrefabIndex++;
        SpawnNextPlayerCharacterForPlacement(); // Spawn next character for placement
    }

    private void AdjustCharacterOnGround(GameObject character)
    {
        if (character == null)
        {
            return;
        }
        Collider charCollider = character.GetComponent<Collider>();
        if (charCollider != null)
        {
            // This ensured the lowest point of the collider is at character.transform.position.y
            // (which should be the ground hit point)
            // currentY is the Y-coordinate of the character's pivot.
            // We want the character's collider bottom (feet) to be at this Y-level.
            float currentY = character.transform.position.y;
            float colliderMinYWorld = charCollider.bounds.min.y;
            float verticalOffset = currentY - colliderMinYWorld;
            const float tolerance = 0.001f; // Small tolerance to avoid floating point issues
            if (Mathf.Abs(verticalOffset) > tolerance)
            {
                character.transform.position += Vector3.up * verticalOffset;
            }
        }
        else
        {
            Debug.LogWarning($"Character: {character.name} has no collider. Cannot accurately adjust to ground.");
        }
    }

    private bool IsOverlappingOtherCharacters(GameObject character)
    {
        Collider newCharCollider = character.GetComponent<Collider>();
        if (newCharCollider == null)
        {
            Debug.LogWarning($"Character: {character.name} has no collider. Cannot check for overlaps.");
            return false; // Or true to precent placement if no collider
        }
        Bounds newCharBounds = newCharCollider.bounds;
        foreach (GameObject placedCharacter in placedPlayerCharacters)
        {
            Collider otherCollider = placedCharacter.GetComponent<Collider>();
            if (otherCollider != null && newCharBounds.Intersects(otherCollider.bounds))
            {
                return true;
            }
        }

        foreach (GameObject placedEnemy in placedEnemyCharacters)
        {
            Collider otherCollider = placedEnemy.GetComponent<Collider>();
            if (otherCollider != null && newCharBounds.Intersects(otherCollider.bounds))
            {
                return true;
            }
        }
        return false;
    }

    private void FinalizePlayerPlacement()
    {
        isPlacingPlayerCharacters = false;
        if (currentPlacingCharacterInstance != null)
        {
            Destroy(currentPlacingCharacterInstance); // Destroy the preview instance if it wasn't placed
            currentPlacingCharacterInstance = null;
        }


        EndPlacementPhase();

        // Here you might want to trigger the next phase of your game, e.g., start the battle.
        GameManager.Instance.StartBattle(placedPlayerCharacters, placedEnemyCharacters);
        Destroy(playerSpawnArea);
        Destroy(enemySpawnArea);
        playerSpawnArea = null;
        enemySpawnArea = null;

    }

    private void EndPlacementPhase()
    {
        // This method can be used to clean up or finalize the placement phase.
        // For example, you might want to enable AI, re-enable NavMeshAgents, etc.
        foreach (GameObject character in placedPlayerCharacters)
        {
            NavMeshAgent agent = character.GetComponent<NavMeshAgent>();
            if (agent != null)
            {
                agent.enabled = true; // Re-enable NavMeshAgent
            }
            // Enable AI or other components as needed
            // e.g., character.GetComponent<AIController>()?.enabled = true;
        }

        foreach (GameObject character in enemyCharacters)
        {
            NavMeshAgent agent = character.GetComponent<NavMeshAgent>();
            if (agent != null)
            {
                agent.enabled = true; // Re-enable NavMeshAgent
            }
            // Enable AI or other components as needed
            // e.g., character.GetComponent<AIController>()?.enabled = true;
        }

    }

    private void PlaceEnemyCharacters()
    {
        Collider spawnAreaCollider = enemySpawnArea.GetComponent<Collider>();
        if (spawnAreaCollider == null)
        {
            Debug.LogError("Enemy spawn area does not have a collider component.");
            return;
        }
        Bounds spawnBounds = spawnAreaCollider.bounds;

        for (int i = enemySelections.Count - 1; i >= 0; i--)
        {
            var selection = enemySelections[i];

            float randomX = UnityEngine.Random.Range(spawnBounds.min.x, spawnBounds.max.x);
            float randomZ = UnityEngine.Random.Range(spawnBounds.min.z, spawnBounds.max.z);

            Vector3 rayOrigin = new Vector3(randomX, enemySpawnArea.transform.position.y + 10f, randomZ);
            Vector3 spawnPosition = new Vector3(randomX, enemySpawnArea.transform.position.y, randomZ);

            // Raycast to find the ground
            if (Physics.Raycast(rayOrigin, Vector3.down, out RaycastHit hit, 200f, groundLayerMask))
            {
                spawnPosition = hit.point;
            }
            else
            {
                Debug.LogWarning($"Raycast did not hit ground below ({randomX}, {randomZ}). Placing enemy at spawn area Y level.");
            }

            GameObject placedEnemy = Instantiate(enemyPrefab, spawnPosition, Quaternion.identity);
            Character character = placedEnemy.GetComponent<Character>();
            if (character != null)
            {
                EquipWeapon(character, selection.weaponType);
                character.CharacterName = selection.characterName + "_" + (i + 1);
            }

            AdjustCharacterOnGround(placedEnemy); // Adjust the enemy to the ground

            placedEnemyCharacters.Add(placedEnemy);
        }
    }
}
