using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody2D))]
public class EnemyBrain : MonoBehaviour
{
    public EnemyCombat Combat { get; private set; }
    
    [Header("Configuration")]
    private EnemyEntity _entity;
    private EnemyConfig _config;
    private EnemyDecisionContext _context;
    private EnemyAction _currentAction;
    
    private Health _health;
    private Transform _playerTransform;
    private EnemyMotor _motor;
    
    public EnemyRole _currentRole = EnemyRole.Idle;
    private Vector2 _desiredPosition;
    private bool _firstTimeSpottingThePlayer = true;
    
    [SerializeField] private LayerMask playerMask;
    [SerializeField] private Transform attackPoint;
    [SerializeField] public EnemyAnimation animationBridge;
    [SerializeField] private GameObject ExclamationMarkPopUpPrefab;
    [Header("Formation/Slotting")]
    [SerializeField] public float slotArrivalTolerance = 0.3f;
    
    [Header("Child Components")]
    [SerializeField] private Transform spriteTransform;
    
    [SerializeField] private List<EnemyAction> possibleActions;
    
    public void Initialize(EnemyEntity entity, EnemyConfig config)
    {   
        _entity = entity;
        _config = config;
        
        Combat = GetComponent<EnemyCombat>();
        _health = GetComponent<Health>();
        _motor = GetComponent<EnemyMotor>();
        
        Combat.Initialize(config, GetComponent<BoxCollider2D>(), attackPoint, playerMask, animationBridge);
        _motor.Initialize(spriteTransform);
        if (EnemyCoordinator.Instance != null)
        {
            //Debug.Log("is the coordinator instance null?");
            _playerTransform = EnemyCoordinator.Instance.GetPlayer();
        }
            
    }
    void Update()
    {
        if (_health != null && _health.CurrentHealth <= 0) return;
        if (_playerTransform == null) return;
        
        HandleFacing();
    }

    
    private void FixedUpdate()
    {
        if (_playerTransform == null)
        {
            _playerTransform = EnemyCoordinator.Instance.GetPlayer();
        }
        if (_health != null && _health.CurrentHealth <= 0) return;
        if (_playerTransform == null) return;
        
        DecideAndAct();
        
    }

    [Header("AI Settings")]
    [SerializeField] private float decisionInterval = 0.2f;
    private float _nextDecisionTime;

    private void DecideAndAct()
    {
        //Dog(Combat.IsStunned);
        //if(_currentAction != null)Debug.Log(_currentAction.name);
        //return if we are in mid attack or block
        if (Combat.IsAttacking || Combat.IsBlocking || Combat.IsStunned)
            return;
        
        // Optimize: Only make new decisions periodically to prevent jitter
        if (Time.time < _nextDecisionTime)
        {
            // Even if we don't pick a NEW action, we must execute the CURRENT one if it exists
            if (_currentAction != null)
            {
                _currentAction.Execute(this, _context);
            }
            return;
        }

        // 1. Build Context (The eyes/ears of the enemy)
        _context = BuildDecisionContext();

        // 2. Decide (The thinking)
        EnemyAction bestAction = null;
        float bestScore = -1f;
        
        foreach(var action in possibleActions)
        {
            float score = action.CalculateUtility(_context);
            if(score > bestScore)
            {
                bestScore = score;
                bestAction = action;
            }
        }

        // 3. Act (The doing)
        if(bestAction != null)
        {
            _currentAction = bestAction;
            // Pass the Brain reference so the Action can tell the Motor what to do
            bestAction.Execute(this, _context); 
            _nextDecisionTime = Time.time + decisionInterval;
        }
    }
    
    public void MoveTowardsSlot() => _motor.MoveTowardsSlot(_desiredPosition, _config.moveSpeed, slotArrivalTolerance);
    public void Retreat() => _motor.Retreat(_playerTransform.position, _config.moveSpeed);
    private void HandleFacing() => _motor.HandleFacing(_playerTransform.position.x);
    
    public void SetDesiredSlot(Vector2 slotPosition)
    {
        _desiredPosition = slotPosition;
    }

    public void SetRole(EnemyRole newRole)
    {
        _currentRole = newRole;
        if (_currentRole == EnemyRole.Approach && _firstTimeSpottingThePlayer)
        {
            GameObject ExMark = Instantiate(ExclamationMarkPopUpPrefab, transform.position + Vector3.up * 2, Quaternion.identity);
            ExMark.transform.SetParent(transform);
            ExMark.GetComponent<PlayerSpottedPopUp>().Init();
            _firstTimeSpottingThePlayer = false;
        }
    }
    
    public float GetEngageDistance()
    {
        return _config.engageDistance;
    }
    
    public EnemyDecisionContext BuildDecisionContext()
    {
        var selfPos = (Vector2)transform.position;
        var playerPos = (Vector2)_playerTransform.position;

        return new EnemyDecisionContext
        {
            Entity = _entity,
            Config = _config,
            CurrentRole = _currentRole,
            PlayerTransform = _playerTransform,
            DistanceToPlayer = Vector2.Distance(selfPos, playerPos),
            TimeSinceLastAttack = Time.time - Combat.TimeSinceLastAttack
        };
    }
}

public struct EnemyDecisionContext
{
    public EnemyEntity Entity;
    public EnemyConfig Config;
    public Transform PlayerTransform;
    public EnemyRole CurrentRole;
    public float DistanceToPlayer;
    public float TimeSinceLastAttack;
}