using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class PlayerDecisionController : MonoBehaviour
{
    [Header("References")]
    public LayerMask enemyLayerMask = 1 << 10; // Enemies are on layer 10
    public LayerMask playerLayerMask = 1 << 9; // Players are on layer 9

    [Header("Settings")]
    public float enemySnapDistance = 1f;

    private List<Character> playerCharacters = new List<Character>();
    private Character selectedCharacter;
    private TargetingLine targetingLine;
    private Camera mainCamera;
    private bool isDragging = false;
    private Vector3 dragStartPosition;
    private bool isEnabled = true;
    private List<TargetingLine> activeActionLines = new List<TargetingLine>();

    void Awake()
    {
        mainCamera = Camera.main;
        targetingLine = GetComponent<TargetingLine>();
        if (targetingLine == null)
        {
            targetingLine = gameObject.AddComponent<TargetingLine>();
        }
    }

    void Start()
    {

        InitializePlayerCharacters();

    }

    void Update()
    {
        HandleInput();
    }

    private void InitializePlayerCharacters()
    {
        // Get player characters from GameManager if available
        if (GameManager.Instance != null)
        {
            playerCharacters.Clear();
            foreach (GameObject playerGO in GameManager.Instance.playerCharacters)
            {
                Character character = playerGO.GetComponent<Character>();
                if (character != null)
                {
                    playerCharacters.Add(character);
                }
            }
        }
        else
        {
            // Fallback: find all characters (for testing without GameManager)
            Character[] characters = FindObjectsByType<Character>(FindObjectsSortMode.None);
            playerCharacters.AddRange(characters);
        }

        foreach (Character character in playerCharacters)
        {
            character.actionData.Reset();
            character.SetVisualState(ActionDecisionState.NoAction);

        }
    }

    private void HandleInput()
    {
        if (!isEnabled) return;

        if (Input.GetMouseButtonDown(0)) // Left click
        {
            HandleLeftClickDown();
        }
        else if (Input.GetMouseButton(0) && isDragging) // Left drag
        {
            HandleLeftDrag();
        }
        else if (Input.GetMouseButtonUp(0)) // Left release
        {
            HandleLeftClickUp();
        }
        else if (Input.GetMouseButtonDown(1)) // Right click
        {
            HandleRightClick();
        }
    }

    private void HandleLeftClickDown()
    {
        Vector3 mouseWorldPosition = GetMouseWorldPosition();
        Character clickedCharacter = GetPlayerCharacterAtPosition(mouseWorldPosition);



        if (clickedCharacter != null)
        {
            selectedCharacter = clickedCharacter;
            isDragging = true;
            dragStartPosition = clickedCharacter.transform.position;

            // Clear any existing action lines before starting new targeting
            ClearActionLineForCharacter(clickedCharacter);

            targetingLine.StartTargeting(dragStartPosition);


            // CinemachineCameraController.Instance.FocusOnCharacter(clickedCharacter.transform);
        }
    }
    private void HandleLeftDrag()
    {
        if (selectedCharacter == null) return;

        Vector3 mouseWorldPos = GetMouseWorldPosition();
        GameObject enemyAtMouse = GetEnemyAtPosition(mouseWorldPos);


        if (enemyAtMouse != null)
        {
            // Snap to enemy
            Vector3 enemyPos = enemyAtMouse.transform.position;
            targetingLine.UpdateTargeting(dragStartPosition, enemyPos, true);
        }
        else
        {
            // Follow mouse
            targetingLine.UpdateTargeting(dragStartPosition, mouseWorldPos, false);
        }
    }

    private void HandleLeftClickUp()
    {
        if (!isDragging || selectedCharacter == null) return;

        Vector3 mouseWorldPos = GetMouseWorldPosition();
        GameObject enemyAtMouse = GetEnemyAtPosition(mouseWorldPos);

        if (enemyAtMouse != null)
        {
            // Set attack target
            selectedCharacter.actionData.SetAttackTarget(enemyAtMouse);

        }
        else
        {
            // Set move target
            selectedCharacter.actionData.SetMoveTarget(mouseWorldPos);

        }

        selectedCharacter.SetVisualState(selectedCharacter.actionData.state);

        // Cleanup
        targetingLine.StopTargeting();
        selectedCharacter = null;
        isDragging = false;
    }

    private void HandleRightClick()
    {
        if (isDragging && selectedCharacter != null)
        {
            // Cancel current action
            selectedCharacter.actionData.Reset();
            selectedCharacter.SetVisualState(ActionDecisionState.NoAction);

            targetingLine.StopTargeting();
            selectedCharacter = null;
            isDragging = false;
        }
        else
        {
            // Right click on character to reset their action
            Vector3 mouseWorldPos = GetMouseWorldPosition();
            Character clickedCharacter = GetPlayerCharacterAtPosition(mouseWorldPos);

            if (clickedCharacter != null)
            {
                clickedCharacter.actionData.Reset();
                clickedCharacter.SetVisualState(ActionDecisionState.NoAction);
            }
        }
    }

    private Vector3 GetMouseWorldPosition()
    {
        Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;

        // Raycast against a ground plane or existing colliders
        if (Physics.Raycast(ray, out hit, 200f))
        {
            return hit.point;
        }

        // Fallback: project onto a horizontal plane at y=0
        Plane groundPlane = new Plane(Vector3.up, Vector3.zero);
        if (groundPlane.Raycast(ray, out float distance))
        {
            return ray.GetPoint(distance);
        }

        return Vector3.zero;
    }

    private Character GetPlayerCharacterAtPosition(Vector3 worldPosition)
    {
        Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;



        if (Physics.Raycast(ray, out hit, 200f, playerLayerMask))
        {

            return hit.collider.GetComponent<Character>();
        }

        // Try raycast without layer mask to see what we're hitting
        if (Physics.Raycast(ray, out hit, 200f))
        {

        }
        else
        {

        }

        return null;
    }

    private GameObject GetEnemyAtPosition(Vector3 worldPosition)
    {
        Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;

        if (Physics.Raycast(ray, out hit, 200f, enemyLayerMask))
        {
            return hit.collider.gameObject;
        }
        return null;
    }

    public bool AllCharactersHaveActions()
    {
        foreach (var character in playerCharacters)
        {
            // Characters need actions if they have no action set
            if (character.actionData.state == ActionDecisionState.NoAction)
                return false;
        }
        return true;
    }

    public void ResetAllCharacterActions()
    {
        foreach (var character in playerCharacters)
        {
            character.actionData.Reset();
            character.SetVisualState(ActionDecisionState.NoAction);
        }
    }

    public void UpdateVisualStates()
    {
        foreach (var character in playerCharacters)
        {
            // Update visual states based on current action status
            if (character.actionData.state == ActionDecisionState.NoAction)
            {
                character.SetVisualState(ActionDecisionState.NoAction); // Pink

            }
            else if (character.HasActionSelected())
            {
                character.SetVisualState(ActionDecisionState.ActionSelected); // Green

            }
        }
    }

    public void RefreshPlayerCharacters()
    {
        InitializePlayerCharacters();
    }

    public void SetEnabled(bool enabled)
    {
        isEnabled = enabled;
        if (!enabled)
        {
            if (isDragging)
            {
                // Cancel any current dragging operation
                targetingLine.StopTargeting();
                selectedCharacter = null;
                isDragging = false;
            }
            // Don't automatically hide action lines when disabling - let caller decide
        }

    }

    public void ShowActiveActionLines()
    {
        HideActiveActionLines(); // Clear any existing lines first

        foreach (var character in playerCharacters)
        {
            if (character.HasActionSelected() && !character.IsActionComplete())
            {
                GameObject lineObject = new GameObject($"ActionLine_{character.name}");
                TargetingLine line = lineObject.AddComponent<TargetingLine>();
                activeActionLines.Add(line);

                Vector3 startPos = character.transform.position + Vector3.up * 0.5f;

                if (character.actionData.targetEnemy != null)
                {
                    Vector3 endPos = character.actionData.targetEnemy.transform.position + Vector3.up * 0.5f;
                    line.StartTargeting(startPos);
                    line.UpdateTargeting(startPos, endPos, true); // true for enemy target (red line)

                }
                else if (character.actionData.targetPosition != Vector3.zero)
                {
                    line.StartTargeting(startPos);
                    line.UpdateTargeting(startPos, character.actionData.targetPosition, false); // false for movement (blue line)

                }
            }
        }
    }

    public void HideActiveActionLines()
    {
        foreach (var line in activeActionLines)
        {
            if (line != null)
            {
                line.StopTargeting();
                Destroy(line.gameObject);
            }
        }
        activeActionLines.Clear();

    }

    public void ClearActionLineForCharacter(Character character)
    {
        for (int i = activeActionLines.Count - 1; i >= 0; i--)
        {
            var line = activeActionLines[i];
            if (line != null && line.gameObject.name == $"ActionLine_{character.name}")
            {
                line.StopTargeting();
                Destroy(line.gameObject);
                activeActionLines.RemoveAt(i);

                break;
            }
        }
    }
}