import '../../about/external/initial/SickModeRequest.dart';
import '../../about/external/initial/ToneRequest.dart';
import '../../about/internal/application/MeDescription.dart';
import '../../about/internal/application/ToneLevel.dart';
import '../../about/internal/application/UserDetails.dart';
import '../../utils/GuardrailEngine.dart';
import '../../utils/Thresholds.dart';
import '../parent/ParentViewModel.dart';
import 'ConnectSettings.dart';

class ViewSettings extends ParentViewModel {
  ConnectSettings connection;

  ViewSettings(super.context, this.connection);

  void initialise() async {
    final UserDetails details = await getDataManager().getUserDetails();

    final int spent = await getDataManager().getAmnestySpent();

    connection.onUserLoaded(
      details,
      GuardrailEngine.tokensRemaining(Thresholds.amnestyTokensPerMonth, spent),
    );
  }

  /// The tone slider is capped: it changes register, never cruelty.
  void changeTone(ToneLevel tone) async {
    if (!await hasNetwork(() => changeTone(tone))) return;

    showLoading("Saving");

    try {
      await getDataManager().updateTone(ToneRequest(tone: tone.name));

      final UserDetails details = await getDataManager().getUserDetails();
      details.tone = tone;
      await getDataManager().setUserDetails(details);

      closeLoading();

      connection.onToneChanged(details);
    } catch (e) {
      handleError(e, () => changeTone(tone), () => dismissError(), "Retry");
    }
  }

  /// Sick mode pauses debt accrual entirely. It requires a reason and is
  /// logged, so it stays honest without being punitive.
  void setSickMode(bool enabled, String reason) async {
    if (!await hasNetwork(() => setSickMode(enabled, reason))) return;

    showLoading(enabled ? "Pausing" : "Resuming");

    try {
      await getDataManager().updateSickMode(SickModeRequest(
        enabled: enabled,
        reason: reason,
      ));

      final UserDetails details = await getDataManager().getUserDetails();
      details.sickMode = enabled;
      await getDataManager().setUserDetails(details);

      closeLoading();

      connection.onSickModeChanged(details);
    } catch (e) {
      handleError(e, () => setSickMode(enabled, reason), () => dismissError(),
          "Retry");
    }
  }

  void signOut() async {
    showLoading("Signing out");

    try {
      await getDataManager().logout();
    } catch (e) {
      // A failed logout call must never trap the user in the app; the local
      // session is cleared either way.
    }

    await getDataManager()
        .setMyDescription(MeDescription(id: "", name: "", token: ""));

    closeLoading();

    connection.onSignedOut();
  }
}
