import '../../about/external/data/Commitment.dart';
import '../../about/external/data/LiveSession.dart';
import '../../about/external/initial/AbandonRequest.dart';
import '../../about/external/initial/CompletionRequest.dart';
import '../../configs/NotificationServiceConfig.dart';
import '../parent/ParentViewModel.dart';
import 'ConnectLiveTask.dart';

class ViewLiveTask extends ParentViewModel {
  ConnectLiveTask connection;

  ViewLiveTask(super.context, this.connection);

  /// Mirrors the live state into the ongoing notification, so the run is
  /// visible and controllable from the lock screen.
  void publishSession(LiveSession session) {
    LocalNotificationEngine.showSessionNotification(session);
  }

  void clearSession() {
    LocalNotificationEngine.cancelSessionNotification();
  }

  /// Completion is refused until the foreground requirement is actually met.
  /// The timer is the proof, so it cannot be talked past.
  void complete(Commitment commitment, LiveSession session) async {
    if (!session.satisfied()) {
      connection.onTooEarly(session.remainingSeconds());
      return;
    }

    if (!await hasNetwork(() => complete(commitment, session))) return;

    showLoading("Recording");

    try {
      await getDataManager().completeCommitmentEntry(CompletionRequest(
        commitmentId: commitment.id ?? "",
        proofType: commitment.proofType.name,
        timerSeconds: session.elapsedSeconds(),
      ));

      clearSession();

      closeLoading();

      connection.onCompleted();
    } catch (e) {
      handleError(e, () => complete(commitment, session), () => dismissError(),
          "Retry");
    }
  }

  void abandon(Commitment commitment, String reason) async {
    if (!await hasNetwork(() => abandon(commitment, reason))) return;

    showLoading("Recording");

    try {
      await getDataManager().abandonCommitmentEntry(AbandonRequest(
        commitmentId: commitment.id ?? "",
        reason: reason,
      ));

      clearSession();

      closeLoading();

      connection.onAbandoned();
    } catch (e) {
      handleError(
          e, () => abandon(commitment, reason), () => dismissError(), "Retry");
    }
  }
}
