// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:async';

import 'package:meta/meta.dart' as meta;
import 'package:test_api/hooks.dart';

import 'describe.dart';
import 'extensions/async.dart';
import 'extensions/core.dart';
import 'extensions/iterable.dart';

/// A target for checking expectations against a value in a test.
///
/// A subject my have a real value, in which case the expectations can be
/// validated or rejected; or it may be a placeholder, in which case
/// expectations describe what would be checked but cannot be rejected.
///
/// Expectation methods are defined in extensions `on Subject`, specialized on
/// the generic [T].
/// Expectation extension methods can use the [ContextExtension] to interact
/// with the [Context] for this subject.
///
/// Create a subject that throws an exception for missed expectations with the
/// [check] function.
final class Subject<T> {
  final Context<T> _context;
  Subject._(this._context);
}

/// A callback that synchronously checks expectations against a subject.
///
/// Asynchronous expectations should not be used within a `Condition` callback.
typedef Condition<T> = void Function(Subject<T>);

/// A callback that asynchronously checks expectations against a subject.
///
/// Any expectations may be used within an `AsyncCondition` callback.
typedef AsyncCondition<T> = FutureOr<void> Function(Subject<T>);

extension SkipExtension<T> on Subject<T> {
  /// Mark the currently running test as skipped and return a [Subject] that
  /// will ignore all expectations.
  ///
  /// Any expectations against the return value will not be checked and will not
  /// be included in the "Expected" or "Actual" string representations of a
  /// failure.
  ///
  /// ```dart
  /// check(actual)
  ///     ..stillChecked()
  ///     ..skip('reason the expectation is temporarily not met').notChecked();
  /// ```
  ///
  /// If `skip` is used in a callback passed to `softCheck` or `describe` it
  /// will still mark the test as skipped, even though failing the expectation
  /// would not have otherwise caused the test to fail.
  Subject<T> skip(String message) {
    TestHandle.current.markSkipped(message);
    return Subject._(_SkippedContext());
  }
}

/// Creates a [Subject] that can be used to validate expectations against
/// [value], with an exception upon a failed expectation.
///
/// Expectations that are not satisfied throw a [TestFailure] to interrupt the
/// currently running test and mark it as failed.
///
/// If [because] is passed it will be included as a "Reason:" line in failure
/// messages.
///
/// ```dart
/// check(actual).equals(expected);
/// ```
@meta.useResult
Subject<T> check<T>(T value, {String? because}) => Subject._(_TestContext._root(
      value: _Present(value),
      // TODO - switch between "a" and "an"
      label: 'a $T',
      fail: (f) {
        final which = f.rejection.which;
        throw TestFailure([
          ...prefixFirst('Expected: ', f.detail.expected),
          ...prefixFirst('Actual: ', f.detail.actual),
          ...indent(
              prefixFirst('Actual: ', f.rejection.actual), f.detail.depth),
          if (which != null && which.isNotEmpty)
            ...indent(prefixFirst('Which: ', which), f.detail.depth),
          if (because != null) 'Reason: $because',
        ].join('\n'));
      },
      allowAsync: true,
      allowUnawaited: true,
    ));

/// Checks whether [value] satisfies all expectations invoked in [condition],
/// without throwing an exception.
///
/// Returns `null` if all expectations are satisfied, otherwise returns the
/// [CheckFailure] for the first expectation that fails.
///
/// Asynchronous expectations are not allowed in [condition] and will cause a
/// runtime error if they are used.
CheckFailure? softCheck<T>(T value, Condition<T> condition) {
  CheckFailure? failure;
  final subject = Subject<T>._(_TestContext._root(
    value: _Present(value),
    fail: (f) {
      failure ??= f;
    },
    allowAsync: false,
    allowUnawaited: false,
  ));
  condition(subject);
  return failure;
}

/// Checks whether [value] satisfies all expectations invoked in [condition],
/// without throwing an exception.
///
/// The future will complete to `null` if all expectations are satisfied,
/// otherwise it will complete to the [CheckFailure] for the first expectation
/// that fails.
///
/// In contrast to [softCheck], asynchronous expectations are allowed in
/// [condition].
Future<CheckFailure?> softCheckAsync<T>(
    T value, AsyncCondition<T> condition) async {
  CheckFailure? failure;
  final subject = Subject<T>._(_TestContext._root(
    value: _Present(value),
    fail: (f) {
      failure ??= f;
    },
    allowAsync: true,
    allowUnawaited: false,
  ));
  await condition(subject);
  return failure;
}

