using UnityEngine;
using Cinemachine;
using System.Collections;

/// <summary>
/// Resets the Main Camera to a known-good position BEFORE CinemachineBrain takes over,
/// then snaps the camera to the correct position AFTER the character spawns.
/// 
/// This solves the camera-underground problem with a two-phase approach:
/// Phase 1 (Awake): Force camera above ground, set CinemachineBrain blend to Cut
/// Phase 2 (Coroutine): Wait for player character, then force camera to correct orbit position
/// 
/// Attach this to the MainCamera GameObject.
/// </summary>
[DefaultExecutionOrder(-100)] // Run before everything else
public class CameraInitializer : MonoBehaviour
{
    [Header("Safe Starting Position")]
    [Tooltip("Camera starts here before Cinemachine takes control")]
    public Vector3 resetPosition = new Vector3(0f, 10f, -10f);
    public Vector3 resetRotation = new Vector3(20f, 0f, 0f);
    
    [Header("Spawn Wait")]
    [Tooltip("Maximum time to wait for the player character to spawn")]
    [SerializeField] private float maxSpawnWaitTime = 5f;
    
    [Tooltip("How often to check for the player character")]
    [SerializeField] private float spawnCheckInterval = 0.1f;
    
    [Header("Debug")]
    [SerializeField] private bool debugLogging = true;

    private void Awake()
    {
        // ===== PHASE 1: Force camera to a known-good position =====
        transform.position = resetPosition;
        transform.rotation = Quaternion.Euler(resetRotation);
        
        if (debugLogging)
            Debug.Log($"[CameraInitializer] Phase 1: Camera reset to position={resetPosition}");
        
        // Set CinemachineBrain to Cut (instant snap, no blending from underground)
        CinemachineBrain brain = GetComponent<CinemachineBrain>();
        if (brain != null)
        {
            brain.m_DefaultBlend = new CinemachineBlendDefinition(
                CinemachineBlendDefinition.Style.Cut, 0f
            );
            if (debugLogging)
                Debug.Log("[CameraInitializer] CinemachineBrain set to CUT blend");
        }
        
        // Invalidate all FreeLook camera states
        CinemachineFreeLook[] freeLooks = FindObjectsOfType<CinemachineFreeLook>();
        foreach (var fl in freeLooks)
        {
            fl.m_YAxis.Value = 0.5f;
            fl.PreviousStateIsValid = false;
            
            // Set orbit heights
            fl.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
            };
            
            // CRITICAL: Clear default input axis names so Cinemachine doesn't fight
            // with CinemachineCameraInput. Without this, Cinemachine reads Input.GetAxis("Mouse X")
            // which returns 0 and snaps Y axis to bottom rig.
            fl.m_XAxis.m_InputAxisName = "";
            fl.m_YAxis.m_InputAxisName = "";
            
            if (debugLogging)
                Debug.Log($"[CameraInitializer] FreeLook '{fl.name}': YAxis=0.5, axes cleared, state invalidated");
        }
    }

    private IEnumerator Start()
    {
        // ===== PHASE 2: Wait for player character, then snap camera =====
        float elapsed = 0f;
        Transform playerTransform = null;
        
        while (elapsed < maxSpawnWaitTime)
        {
            // Try to find the player character
            playerTransform = FindPlayerCharacter();
            
            if (playerTransform != null)
            {
                if (debugLogging)
                    Debug.Log($"[CameraInitializer] Phase 2: Found player '{playerTransform.name}' at {playerTransform.position} after {elapsed:F1}s");
                break;
            }
            
            yield return new WaitForSeconds(spawnCheckInterval);
            elapsed += spawnCheckInterval;
        }
        
        if (playerTransform == null)
        {
            Debug.LogWarning("[CameraInitializer] Phase 2: No player found within timeout — camera may be incorrect");
            yield break;
        }
        
        // Force camera to the correct position relative to the character
        SnapCameraToCharacter(playerTransform);
        
        // Wait a frame for Cinemachine to process the snap
        yield return null;
        yield return null;
        
        // Restore smooth blending for character switching
        CinemachineBrain brain = GetComponent<CinemachineBrain>();
        if (brain != null)
        {
            brain.m_DefaultBlend = new CinemachineBlendDefinition(
                CinemachineBlendDefinition.Style.EaseInOut, 1f
            );
            if (debugLogging)
                Debug.Log("[CameraInitializer] Phase 2: Blend restored to EaseInOut");
        }
    }
    
    /// <summary>
    /// Force-snap the camera to the correct orbit position relative to the character.
    /// </summary>
    private void SnapCameraToCharacter(Transform character)
    {
        CinemachineFreeLook[] freeLooks = FindObjectsOfType<CinemachineFreeLook>();
        foreach (var fl in freeLooks)
        {
            if (!fl.isActiveAndEnabled) continue;
            
            // Ensure target is set
            if (fl.Follow == null)
            {
                fl.Follow = character;
                fl.LookAt = character;
            }
            
            // Reset to middle rig
            fl.m_YAxis.Value = 0.5f;
            fl.PreviousStateIsValid = false;
            
            // Force camera transform to the correct position
            // MiddleRig: Height 2.5, Radius 6 — camera should be behind and above
            Vector3 targetPos = character.position;
            Vector3 cameraPos = targetPos + new Vector3(0f, 2.5f, -6f);
            
            // Set the Main Camera transform directly
            transform.position = cameraPos;
            transform.LookAt(targetPos + Vector3.up * 1.5f);
            
            if (debugLogging)
            {
                Debug.Log($"[CameraInitializer] Camera snapped to {cameraPos} (character at {targetPos})");
                Debug.Log($"[CameraInitializer] FreeLook Follow={fl.Follow?.name}, LookAt={fl.LookAt?.name}");
            }
        }
    }
    
    /// <summary>
    /// Find the player-controlled character in the scene.
    /// </summary>
    private Transform FindPlayerCharacter()
    {
        // Try CameraManager first
        if (CameraManager.Instance != null)
        {
            var target = CameraManager.Instance.GetCurrentTarget();
            if (target != null) return target.transform;
        }
        
        // Try finding by tag
        GameObject player = GameObject.FindGameObjectWithTag("Player");
        if (player != null) return player.transform;
        
        // Try TeamMember with IsPlayerControlled
        TeamMember[] teamMembers = FindObjectsOfType<TeamMember>();
        foreach (var tm in teamMembers)
        {
            if (tm.IsPlayerControlled) return tm.transform;
        }
        
        return null;
    }
}
