using System.Collections;
using UnityEngine;
using Boxes;

public class VanController : MonoBehaviour
{
    [Header("Движение")]
    public float forwardSpeed = 5.0f;
    public float moveSpeed = 10.0f;

    [Header("Спавн коробок")]
    public BoxData[] availableBoxes;
    public float spawnInterval = 0.5f;
    public float boxEjectionForce = 2f;
    public float boxTorqueForce = 5f;

    [Header("AI Уклонения")]
    public float detectionDistance = 40f;
    public LayerMask trafficLayer;

    private int _currentLaneIndex = 3;
    private float _targetX;
    private bool _isChangingLane;
    private float _totalSpawnWeight;
    private bool _isAlive = true;
    
    private int[] _safeLanesBuffer; 

    private void OnEnable()
    {
        GameEvents.OnPlayerDied += StopActivities;
    }

    private void OnDisable()
    {
        GameEvents.OnPlayerDied -= StopActivities;
    }

    void Start()
    {
        _targetX = transform.position.x;
        
        _totalSpawnWeight = 0;
        foreach (var box in availableBoxes)
        {
            _totalSpawnWeight += box.spawnWeight;
        }

        _safeLanesBuffer = new int[RoadManager.Instance.GetLanesCount()];

        StartCoroutine(SpawnBoxesInfinitely());
        StartCoroutine(AvoidanceRoutine());
    }

    void Update()
    {
        if (!_isAlive) return;

        transform.Translate(Vector3.forward * forwardSpeed * Time.deltaTime);
        Vector3 newPos = transform.position;
        newPos.x = Mathf.Lerp(newPos.x, _targetX, Time.deltaTime * moveSpeed);
        transform.position = newPos;
    }

    private void StopActivities() => _isAlive = false;
    
    IEnumerator SpawnBoxesInfinitely()
    {
        while (_isAlive)
        {
            yield return new WaitForSeconds(spawnInterval);
            SpawnPhysicalBox();
        }
    }

    void SpawnPhysicalBox()
    {
        BoxData boxToSpawn = GetRandomBoxType();
        if (boxToSpawn == null || boxToSpawn.boxPrefab == null) return;
        
        GameObject box = SimpleObjectPool.Instance.Get(boxToSpawn.boxPrefab, transform.position, Random.rotation);
        
        Box boxComponent = box.GetComponent<Box>();
        if (boxComponent != null) boxComponent.Init(boxToSpawn);

        Rigidbody rb = box.GetComponent<Rigidbody>();
        if (rb != null)
        {
            rb.linearVelocity = Vector3.zero; 
            rb.angularVelocity = Vector3.zero;
            rb.AddForce(Vector3.back * boxEjectionForce, ForceMode.Impulse);
            rb.AddTorque(Random.insideUnitSphere * boxTorqueForce, ForceMode.Impulse);
        }
    }

    BoxData GetRandomBoxType()
    {
        if (availableBoxes.Length == 0) return null;
        float randomValue = Random.Range(0, _totalSpawnWeight);
        float currentWeight = 0;
        foreach (var boxData in availableBoxes)
        {
            currentWeight += boxData.spawnWeight;
            if (randomValue <= currentWeight) return boxData;
        }
        return null;
    }

    IEnumerator AvoidanceRoutine()
    {
        while (_isAlive)
        {
            yield return new WaitForSeconds(0.2f);
            if (_isChangingLane) continue;
            if (IsObstacleAhead()) TryToEvade();
        }
    }

    bool IsObstacleAhead() => Physics.Raycast(transform.position, Vector3.forward, detectionDistance, trafficLayer);

    void TryToEvade()
    {
        int safeLanesCount = 0;
        int totalLanes = RoadManager.Instance.GetLanesCount();

        for (int i = 0; i < totalLanes; i++)
        {
            if (i == _currentLaneIndex) continue;
            
            float laneX = RoadManager.Instance.GetLaneX(i);
            Vector3 checkPosition = new Vector3(laneX, transform.position.y, transform.position.z);
            
            if (!Physics.Raycast(checkPosition, Vector3.forward, detectionDistance, trafficLayer))
            {
                _safeLanesBuffer[safeLanesCount] = i;
                safeLanesCount++;
            }
        }

        if (safeLanesCount > 0)
        {
            int chosenLane = _safeLanesBuffer[Random.Range(0, safeLanesCount)];
            StartCoroutine(ChangeLane(chosenLane));
        }
    }

    IEnumerator ChangeLane(int newLaneIndex)
    {
        _isChangingLane = true;
        _currentLaneIndex = newLaneIndex;
        _targetX = RoadManager.Instance.GetLaneX(newLaneIndex);
        yield return new WaitForSeconds(0.6f);
        _isChangingLane = false;
    }
}