/// Creates a description of the expectations checked by [condition].
///
/// The strings are individual lines of a description.
/// The description of an expectation may be one or more adjacent lines.
///
/// Matches the "Expected: " lines in the output of a failure message if a value
/// did not meet the last expectation in [condition], without the first labeled
/// line.
///
/// Asynchronous expectations are not allowed in [condition], for async
/// conditions use [describeAsync].
Iterable<String> describe<T>(Condition<T> condition) {
  final context = _TestContext<T>._root(
    value: _Absent(),
    fail: (_) {
      throw UnimplementedError();
    },
    allowAsync: false,
    allowUnawaited: true,
  );
  condition(Subject._(context));
  return context.detail(context).expected.skip(1);
}

/// Creates a description of the expectations checked by [condition].
///
/// The strings are individual lines of a description.
/// The description of an expectation may be one or more adjacent lines.
///
/// Matches the "Expected: " lines in the output of a failure message if a value
/// did not meet the last expectation in [condition], without the first labeled
/// line.
///
/// In contrast to [describe], asynchronous expectations are allowed in
/// [condition].
Future<Iterable<String>> describeAsync<T>(AsyncCondition<T> condition) async {
  final context = _TestContext<T>._root(
    value: _Absent(),
    fail: (_) {
      throw UnimplementedError();
    },
    allowAsync: true,
    allowUnawaited: true,
  );
  await condition(Subject._(context));
  return context.detail(context).expected.skip(1);
}

extension ContextExtension<T> on Subject<T> {
  /// The expectations and nesting context for this subject.
  Context<T> get context => _context;
}

