using UnityEngine;
using Cinemachine;
using System.Collections;

/// <summary>
/// Automatically configures Cinemachine FreeLook camera targets on scene start.
/// Correctly separates Follow (character root) from LookAt (head bone)
/// to prevent orbit collapse and camera looking at the sky.
/// </summary>
public class AutoAddCinemachineCamera : MonoBehaviour
{
    [TagField]
    public string Tag = string.Empty;

    void Start()
    {
        var vcam = GetComponent<CinemachineFreeLook>();
        if (vcam != null && Tag.Length > 0)
        {
            bool isCashSystemMode = SelectionOptions.Instance != null && SelectionOptions.Instance.isCashSystemSelected;
            
            if (isCashSystemMode)
            {
                // In Cash System mode, characters spawn after a delay
                StartCoroutine(FindPlayerControlledTargetDelayed(vcam, 1.0f));
            }
            else
            {
                // Normal mode - find immediately
                var targets = GameObject.FindGameObjectsWithTag(Tag);
                if (targets.Length > 0)
                {
                    SetCameraTargets(vcam, targets[0]);
                }
            }
        }
    }
    
    private IEnumerator FindPlayerControlledTargetDelayed(CinemachineFreeLook vcam, float delay)
    {
        yield return new WaitForSeconds(delay);
        
        // If CameraManager already set targets, don't override
        if (CameraManager.Instance != null && CameraManager.Instance.GetCurrentTarget() != null)
        {
            Debug.Log("[AutoAddCinemachineCamera] CameraManager already handling camera — skipping.");
            yield break;
        }
        
        var targets = GameObject.FindGameObjectsWithTag(Tag);
        
        // Find the character with IsPlayerControlled = true
        foreach (var target in targets)
        {
            TeamMember teamMember = target.GetComponent<TeamMember>();
            if (teamMember != null && teamMember.IsPlayerControlled)
            {
                // Route through CameraManager if available
                if (CameraManager.Instance != null)
                {
                    CameraManager.Instance.SetTarget(teamMember);
                    Debug.Log($"[AutoAddCinemachineCamera] Routed to CameraManager for {target.name}");
                }
                else
                {
                    SetCameraTargets(vcam, target);
                    Debug.Log($"[AutoAddCinemachineCamera] Set targets directly for {target.name}");
                }
                yield break;
            }
        }
        
        // Fallback if no TeamMember found
        if (targets.Length > 0)
        {
            Debug.LogWarning("[AutoAddCinemachineCamera] No player-controlled character found, using first target");
            SetCameraTargets(vcam, targets[0]);
        }
    }
    
    /// <summary>
    /// Set Follow to character ROOT (orbit center) and LookAt to HEAD (aim point).
    /// This is the correct configuration for CinemachineFreeLook.
    /// </summary>
    private void SetCameraTargets(CinemachineFreeLook vcam, GameObject character)
    {
        // Follow = character root (stable orbit center at ground level)
        Transform followTarget = character.transform;
        
        // LookAt = head bone (camera aims at upper body)
        Transform lookAtTarget = FindHeadTransform(character) ?? character.transform;
        
        vcam.Follow = followTarget;
        vcam.LookAt = lookAtTarget;
        
        // CRITICAL: Start at middle rig (0.5), not bottom (0)
        // Without this, camera defaults to looking UP at the character from below
        vcam.m_YAxis.Value = 0.5f;
        
        // Force Cinemachine to recalculate from scratch (forget cached underground position)
        vcam.PreviousStateIsValid = false;
        
        // Clear input axis names — CinemachineCameraInput handles all input
        vcam.m_XAxis.m_InputAxisName = "";
        vcam.m_YAxis.m_InputAxisName = "";
        
        // Set professional orbit heights (consistent with CameraManager)
        vcam.m_Orbits = new CinemachineFreeLook.Orbit[] {
            new CinemachineFreeLook.Orbit(4.5f, 5f),   // TopRig
            new CinemachineFreeLook.Orbit(2.5f, 6f),   // MiddleRig
            new CinemachineFreeLook.Orbit(0.5f, 5f),   // BottomRig
        };
        
        // Configure Composer aim on each rig
        for (int i = 0; i < 3; i++)
        {
            var rig = vcam.GetRig(i);
            if (rig == null) continue;
            var composer = rig.GetCinemachineComponent<CinemachineComposer>();
            if (composer != null)
            {
                composer.m_ScreenX = 0.5f;
                composer.m_ScreenY = 0.4f;
                composer.m_DeadZoneWidth = 0.1f;
                composer.m_DeadZoneHeight = 0.1f;
                composer.m_SoftZoneWidth = 0.8f;
                composer.m_SoftZoneHeight = 0.8f;
            }
        }
        
        // Add CinemachineCollider to prevent camera clipping below terrain
        EnsureCinemachineCollider(vcam);
        
        Debug.Log($"[AutoAddCinemachineCamera] Follow={followTarget.name}, LookAt={lookAtTarget.name}, YAxis=0.5");
    }
    
    /// <summary>
    /// Adds a CinemachineCollider extension so the camera stays above terrain
    /// and doesn't clip through the environment after changing levels.
    /// </summary>
    private void EnsureCinemachineCollider(CinemachineFreeLook vcam)
    {
        var colliderExt = vcam.GetComponent<CinemachineCollider>();
        if (colliderExt == null)
        {
            colliderExt = vcam.gameObject.AddComponent<CinemachineCollider>();
        }
        
        colliderExt.m_Strategy = CinemachineCollider.ResolutionStrategy.PullCameraForward;
        colliderExt.m_CollideAgainst = LayerMask.GetMask("Default", "Ground");
        colliderExt.m_IgnoreTag = "Player";
        colliderExt.m_CameraRadius = 0.2f;
        colliderExt.m_Damping = 0f;
        colliderExt.m_MinimumDistanceFromTarget = 1f;
        
        Debug.Log("[AutoAddCinemachineCamera] CinemachineCollider extension configured for terrain avoidance");
    }
    
    private Transform FindHeadTransform(GameObject character)
    {
        string[] headNames = { "Head", "head", "Bip001 Head", "mixamorig:Head", "Bip01 Head" };
        
        foreach (string headName in headNames)
        {
            Transform head = FindChildRecursive(character.transform, headName);
            if (head != null) return head;
        }
        
        return null;
    }
    
    private Transform FindChildRecursive(Transform parent, string name)
    {
        foreach (Transform child in parent)
        {
            if (child.name == name) return child;
            Transform found = FindChildRecursive(child, name);
            if (found != null) return found;
        }
        return null;
    }
}