using UnityEngine;

// ============================================================================
// HpBar
// ----------------------------------------------------------------------------
// SpriteRenderer 기반 HP바. Canvas보다 가벼움 (Canvas Rebuild 비용 없음).
// 부모(또는 Inspector 할당)의 Health 컴포넌트 이벤트 OnHealthChanged 구독.
//
// 동작:
//   - Background와 Fill 두 SpriteRenderer로 구성
//   - Fill의 스프라이트 피벗은 LEFT (0, 0.5) 여야 X 스케일 변경 시 왼쪽부터 줄어듦
//   - HP 비율에 따라 _fill.localScale.x 조정
//   - 임계값 기반으로 색상도 자동 변경 (높음/중간/낮음)
// ============================================================================
public class HpBar : MonoBehaviour
{
    [SerializeField] private Health _health;                       // 비워두면 _autoFindHealthInParent로 자동 검색
    [SerializeField] private Transform _fill;                      // 채움 sprite transform (스케일 조정 대상)
    [SerializeField] private bool _autoFindHealthInParent = true;  // _health가 null이면 부모에서 Health 자동 검색
    [SerializeField] private bool _hideWhenFull = true;            // HP 풀이거나 0일 때 HpBar 자동 숨김
    [SerializeField] private float _smoothSpeed = 0f;              // 0이면 즉시 반영, 0보다 크면 보간 (units/sec)

    // ─── 임계값별 색상 ──────────────────────────────────────────────────
    // ratio > _midThreshold    → _highColor   (정상)
    // _lowThreshold < ratio <= _midThreshold → _midColor (주의)
    // ratio <= _lowThreshold   → _lowColor    (위험)
    [Header("Color Thresholds")]
    [SerializeField] private Color _highColor = new Color(0.2f, 0.9f, 0.3f, 1f);
    [SerializeField] private Color _midColor = new Color(1f, 0.85f, 0.2f, 1f);
    [SerializeField] private Color _lowColor = new Color(0.95f, 0.25f, 0.25f, 1f);
    [SerializeField, Range(0f, 1f)] private float _midThreshold = 0.5f;
    [SerializeField, Range(0f, 1f)] private float _lowThreshold = 0.2f;

    private Vector3 _baseFillScale;     // 풀체력 시 Fill 스케일 (Awake에 캐싱, 이후 ratio 곱해서 사용)
    private SpriteRenderer _fillRenderer; // Fill의 색상 변경용 SpriteRenderer
    private float _currentRatio = 1f;   // 현재 표시된 HP 비율 (보간 진행 시 _targetRatio로 수렴)
    private float _targetRatio = 1f;    // 도달해야 할 HP 비율

    private void Awake()
    {
        if (_health == null && _autoFindHealthInParent)
            _health = GetComponentInParent<Health>();

        if (_fill != null)
        {
            _baseFillScale = _fill.localScale;
            _fillRenderer = _fill.GetComponent<SpriteRenderer>();
        }
    }

    // 활성/비활성 토글 시 자동 구독·해제 (메모리 누수 방지).
    // 활성 시 즉시 한 번 갱신해서 현재 HP 상태 반영.
    private void OnEnable()
    {
        if (_health == null) return;

        _health.OnHealthChanged += HandleHealthChanged;
        HandleHealthChanged(_health.CurrentHealth, _health.MaxHealth);
    }

    private void OnDisable()
    {
        if (_health != null)
            _health.OnHealthChanged -= HandleHealthChanged;
    }

    // 보간 모드일 때만 매 프레임 스케일 갱신.
    private void Update()
    {
        if (_smoothSpeed <= 0f) return;
        if (Mathf.Approximately(_currentRatio, _targetRatio)) return;

        _currentRatio = Mathf.MoveTowards(_currentRatio, _targetRatio, _smoothSpeed * Time.deltaTime);
        ApplyScale();
    }

    // Health.OnHealthChanged 이벤트 콜백. ratio 계산 → 스케일/색상 갱신 → 숨김 처리.
    private void HandleHealthChanged(int current, int max)
    {
        _targetRatio = max > 0 ? (float)current / max : 0f;

        // 즉시 모드면 바로 스케일 반영. 보간 모드면 Update에서 점진적으로.
        if (_smoothSpeed <= 0f)
        {
            _currentRatio = _targetRatio;
            ApplyScale();
        }

        ApplyColor(_targetRatio);

        // 풀체력(1)이거나 사망(0)이면 HpBar 자체를 숨김 (UI 정리 + GameObject 부하 감소).
        if (_hideWhenFull && _fill != null)
        {
            bool shouldShow = _targetRatio < 1f && _targetRatio > 0f;
            if (gameObject.activeSelf != shouldShow)
                gameObject.SetActive(shouldShow);
        }
    }

    // Fill의 X 스케일 = baseScale.x × ratio. 피벗이 LEFT여야 왼쪽부터 채워짐.
    private void ApplyScale()
    {
        if (_fill == null) return;

        Vector3 scale = _baseFillScale;
        scale.x = _baseFillScale.x * Mathf.Clamp01(_currentRatio);
        _fill.localScale = scale;
    }

    // 비율 구간 매핑으로 색상 결정. 임계값 교차 시 즉시 바뀜 (보간 안 함).
    private void ApplyColor(float ratio)
    {
        if (_fillRenderer == null) return;

        Color color;
        if (ratio <= _lowThreshold)
            color = _lowColor;
        else if (ratio <= _midThreshold)
            color = _midColor;
        else
            color = _highColor;

        _fillRenderer.color = color;
    }
}