/// The context for a [Subject] that allows asserting expectations and creating
/// nested subjects.
///
/// A [Subject] is the target for checking expectations in a test.
/// Every subject has a [Context] which holds the "actual" value, tracks how the
/// value was obtained, and can check expectations about the value.
///
/// The user focused APIs called within tests are expectation extension methods
/// written in an extension `on Subject`, typically specialized to a specific
/// generic.
///
/// Expectation extension methods will make a call to one of the APIs on the
/// subject's [Context], and can perform one of two types of operations:
///
/// -   Expect something of the current value (such as [CoreChecks.equals] or
///     [IterableChecks.contains]) by calling [expect], [expectAsync], or
///     [expectUnawaited].
/// -   Expect that a new subject can be extracted from the current value (such
///     as [CoreChecks.has] or [FutureChecks.completes]) by calling [nest] or
///     [nestAsync].
///
///
/// Whichever type of operation, an expectation extension method provides two
/// callbacks.
/// The first callback is an `Iterable<String> Function()` returning a
/// description of the expectation.
/// The second callback always takes the actual value as an argument, and the
/// specific signature varies by operation.
///
///
/// In expectation extension methods calling [expect], [expectAync], or
/// [expectUnawaited], the `predicate` callback can report a [Rejection] if the
/// value fails to satisfy the expectation.
/// The description will be passed in a "clause" callback.
/// {@template clause_description}
/// The clause callback returns a description of what is checked which stands
/// on its own.
/// For instance the `is equal to <1>` in:
///
/// ```
/// Expected: a int that:
///   is equal to <1>
/// ```
/// {@endtemplate}
///
///
/// In expectation extension methods calling [nest] or [nestAsync], the
/// `extract` callback can return a [Extracted.rejection] if the value fails to
/// satisfy an expectation which disallows extracting the value, or an
/// [Extracted.value] to become the value in a nested subject.
/// The description will be passed in a "label" callback.
/// {@template label_description}
/// The label callback returns a description of the extracted subject as it
/// relates to the original subject.
/// For instance the `completes to a value` in:
///
/// ```
/// Expected a Future<int> that:
///   completes to a value that:
///     is equal to <1>
/// ```
///
/// A label should also be sensible when it is read as a clause.
/// If no further expectations are checked on the extracted subject, or if the
/// extraction is rejected, the "that:" is omitted in the output.
///
/// ```
///   Expected a Future<int> that:
///     completes to a value
/// ```
/// {@endtemplate}
///
///
/// A rejection carries two descriptions, one description of the "actual" value
/// that was tested, and an optional "which" with further details about how the
/// result different from the expectation.
/// If the "actual" argument is omitted it will be filled with a representation
/// of the value passed to the expectation callback formatted with [literal].
/// If an expectation extension method is written on a type of subject without a
/// useful `toString()`, the rejection can provide a string representation to
/// use instead.
/// The "which" argument may be omitted if the reason is very obvious based on
/// the clause and "actual" description, but most expectations should include a
/// "which".
///
/// The behavior of a context following a rejection depends on the source of the
/// [Subject].
///
/// When an expectation is rejected for a [check] subject, an exception is
/// thrown to interrupt the test, so no further checks should happen. The
/// failure message will include:
/// -  An "Expected" section with descriptions of all the expectations that
///    were checked, including the ones that passed, and the last one that
///    failed.
/// -  An "Actual" section, which may be the description directly from the
///    [Rejection] if the failure was on the root subject, or may start with a
///    partial version of the "Expected" description up to the label for the
///    nesting subject that saw a failure, then the "actual" from the rejection.
/// -  A "Which" description from the rejection, if it was included.
///
/// For example, if a failure happens on the root subject, the "actual" is taken
/// directly from the rejection.
///
/// ```
/// Expected: a Future<int> that:
///   completes to a value
/// Actual: a future that completes as an error
/// Which: threw <UnimplementedError> at:
/// <stack trace>
/// ```
///
/// But if the failure happens on a nested subject, the actual starts with a
/// description of the nesting or non-nesting expectations that succeeded, up
/// to nesting point of the failure, then the "actual" and "which" from the
/// rejection are indented to that level of nesting.
///
/// ```
/// Expected: a Future<int> that:
///   completes to a value that:
///     equals <1>
/// Actual: a Future<int> that:
///   completes to a value that:
///   Actual: <0>
///   Which: are not equal
/// ```
///
/// ```dart
/// extension CustomChecks on Subject<CustomType> {
///   void someExpectation() {
///     context.expect(() => ['meets this expectation'], (actual) {
///       if (_expectationIsMet(actual)) return null;
///       return Rejection(which: ['does not meet this expectation']);
///     });
///   }
///
///   Subject<Foo> get someDerivedValue =>
///       context.nest('has someDerivedValue', (actual) {
///         if (_cannotReadDerivedValue(actual)) {
///           return Extracted.rejection(which: ['cannot read someDerivedValue']);
///         }
///         return Extracted.value(_readDerivedValue(actual));
///       });
///
///   // for field reads that will not get rejected, use `has`
///   Subject<Bar> get someField => has((a) => a.someField, 'someField');
/// }
/// ```
///
/// When an expectation is rejected for a subject within a call to [softCheck]
/// or [softCheckAsync] a [CheckFailure] will be returned with the rejection, as
/// well as a [FailureDetail] which could be used to format the same failure
/// message thrown by the [check] subject.
///
/// {@template callbacks_may_be_unused}
/// The description of an expectation may never be shown to the user, so the
/// callback may never be invoked.
/// If all the conditions on a subject succeed, or if the failure detail for a
/// failed [softCheck] is never read, the descriptions will be unused.
/// String formatting for the descriptions should be performed in the callback,
/// not ahead of time.
///
///
/// The context for a subject may hold a real "actual" value to test against, or
/// it may have a placeholder within a call to [describe].
/// A context with a placeholder value will not invoke the callback to check
/// expectations.
///
/// If both callbacks are invoked, the description callback will always be
/// called strictly after the expectation callback is called.
///
/// Callbacks passed to a context should not throw.
/// {@endtemplate}
///
///
/// Some contexts disallow certain interactions.
/// {@template async_limitations}
/// Calls to [expectAsync] or [nestAsync] must not be performed by a condition
/// callback passed to [softCheck] or [describe].
/// Use [softCheckAsync] or [describeAsync] for any condition which checks async
/// expectations.
/// {@endtemplate}
/// {@template unawaited_limitations}
/// Calls to [expectUnawaited] may not be performed by a condition callback
/// passed to [softCheck] or [softCheckAsync].
/// {@endtemplate}
///
/// Expectation extension methods can access the context for the subject with
/// the [ContextExtension].
///
/// {@template description_lines}
/// Description callbacks return an `Iterable<String>` where each element is a
/// line in the output. Individual elements should not contain newlines.
/// Utilities such as [prefixFirst], [postfixLast], and [literal] may be useful
/// to format values which are potentially multiline.
/// {@endtemplate}
abstract final class Context<T> {
  /// Expect that [predicate] will not return a [Rejection] for the checked
  /// value.
  ///
  /// {@macro clause_description}
  ///
  /// {@macro description_lines}
  ///
  /// {@macro callbacks_may_be_unused}
  ///
  /// ```dart
  /// void someExpectation() {
  ///   context.expect(() => ['meets this expectation'], (actual) {
  ///     if (_expectationIsMet(actual)) return null;
  ///     return Rejection(which: ['does not meet this expectation']);
  ///   });
  /// }
  /// ```
  void expect(
      Iterable<String> Function() clause, Rejection? Function(T) predicate);

