// ==============================================
// PlayerController.cs - Spieler-Steuerung
// ==============================================
// 3-Spur-System mit Tastatur und Touch-Eingabe.
// Kollisionserkennung fuer Hindernisse und Items.

using System;
using UnityEngine;

namespace BreakpilotDrive
{
    public class PlayerController : MonoBehaviour
    {
        public static PlayerController Instance { get; private set; }

        [Header("Bewegung")]
        [SerializeField] private float laneDistance = 3f;      // Abstand zwischen Spuren
        [SerializeField] private float laneSwitchSpeed = 10f;  // Geschwindigkeit beim Spurwechsel
        [SerializeField] private float forwardSpeed = 10f;     // Vorwaertsgeschwindigkeit

        [Header("Spuren")]
        [SerializeField] private int currentLane = 1;          // 0=Links, 1=Mitte, 2=Rechts
        private int targetLane = 1;

        [Header("Touch-Steuerung")]
        [SerializeField] private float swipeThreshold = 50f;   // Pixel fuer Swipe-Erkennung
        private Vector2 touchStartPos;
        private bool isSwiping = false;

        [Header("Effekte")]
        [SerializeField] private ParticleSystem crashEffect;
        [SerializeField] private ParticleSystem collectEffect;

        // Zustand
        private bool isAlive = true;
        private bool isInvincible = false;
        private float invincibleTimer = 0f;

        // Events
        public event Action OnCrash;
        public event Action<string> OnItemCollected;

        // Components
        private Rigidbody rb;
        private Animator animator;

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

            rb = GetComponent<Rigidbody>();
            animator = GetComponent<Animator>();
        }

        void Start()
        {
            // Startposition (mittlere Spur)
            currentLane = 1;
            targetLane = 1;
            UpdateTargetPosition();

            // Geschwindigkeit von Difficulty laden
            if (GameManager.Instance?.DifficultySettings != null)
            {
                forwardSpeed = GameManager.Instance.DifficultySettings.lane_speed;
            }
        }

        void Update()
        {
            if (!isAlive || GameManager.Instance?.CurrentState != GameState.Playing)
                return;

            // Eingabe verarbeiten
            HandleInput();

            // Zur Zielspur bewegen
            MoveToTargetLane();

            // Vorwaerts bewegen
            MoveForward();

            // Unverwundbarkeit Timer
            if (isInvincible)
            {
                invincibleTimer -= Time.deltaTime;
                if (invincibleTimer <= 0)
                {
                    isInvincible = false;
                    // Blink-Effekt beenden
                    SetVisibility(true);
                }
            }

            // Distanz zum GameManager melden
            GameManager.Instance?.AddDistance(forwardSpeed * Time.deltaTime);
        }

        // ==============================================
        // Eingabe-Verarbeitung
        // ==============================================
        private void HandleInput()
        {
            // Tastatur-Eingabe
            if (Input.GetKeyDown(KeyCode.A) || Input.GetKeyDown(KeyCode.LeftArrow))
            {
                MoveLane(-1);
            }
            else if (Input.GetKeyDown(KeyCode.D) || Input.GetKeyDown(KeyCode.RightArrow))
            {
                MoveLane(1);
            }

            // Direkte Spurwahl mit Zahlen (auch fuer Quiz)
            if (Input.GetKeyDown(KeyCode.Alpha1) || Input.GetKeyDown(KeyCode.Keypad1))
            {
                SetLane(0);
            }
            else if (Input.GetKeyDown(KeyCode.Alpha2) || Input.GetKeyDown(KeyCode.Keypad2))
            {
                SetLane(1);
            }
            else if (Input.GetKeyDown(KeyCode.Alpha3) || Input.GetKeyDown(KeyCode.Keypad3))
            {
                SetLane(2);
            }

            // Touch-Eingabe
            HandleTouchInput();
        }

        private void HandleTouchInput()
        {
            if (Input.touchCount > 0)
            {
                Touch touch = Input.GetTouch(0);

                switch (touch.phase)
                {
                    case TouchPhase.Began:
                        touchStartPos = touch.position;
                        isSwiping = true;
                        break;

                    case TouchPhase.Moved:
                    case TouchPhase.Ended:
                        if (isSwiping)
                        {
                            Vector2 swipeDelta = touch.position - touchStartPos;

                            if (Mathf.Abs(swipeDelta.x) > swipeThreshold)
                            {
                                if (swipeDelta.x > 0)
                                {
                                    MoveLane(1); // Rechts
                                }
                                else
                                {
                                    MoveLane(-1); // Links
                                }
                                isSwiping = false;
                            }
                        }
                        break;
                }
            }

            // Maus-Simulation (fuer Editor-Tests)
            if (Input.GetMouseButtonDown(0))
            {
                touchStartPos = Input.mousePosition;
                isSwiping = true;
            }
            else if (Input.GetMouseButtonUp(0) && isSwiping)
            {
                Vector2 swipeDelta = (Vector2)Input.mousePosition - touchStartPos;

                if (Mathf.Abs(swipeDelta.x) > swipeThreshold)
                {
                    MoveLane(swipeDelta.x > 0 ? 1 : -1);
                }
                isSwiping = false;
            }
        }

