import 'dart:math' as math;

import '../../../../../core/service/app_sounds.dart';
import '../../../domain/entities/game_entities.dart';

/// ضربانِ قلبِ نوبتِ کاربر: در ثانیه‌های پایانیِ نوبتِ خودِ کاربر صدای ضربان پخش
/// می‌کند و با پایانِ نوبت بلافاصله قطع می‌شود. مستقل از چیدمانِ صحنه است.
///
/// زمان‌سنجِ نوبت دقیقاً هم‌زمان با «حلقه‌ی زمانِ نوبت» در HUD شروع می‌شود؛ آن حلقه
/// با تغییرِ امضای نوبت (نوبت|تعدادِ کارتِ زمین|فاز) ریست می‌شود و به انیمیشنِ بُر/
/// پخش کاری ندارد. اینجا هم شمارش به همان امضا بسته می‌شود و فقط «پخشِ صدا» در حینِ
/// انیمیشن/اینترو خاموش است تا صدا و تصویر یکی شوند.
class TurnHeartbeat {
  double _elapsed = 0;
  bool _beatPlayed = false;
  double _accum = 0;
  bool _wasMyTurn = false;
  String _sig = '';

  /// هر فریم صدا زده می‌شود. [busy] یعنی اینترو/بُر زدن/پخشِ کارت در جریان است
  /// (شمارش ادامه دارد اما صدایی پخش نمی‌شود).
  void update(
    double dt,
    GameState? s, {
    required bool silent,
    required bool busy,
  }) {
    final isMyTurn = s != null &&
        ((s.phase == 'playing' && s.turn == s.yourSeat) ||
            (s.phase == 'choose_trump' && s.hakem == s.yourSeat));

    if (!isMyTurn || silent) {
      if (_wasMyTurn) {
        AppSounds.stopHeartBeat(); // نوبت تمام شد ⇒ توقفِ فوریِ صدا
        _wasMyTurn = false;
      }
      _sig = s == null ? '' : '${s.turn}|${s.trick.length}|${s.phase}';
      return;
    }

    final sig = '${s.turn}|${s.trick.length}|${s.phase}';
    if (!_wasMyTurn || sig != _sig) {
      // شروعِ نوبتِ من (یا نوبتِ جدید) ⇒ شمارش از صفر، هم‌زمان با حلقه‌ی HUD.
      _wasMyTurn = true;
      _sig = sig;
      _elapsed = 0;
      _beatPlayed = false;
      _accum = 0;
      if (s.phase == 'playing' && !busy) AppSounds.turn();
    }
    _elapsed += dt;

    if (busy) return;

    final dur = (s.turnTimeoutMs > 0 ? s.turnTimeoutMs / 1000.0 : 30.0);
    final remaining = dur - _elapsed;
    final warn = math.min(7.0, dur * 0.4);
    // در پنجره‌ی پایانیِ نوبت، ضربان با فاصله‌ی منظم تکرار می‌شود تا تا لحظه‌ی آخر
    // شنیده شود (نه فقط یک ضربانِ زودهنگام که در سکوتِ پایانی گم می‌شود).
    if (remaining > 0 && remaining <= warn) {
      if (!_beatPlayed) {
        _beatPlayed = true;
        _accum = 0;
        AppSounds.heartBeat();
      } else {
        _accum += dt;
        if (_accum >= 0.95) {
          _accum = 0;
          AppSounds.heartBeat();
        }
      }
    }
  }

  void stop() => AppSounds.stopHeartBeat();
}