  /// Expect that [predicate] will not result in a [Rejection] for the checked
  /// value.
  ///
  /// {@macro clause_description}
  ///
  /// {@macro description_lines}
  ///
  /// {@macro callbacks_may_be_unused}
  ///
  /// {@macro async_limitations}
  ///
  /// ```dart
  /// extension CustomChecks on Subject<CustomType> {
  ///   Future<void> someAsyncExpectation() async {
  ///     await context.expectAsync(() => ['meets this async expectation'],
  ///         (actual) async {
  ///       if (await _expectationIsMet(actual)) return null;
  ///       return Rejection(which: ['does not meet this async expectation']);
  ///     });
  ///   }
  /// }
  /// ```
  Future<void> expectAsync<R>(Iterable<String> Function() clause,
      FutureOr<Rejection?> Function(T) predicate);

  /// Expect that [predicate] will not invoke the passed callback with a
  /// [Rejection] at any point.
  ///
  /// In contrast to [expectAsync], a rejection is reported through a
  /// callback instead of through a returned Future. The callback may be invoked
  /// at any point that the failure surfaces.
  ///
  /// This may be useful for a condition checking that some event _never_
  /// happens. If there is no specific point where it is know to be safe to stop
  /// listening for the event, there is no way to complete a returned future and
  /// consider the check "complete".
  ///
  /// {@macro clause_description}
  ///
  /// {@macro description_lines}
  ///
  /// {@macro callbacks_may_be_unused}
  ///
  /// {@macro unawaited_limitations}
  /// The only useful effect of a late rejection is to throw a [TestFailure]
  /// when used with a [check] subject. Most conditions should prefer to use
  /// [expect] or [expectAsync].
  ///
  /// ```dart
  /// void someUnawaitableExpectation() async {
  ///   await context.expectUnawaited(
  ///       () => ['meets this unawaitable expectation'], (actual, reject) {
  ///     final failureSignal = _completeIfFailed(actual);
  ///     unawaited(failureSignal.then((_) {
  ///       reject(Reject(
  ///           which: ['unexpectedly failed this unawaited expectation']));
  ///     }));
  ///   });
  /// }
  /// ```
  void expectUnawaited(Iterable<String> Function() clause,
      void Function(T, void Function(Rejection)) predicate);

