// 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], [expectAsync], 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(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(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(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
  /// &lt;Type&gt;" and nested subjects get a label based on the condition
  /// which extracted a property for further checks. Each level of nesting is
  /// described as "&lt;label&gt; that:" followed by an indented list of the
  /// expectations for that property.
  ///
  /// For example:
  ///
  ///   a List that:
  ///     has length that:
  ///       equals &lt;3&gt;
  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 &lt;3&gt;
  ///
  /// 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});
}
