using System;
using UnityEngine;

public class PlayerStateMachine : MonoBehaviour
{
    private Animator _anim;

    public PlayerState CurrentState { get; private set; } = PlayerState.Idle;
    public Action<PlayerState> OnStateChanged; // 상태가 변했을 때 다른 컴포넌트들이 알 수 있도록 이벤트 제공 (함수 포인터 활용)

    public bool IsGrounded { get; set; } //상태 머신이기 때문에 계산은 여기서 안함 (플레이어가 갱신할 수 있도록 set 허용)
    public bool IsCloseToGround { get; set; }
    public bool IsRunInputPressed { get; set; } //달리기키가 눌린 상태인가
    public bool IsPossibleCharge { get; set; } //현재 차지 가능한 상태인가
    public bool IsMoveCut { get; set; } //현재 이동 금지 상태인가
    public bool IsJumpCool { get; set; } //현재 점프 쿨타임 상태인가
    public bool IsAiming { get; set; } // 현재 aim모드인가

    private int _jumpCount = 0;
    private int _maxJumpCount = 1;


    private void Awake()
    {
        _anim = GetComponent<Animator>();
    }

    private void Update()
    {
        if (IsGrounded)
            _jumpCount = 0;
    }

    public void RecordJump()
    {
        if(_maxJumpCount > _jumpCount) _jumpCount++;
    }

    public void ChangeState(PlayerState newState)
    {
        if (CurrentState == newState) return;

        // 상태 전환 규칙 (예: 죽었는데 공격 상태로 갈 수 없음)
        if (CurrentState == PlayerState.Dead) return;

        CurrentState = newState;

        OnStateChanged?.Invoke(newState);

        //Debug.Log($"State Switched to: {newState}");
    }

    public void SetMaxJumpCount(int maxCount)
    {
        _maxJumpCount = maxCount;
    }

    #region 상태확인용 헬퍼함수들
    //지상 이동이 가능한가?
    public bool CanMove() => IsGrounded && !IsMoveCut && (CurrentState == PlayerState.Idle || CurrentState == PlayerState.Walk || CurrentState == PlayerState.Run) && (CurrentState != PlayerState.Inertia && CurrentState != PlayerState.Action && CurrentState != PlayerState.Trans);
    //점프가 가능한 상태인가?
    public bool CanJump()
    {
        bool jumpAlreadyMax = (_maxJumpCount <= _jumpCount);

        return IsGrounded && !IsMoveCut && !jumpAlreadyMax && (CurrentState == PlayerState.Idle || CurrentState == PlayerState.Walk || CurrentState == PlayerState.Run) && (CurrentState != PlayerState.Inertia && CurrentState != PlayerState.Action && CurrentState != PlayerState.Trans);
    }
    //대쉬가 가능한 상태인가?
    public bool CanDodge()
    {
        // 이미 구르는중
        if (CurrentState == PlayerState.Dodge) return false;

        // 공중대쉬 제한
        // if (!IsGrounded) return false;

        // 피격 상태이거나 죽었을 때 안 되게
        if (CurrentState == PlayerState.Hit || CurrentState == PlayerState.Dead) return false;

        if (IsMoveCut) return false;
        if (CurrentState == PlayerState.Inertia) return false;
        if (CurrentState == PlayerState.Action) return false;
        if (CurrentState == PlayerState.Trans) return false;

        // 스태미나 시스템이 있다면 체크
        // if (CurrentStamina < DodgeCost) return false;

        return true;
    }
    //공중에서 조작 가능한 상태인가?
    public bool CanControlInAir() => !IsGrounded && !IsMoveCut && (CurrentState == PlayerState.Jump || CurrentState == PlayerState.Fall) && (CurrentState != PlayerState.Inertia && CurrentState != PlayerState.Action && CurrentState != PlayerState.Trans);
    //공격이 가능한 상태인가?
    public bool CanAttack()
    {
        //이미 공격 중이거나 차징 중이면 공격 불가 (연속기가 있다면 바뀔수 있음)
        if (CurrentState == PlayerState.Attack || CurrentState == PlayerState.Charge)
            return false;

        //피격(Hit) 중이거나 죽었다면(Dead) 공격 불가
        if (CurrentState == PlayerState.Hit || CurrentState == PlayerState.Dead)
            return false;

        if (CurrentState == PlayerState.Dodge || CurrentState == PlayerState.Inertia)
            return false;

        if (CurrentState == PlayerState.Action || CurrentState == PlayerState.Trans)
            return false;

        // (Idle, Walk, Run, Jump, Fall 상태에서 공격 가능)
        return true;
    }
    
    #endregion
}