  /// Extract a property from the value for further checking.
  ///
  /// If the property cannot be extracted, [extract] should return an
  /// [Extracted.rejection] describing the problem. Otherwise it should return
  /// an [Extracted.value].
  ///
  /// Subsequent expectations can be checked for the extracted value on the
  /// returned [Subject].
  ///
  /// {@macro label_description}
  ///
  /// If [atSameLevel] is true then the returned [Extracted.value] should hold
  /// the same instance as the passed value, or an object which is is equivalent
  /// but has a type that is more convenient to test.
  /// In this case expectations applied to the returned [Subject] will behave as
  /// if they were applied to the subject for this context.
  /// The [label] will be used as if it were a "clause" argument passed to
  /// [expect].
  /// If the label returns an empty iterable, the clause will be omitted.
  /// The label should only be left empty if the value extraction cannot be
  /// rejected.
  ///
  /// {@macro description_lines}
  ///
  /// {@macro callbacks_may_be_unused}
  ///
  /// ```dart
  /// Subject<Foo> get someDerivedValue =>
  ///     context.nest(() => ['has someDerivedValue'], (actual) {
  ///       if (_cannotReadDerivedValue(actual)) {
  ///         return Extracted.rejection(
  ///             which: ['cannot read someDerivedValue']);
  ///       }
  ///       return Extracted.value(_readDerivedValue(actual));
  ///     });
  /// ```
  Subject<R> nest<R>(
      Iterable<String> Function() label, Extracted<R> Function(T) extract,
      {bool atSameLevel = false});

  /// Extract an asynchronous property from the value for further checking.
  ///
  /// If the property cannot be extracted, [extract] should return an
  /// [Extracted.rejection] describing the problem. Otherwise it should return
  /// an [Extracted.value].
  ///
  /// In contrast to [nest], subsequent expectations need to be passed in
  /// [nestedCondition] which will be applied to the subject for the extracted
  /// value.
  ///
  /// {@macro label_description}
  ///
  /// {@macro description_lines}
  ///
  /// {@macro callbacks_may_be_unused}
  ///
  /// {@macro async_limitations}
  ///
  /// ```dart
  /// Future<void> someAsyncResult(
  ///     [AsyncCondition<Result> resultCondition]) async {
  ///   await context.nestAsync(() => ['has someAsyncResult'], (actual) async {
  ///     if (await _asyncOperationFailed(actual)) {
  ///       return Extracted.rejection(which: ['cannot read someAsyncResult']);
  ///     }
  ///     return Extracted.value(await _readAsyncResult(actual));
  ///   }, resultCondition);
  /// }
  /// ```
  Future<void> nestAsync<R>(
      Iterable<String> Function() label,
      FutureOr<Extracted<R>> Function(T) extract,
      AsyncCondition<R>? nestedCondition);
}

/// A property extracted from a value being checked, or a rejection.
final class Extracted<T> {
  final Rejection? _rejection;
  final T? _value;

  /// Creates a rejected extraction to indicate a failure trying to read the
  /// value.
  ///
  /// When a nesting is rejected with an omitted or empty [actual] argument, it
  /// will be filled in with the [literal] representation of the value.
  Extracted.rejection(
      {Iterable<String> actual = const [], Iterable<String>? which})
      : _rejection = Rejection(actual: actual, which: which),
        _value = null;
  Extracted.value(T this._value) : _rejection = null;

  Extracted._(Rejection this._rejection) : _value = null;

  Extracted<R> _map<R>(R Function(T) transform) {
    final rejection = _rejection;
    if (rejection != null) return Extracted._(rejection);
    return Extracted.value(transform(_value as T));
  }

  Extracted<T> _fillActual(Object? actual) => _rejection == null ||
          _rejection!.actual.isNotEmpty
      ? this
      : Extracted.rejection(actual: literal(actual), which: _rejection!.which);
}

abstract interface class _Optional<T> {
  R? apply<R extends FutureOr<Rejection?>>(R Function(T) callback);
  Future<Extracted<_Optional<R>>> mapAsync<R>(
      FutureOr<Extracted<R>> Function(T) transform);
  Extracted<_Optional<R>> map<R>(Extracted<R> Function(T) transform);
}

class _Present<T> implements _Optional<T> {
  final T value;
  _Present(this.value);

  @override
  R? apply<R extends FutureOr<Rejection?>>(R Function(T) c) => c(value);

  @override
  Future<Extracted<_Present<R>>> mapAsync<R>(
      FutureOr<Extracted<R>> Function(T) transform) async {
    final transformed = await transform(value);
    return transformed._map(_Present.new);
  }

  @override
  Extracted<_Present<R>> map<R>(Extracted<R> Function(T) transform) =>
      transform(value)._map(_Present.new);
}

class _Absent<T> implements _Optional<T> {
  @override
  R? apply<R extends FutureOr<Rejection?>>(R Function(T) c) => null;

