part of '../async_action_button.dart';

typedef AsyncActionCallback = Future<void> Function();
typedef AsyncErrorBuilder = String Function(Object error);

/// Shared style for the inline error message the async-button family renders
/// beneath a control after a caught failure.
TextStyle _asyncErrorTextStyle(BuildContext context) =>
    TextStyle(color: Theme.of(context).colorScheme.error, fontSize: 13);

/// Wraps [action] with a try/catch that pops up an [InfoDialog] on failure
/// (using [errorBuilder] or the default error mapper). Returns `true` on
/// success, `false` on caught failure.
Future<bool> runWithErrorDialog(
  BuildContext context,
  AsyncActionCallback action, {
  AsyncErrorBuilder? errorBuilder,
}) async {
  try {
    await action();
    Haptics.success();
    return true;
  } catch (e) {
    Haptics.error();
    if (!context.mounted) return false;
    final message = errorBuilder != null
        ? errorBuilder(e)
        : errorToUserMessage(e);
    final details = errorToTechnicalDetails(e);
    final body = details != null && details != message
        ? '$message\n\n$details'
        : message;
    InfoDialog.show(context, body, copyable: true, title: 'Fehler');
    return false;
  }
}

/// Reusable busy/error state for the async-button family. Multiple buttons
/// can share the same controller (e.g. a parent toolbar wanting to disable
/// while any one child is running).
class AsyncActionController extends ChangeNotifier {
  bool _busy = false;
  String? _error;

  bool get busy => _busy;
  String? get error => _error;

  Future<bool> run(
    AsyncActionCallback action, {
    AsyncErrorBuilder? errorBuilder,
  }) async {
    if (_busy) return false;
    _busy = true;
    _error = null;
    notifyListeners();
    try {
      await action();
      _busy = false;
      notifyListeners();
      return true;
    } catch (e) {
      _busy = false;
      _error = errorBuilder != null ? errorBuilder(e) : errorToUserMessage(e);
      notifyListeners();
      return false;
    }
  }

  void clearError() {
    if (_error == null) return;
    _error = null;
    notifyListeners();
  }
}
