using UnityEngine;

public class SkillManager : MonoBehaviour
{
    [SerializeField] private int _maxSlots = 4;

    private PlayerStateMachine _stateMachine;
    private Animator _anim;
    private Transform _transform;

    private SkillInstance[] _equippedSkills;
    private ISkillEffect[] _skillEffects;

    private int _chargingSlot = -1;
    private float _chargeTimer = 0f;

    private void Awake()
    {
        _stateMachine = GetComponent<PlayerStateMachine>();
        _anim = GetComponent<Animator>();
        _transform = transform;

        _equippedSkills = new SkillInstance[_maxSlots];
        _skillEffects = new ISkillEffect[_maxSlots];
    }

    private void Update()
    {
        TickCooldowns();
        TickCharge();
    }

    #region 스킬 장착
    public void LoadWeaponSkills(WeaponSkillSet skillSet)
    {
        for (int i = 0; i < _maxSlots; i++)
        {
            if (i < skillSet.Skills.Count && skillSet.Skills[i] != null)
            {
                _equippedSkills[i] = new SkillInstance(skillSet.Skills[i]);
                _skillEffects[i] = ResolveEffect(skillSet.Skills[i].TargetType);
            }
            else
            {
                _equippedSkills[i] = null;
                _skillEffects[i] = null;
            }
        }

        ApplyPassives();
    }

    private ISkillEffect ResolveEffect(TargetType targetType)
    {
        return targetType switch
        {
            TargetType.Self => GetComponent<BuffEffect>(),
            TargetType.Single => GetComponent<DamageEffect>(),
            TargetType.Area => GetComponent<AreaEffect>(),
            TargetType.Projectile => GetComponent<ProjectileEffect>(),
            _ => null
        };
    }
    #endregion

    #region 입력
    public void SkillInput(int slotIndex, InputState inputState)
    {
        if (slotIndex < 0 || slotIndex >= _maxSlots) return;

        SkillInstance skill = _equippedSkills[slotIndex];
        if (skill == null) return;
        if (skill.Data.SkillType == SkillType.Passive) return;

        if (inputState == InputState.Started)
        {
            if (!CanUseSkill(skill)) return;

            if (skill.Data.ActivationType == ActivationType.Instant)
            {
                ExecuteSkill(slotIndex);
            }
            else if (skill.Data.ActivationType == ActivationType.Charge)
            {
                StartCharge(slotIndex);
            }
        }
        else if (inputState == InputState.Canceled)
        {
            if (_chargingSlot == slotIndex)
            {
                ReleaseCharge();
            }
        }
    }
    #endregion

    #region 실행
    private bool CanUseSkill(SkillInstance skill)
    {
        if (skill.IsOnCooldown) return false;

        PlayerState state = _stateMachine.CurrentState;
        if (state == PlayerState.Dead || state == PlayerState.Hit
            || state == PlayerState.Dodge || state == PlayerState.Trans
            || state == PlayerState.Action)
            return false;

        return true;
    }

    private void ExecuteSkill(int slotIndex)
    {
        SkillInstance skill = _equippedSkills[slotIndex];
        ISkillEffect effect = _skillEffects[slotIndex];

        _stateMachine.ChangeState(PlayerState.Attack);

        if (!string.IsNullOrEmpty(skill.Data.AnimTrigger))
            _anim.SetTrigger(skill.Data.AnimTrigger);

        float chargeRatio = 1f;
        if (skill.Data.ActivationType == ActivationType.Charge)
        {
            float maxCharge = skill.CurrentLevelData.ChargeTimeMax;
            chargeRatio = maxCharge > 0 ? Mathf.Clamp01(_chargeTimer / maxCharge) : 1f;
        }

        effect?.Execute(skill, _transform, chargeRatio);

        skill.StartCooldown();
        _chargeTimer = 0f;
        _chargingSlot = -1;
    }
    #endregion

    #region 차지
    private void StartCharge(int slotIndex)
    {
        _chargingSlot = slotIndex;
        _chargeTimer = 0f;

        _stateMachine.ChangeState(PlayerState.Charge);

        SkillInstance skill = _equippedSkills[slotIndex];
        if (!string.IsNullOrEmpty(skill.Data.AnimTrigger))
            _anim.SetTrigger(skill.Data.AnimTrigger);
    }

    private void ReleaseCharge()
    {
        if (_chargingSlot < 0) return;
        ExecuteSkill(_chargingSlot);
    }

    private void TickCharge()
    {
        if (_chargingSlot < 0) return;

        SkillInstance skill = _equippedSkills[_chargingSlot];
        _chargeTimer += Time.deltaTime;

        if (_chargeTimer >= skill.CurrentLevelData.ChargeTimeMax)
        {
            ReleaseCharge();
        }
    }
    #endregion

    #region 쿨다운
    private void TickCooldowns()
    {
        foreach (var skill in _equippedSkills)
        {
            skill?.TickCooldown(Time.deltaTime);
        }
    }
    #endregion

    #region 패시브
    private void ApplyPassives()
    {
        foreach (var skill in _equippedSkills)
        {
            if (skill != null && skill.Data.SkillType == SkillType.Passive)
            {
                // PlayerStat에 스탯 보정 적용
            }
        }
    }
    #endregion

    #region 외부 접근
    public SkillInstance GetSkill(int slotIndex)
    {
        if (slotIndex < 0 || slotIndex >= _maxSlots) return null;
        return _equippedSkills[slotIndex];
    }

    public int MaxSlots => _maxSlots;
    #endregion
}