  @override
  Future<Extracted<_Absent<R>>> mapAsync<R>(
          FutureOr<Extracted<R>> Function(T) transform) async =>
      Extracted.value(_Absent<R>());

  @override
  Extracted<_Absent<R>> map<R>(FutureOr<Extracted<R>> Function(T) transform) =>
      Extracted.value(_Absent<R>());
}

final class _TestContext<T> implements Context<T>, _ClauseDescription {
  final _Optional<T> _value;

  /// A reference to find the root context which this context is nested under.
  ///
  /// null only for the root context.
  final _TestContext<dynamic>? _parent;

  final List<_ClauseDescription> _clauses;
  final List<_TestContext> _aliases;

  final void Function(CheckFailure) _fail;

  final bool _allowAsync;
  final bool _allowUnawaited;

  /// A callback that returns a label for this context.
  ///
  /// If this context is the root the label should return a phrase like
  /// "a List" in
  ///
  /// ```
  /// Expected: a List that:
  /// ```
  ///
  /// If this context is nested under another context the lable should return a
  /// phrase like "completes to a value" in
  ///
  ///
  /// ```
  /// Expected: a Future<int> that:
  ///   completes to a value that:
  /// ```
  ///
  /// In cases where a nested context does not have any expectations checked on
  /// it, the "that:" will be will be omitted.
  final Iterable<String> Function() _label;

  static Iterable<String> _emptyLabel() => const [];

  /// Create a context appropriate for a subject which is not nested under any
  /// other subject.
  _TestContext._root({
    required _Optional<T> value,
    required void Function(CheckFailure) fail,
    required bool allowAsync,
    required bool allowUnawaited,
    String? label,
  })  : _value = value,
        _label = (() => [label ?? '']),
        _fail = fail,
        _allowAsync = allowAsync,
        _allowUnawaited = allowUnawaited,
        _parent = null,
        _clauses = [],
        _aliases = [];

  _TestContext._alias(_TestContext original, this._value)
      : _parent = original,
        _clauses = original._clauses,
        _aliases = original._aliases,
        _fail = original._fail,
        _allowAsync = original._allowAsync,
        _allowUnawaited = original._allowUnawaited,
        // Never read from an aliased context because they are never present in
        // `_clauses`.
        _label = _emptyLabel;

  /// Create a context nested under [parent].
  ///
  /// The [_label] callback should not return an empty iterable.
  _TestContext._child(this._value, this._label, _TestContext<dynamic> parent)
      : _parent = parent,
        _fail = parent._fail,
        _allowAsync = parent._allowAsync,
        _allowUnawaited = parent._allowUnawaited,
        _clauses = [],
        _aliases = [];

  @override
  void expect(
      Iterable<String> Function() clause, Rejection? Function(T) predicate) {
    _clauses.add(_ExpectationClause(clause));
    final rejection =
        _value.apply((actual) => predicate(actual)?._fillActual(actual));
    if (rejection != null) {
      _fail(_failure(rejection));
    }
  }

  @override
  Future<void> expectAsync<R>(Iterable<String> Function() clause,
      FutureOr<Rejection?> Function(T) predicate) async {
    if (!_allowAsync) {
      throw StateError(
          'Async expectations cannot be used on a synchronous subject');
    }
    _clauses.add(_ExpectationClause(clause));
    final outstandingWork = TestHandle.current.markPending();
    try {
      final rejection = await _value.apply(
          (actual) async => (await predicate(actual))?._fillActual(actual));
      if (rejection == null) return;
      _fail(_failure(rejection));
    } finally {
      outstandingWork.complete();
    }
  }

  @override
  void expectUnawaited(Iterable<String> Function() clause,
      void Function(T actual, void Function(Rejection) reject) predicate) {
    if (!_allowUnawaited) {
      throw StateError('Late expectations cannot be used for soft checks');
    }
    _clauses.add(_ExpectationClause(clause));
    _value.apply((actual) {
      predicate(actual, (r) => _fail(_failure(r._fillActual(actual))));
    });
  }