        // ==============================================
        // Spur-Bewegung
        // ==============================================
        private void MoveLane(int direction)
        {
            targetLane = Mathf.Clamp(targetLane + direction, 0, 2);
        }

        private void SetLane(int lane)
        {
            targetLane = Mathf.Clamp(lane, 0, 2);
        }

        private void MoveToTargetLane()
        {
            float targetX = (targetLane - 1) * laneDistance;
            Vector3 targetPos = new Vector3(targetX, transform.position.y, transform.position.z);

            transform.position = Vector3.Lerp(
                transform.position,
                targetPos,
                laneSwitchSpeed * Time.deltaTime
            );

            // Aktuelle Spur aktualisieren
            currentLane = targetLane;
        }

        private void MoveForward()
        {
            // Spieler bleibt stationaer, Welt bewegt sich
            // Alternativ: transform.Translate(Vector3.forward * forwardSpeed * Time.deltaTime);
        }

        private void UpdateTargetPosition()
        {
            float targetX = (targetLane - 1) * laneDistance;
            transform.position = new Vector3(targetX, transform.position.y, transform.position.z);
        }

        // ==============================================
        // Kollisionen
        // ==============================================
        void OnTriggerEnter(Collider other)
        {
            if (!isAlive) return;

            // Hindernis
            if (other.CompareTag("Obstacle"))
            {
                if (!isInvincible)
                {
                    Crash();
                }
            }
            // Sammelbare Items
            else if (other.CompareTag("Coin"))
            {
                CollectItem("coin", 100);
                Destroy(other.gameObject);
            }
            else if (other.CompareTag("Star"))
            {
                CollectItem("star", 500);
                Destroy(other.gameObject);
            }
            else if (other.CompareTag("Shield"))
            {
                CollectItem("shield", 0);
                ActivateShield(5f);
                Destroy(other.gameObject);
            }
            // Quiz-Trigger
            else if (other.CompareTag("QuizTrigger"))
            {
                VisualTrigger trigger = other.GetComponent<VisualTrigger>();
                if (trigger != null)
                {
                    QuizManager.Instance?.ShowQuickQuestion(trigger.TriggerType);
                }
            }
        }

        // ==============================================
        // Crash-Handling
        // ==============================================
        private void Crash()
        {
            // Effekt abspielen
            if (crashEffect != null)
            {
                crashEffect.Play();
            }

            // Animation
            if (animator != null)
            {
                animator.SetTrigger("Crash");
            }

            // Leben verlieren
            GameManager.Instance?.LoseLife();

            // Kurze Unverwundbarkeit
            isInvincible = true;
            invincibleTimer = 2f;
            StartCoroutine(BlinkEffect());

            OnCrash?.Invoke();
        }

        private System.Collections.IEnumerator BlinkEffect()
        {
            while (isInvincible)
            {
                SetVisibility(false);
                yield return new WaitForSeconds(0.1f);
                SetVisibility(true);
                yield return new WaitForSeconds(0.1f);
            }
        }

        private void SetVisibility(bool visible)
        {
            Renderer[] renderers = GetComponentsInChildren<Renderer>();
            foreach (var r in renderers)
            {
                r.enabled = visible;
            }
        }

        // ==============================================
        // Item-Collection
        // ==============================================
        private void CollectItem(string itemType, int points)
        {
            // Effekt abspielen
            if (collectEffect != null)
            {
                collectEffect.Play();
            }

            // Punkte hinzufuegen
            if (points > 0)
            {
                GameManager.Instance?.AddScore(points);
            }

            OnItemCollected?.Invoke(itemType);
        }

        private void ActivateShield(float duration)
        {
            isInvincible = true;
            invincibleTimer = duration;
            // TODO: Schild-Visualisierung
        }

        // ==============================================
        // Oeffentliche Methoden
        // ==============================================
        public void SetSpeed(float speed)
        {
            forwardSpeed = speed;
        }

        public int GetCurrentLane()
        {
            return currentLane;
        }

        public void Reset()
        {
            isAlive = true;
            isInvincible = false;
            currentLane = 1;
            targetLane = 1;
            UpdateTargetPosition();
        }
    }
}