  @override
  Subject<R> nest<R>(
      Iterable<String> Function() label, Extracted<R> Function(T) extract,
      {bool atSameLevel = false}) {
    final result = _value.map((actual) => extract(actual)._fillActual(actual));
    final rejection = result._rejection;
    if (rejection != null) {
      _clauses.add(_ExpectationClause(label));
      _fail(_failure(rejection));
    }
    final value = result._value ?? _Absent<R>();
    final _TestContext<R> context;
    if (atSameLevel) {
      context = _TestContext._alias(this, value);
      _aliases.add(context);
      _clauses.add(_ExpectationClause(label));
    } else {
      context = _TestContext._child(value, label, this);
      _clauses.add(context);
    }
    return Subject._(context);
  }

  @override
  Future<void> nestAsync<R>(
      Iterable<String> Function() label,
      FutureOr<Extracted<R>> Function(T) extract,
      AsyncCondition<R>? nestedCondition) async {
    if (!_allowAsync) {
      throw StateError(
          'Async expectations cannot be used on a synchronous subject');
    }
    final outstandingWork = TestHandle.current.markPending();
    try {
      final result = await _value.mapAsync(
          (actual) async => (await extract(actual))._fillActual(actual));
      final rejection = result._rejection;
      if (rejection != null) {
        _clauses.add(_ExpectationClause(label));
        _fail(_failure(rejection));
      }
      final value = result._value ?? _Absent<R>();
      final context = _TestContext<R>._child(value, label, this);
      _clauses.add(context);
      await nestedCondition?.call(Subject<R>._(context));
    } finally {
      outstandingWork.complete();
    }
  }

  CheckFailure _failure(Rejection rejection) =>
      CheckFailure(rejection, () => _root.detail(this));

  _TestContext get _root {
    _TestContext<dynamic> current = this;
    while (current._parent != null) {
      current = current._parent!;
    }
    return current;
  }

  @override
  FailureDetail detail(_TestContext failingContext) {
    final thisContextFailed =
        identical(failingContext, this) || _aliases.contains(failingContext);
    var foundDepth = thisContextFailed ? 0 : -1;
    var foundOverlap = thisContextFailed ? 0 : -1;
    var successfulOverlap = 0;
    final expected = <String>[];
    if (_clauses.isEmpty) {
      expected.addAll(_label());
    } else {
      expected.addAll(postfixLast(' that:', _label()));
      for (var clause in _clauses) {
        final details = clause.detail(failingContext);
        expected.addAll(indent(details.expected));
        if (details.depth >= 0) {
          assert(foundDepth == -1);
          assert(foundOverlap == -1);
          foundDepth = details.depth + 1;
          foundOverlap = details._actualOverlap + successfulOverlap + 1;
        } else {
          if (foundDepth == -1) {
            successfulOverlap += details.expected.length;
          }
        }
      }
    }
    return FailureDetail(expected, foundOverlap, foundDepth);
  }
}

/// A context which never runs expectations and can never fail.
final class _SkippedContext<T> implements Context<T> {
  @override
  void expect(
      Iterable<String> Function() clause, Rejection? Function(T) predicate) {
    // no-op
  }

  @override
  Future<void> expectAsync<R>(Iterable<String> Function() clause,
      FutureOr<Rejection?> Function(T) predicate) async {
    // no-op
  }

  @override
  void expectUnawaited(Iterable<String> Function() clause,
      void Function(T actual, void Function(Rejection) reject) predicate) {
    // no-op
  }

  @override
  Subject<R> nest<R>(
      Iterable<String> Function() label, Extracted<R> Function(T p1) extract,
      {bool atSameLevel = false}) {
    return Subject._(_SkippedContext());
  }

  @override
  Future<void> nestAsync<R>(
      Iterable<String> Function() label,
      FutureOr<Extracted<R>> Function(T p1) extract,
      AsyncCondition<R>? nestedCondition) async {
    // no-op
  }
}

abstract interface class _ClauseDescription {
  FailureDetail detail(_TestContext failingContext);
}

class _ExpectationClause implements _ClauseDescription {
  final Iterable<String> Function() _expected;
  _ExpectationClause(this._expected);
  @override
  FailureDetail detail(_TestContext failingContext) =>
      FailureDetail(_expected(), -1, -1);
}

/// The result an expectation that failed for a subject..
final class CheckFailure {
  /// The specific rejected value within the overall subject that caused the
  /// failure.
  ///
  /// The [Rejection.actual] may be a property derived from the value at the
  /// root of the subject, for instance a field or an element in a collection.
  final Rejection rejection;

  /// The context within the overall subject where an expectation resulted in
  /// the [rejection].
  late final FailureDetail detail = _readDetail();

  final FailureDetail Function() _readDetail;

  CheckFailure(this.rejection, this._readDetail);
}

/// The context for a failed expectation.
///
/// A subject may have some number of succeeding expectations, and the failure may
/// be for an expectation against a property derived from the value at the root
/// of the subject. For example, in `check([]).length.equals(1)` the
/// specific value that gets rejected is `0` from the length of the list, and
/// the subject that sees the rejection is nested with the label "has length".
final class FailureDetail {
  /// A description of all the conditions the subject was expected to satisfy.
  ///
  /// Each subject has a label. At the root the label is typically "a <Type>"
  /// and nested subjects get a label based on the condition which extracted a
  /// property for further checks. Each level of nesting is described as
  /// "<label> that:" followed by an indented list of the expectations for that
  /// property.
  ///
  /// For example:
  ///
  ///   a List that:
  ///     has length that:
  ///       equals <3>
  final Iterable<String> expected;

  /// A description of the conditions the checked value satisfied.
  ///
  /// Matches the format of [expected], except it will be cut off after the
  /// label for the subject that had a failing expectation. For example, if the
  /// equality check for the length of a list fails:
  ///
  ///   a List that:
  ///     has length that:
  ///
  /// If the subject with a failing expectation is the root, returns an empty
  /// list. Instead the "Actual: " value from the rejection can be used without
  /// indentation.
  Iterable<String> get actual =>
      _actualOverlap > 0 ? expected.take(_actualOverlap + 1) : const [];

  /// The number of lines from [expected] which describe conditions that were
  /// successful.
  ///
  /// A failed expectation on a derived property may have some number of
  /// expectations that were checked and satisfied starting from the root
  /// subject. This field indicates how many lines of expectations were
  /// successful.
  final int _actualOverlap;

  /// The number of times the failing subject was nested from the root subject.
  ///
  /// Indicates how far the "Actual: " and "Which: " lines from the [Rejection]
  /// should be indented so that they are at the same level of indentation as
  /// the label for the subject where the expectation failed.
  ///
  /// For example, if a `List` is expected to and have a certain length
  /// [expected] may be:
  ///
  ///   a List that:
  ///     has length that:
  ///       equals <3>
  ///
  /// If the actual value had an incorrect length, the [depth] will be `1` to
  /// indicate that the failure occurred checking one of the expectations
  /// against the `has length` label.
  final int depth;

  FailureDetail(this.expected, this._actualOverlap, this.depth);
}

/// A description of a value that failed an expectation.
final class Rejection {
  /// A description of the actual value as it relates to the expectation.
  ///
  /// This may use [literal] to show a String representation of the value, or it
  /// may be a description of a specific aspect of the value. For instance an
  /// expectation that a Future completes to a value may describe the actual as
  /// "A Future that completes to an error".
  ///
  /// When a value is rejected with no [actual] argument, it will be filled in
  /// with the [literal] representation of the value.
  ///
  /// Lines should be split to separate elements, and individual strings should
  /// not contain newlines.
  ///
  /// This is printed following an "Actual: " label in the output of a failure
  /// message. All lines in the message will be indented to the level of the
  /// expectation in the description, and printed following the descriptions of
  /// any expectations that have already passed.
  final Iterable<String> actual;

  /// A description of the way that [actual] failed to meet the expectation.
  ///
  /// An expectation can provide extra detail, or focus attention on a specific
  /// part of the value. For instance when comparing multiple elements in a
  /// collection, the rejection may describe that the value "has an unequal
  /// value at index 3".
  ///
  /// Lines should be separate values in the iterable, if any element contains a
  /// newline it may cause problems with indentation in the output.
  ///
  /// When provided, this is printed following a "Which: " label at the end of
  /// the output for the failure message.
  final Iterable<String>? which;

  Rejection _fillActual(Object? value) => actual.isNotEmpty
      ? this
      : Rejection(actual: literal(value), which: which);

  Rejection({this.actual = const [], this.which});
}
