@use 'sass:list';
@use 'sass:map';
@use 'utilities';

// Get Result
// ----------
/// Compare two values, and return a `pass` or `fail` result.
/// @access private
/// @group private-context
/// @param {*} $assert - Value to consider
/// @param {*} $expected - Expected match
/// @param {bool} $unequal [false] -
///   Set to `true` if the comparison is expected to fail
/// @return {'pass' | 'fail'} The result of a test
@function get-result($assert, $expected, $unequal: false) {
  $is-equal: $assert == $expected;
  $assert-equal: not $unequal;

  @if ($assert-equal != $is-equal) {
    @return 'fail';
  }

  @return 'pass';
}

// Results
// -------
/// Global test-results map
/// @access private
/// @group private-context
/// @type Map
$results: (
  'run': 0,
  'pass': 0,
  'fail': 0,
  'output-to-css': 0,
);

// Update
// ------
/// Update global results data
/// @access private
/// @group private-context
/// @param {'pass' | 'fail' | 'output-to-css'} $result -
@mixin update($result) {
  $update: (
    'run': 1,
    $result: 1,
  );
  $results: utilities.map-increment($results, $update) !global;
  $test-result: null !global;
}

// Test Results
// ------------
// Local flags for tracking assertion results in a test
/// @access private
/// @group private-context
/// @type String
$test-result: null;

// Update Test
// -----------
/// Update test result flag with new data
/// @access private
/// @group private-context
/// @param {'pass' | 'fail' | 'output-to-css'} $result -
@mixin update-test($result) {
  @if ($result == 'fail') or ($test-result == 'fail') {
    $test-result: 'fail' !global;
  } @else if ($test-result != 'output-to-css') {
    $test-result: $result !global;
  }
}

// Results Message
// ---------------
/// Report message
/// @access private
/// @group private-message
/// @param {Bool} $linebreak [false] -
///   Return message either as a single line or in multiple lines
/// @param {Map} $results [$results] -
///   A map of run, pass, fail, and output-to-css results
/// @return {String} -
///   Single or multi-line message for reporting
@function results-message($linebreak: false, $results: $results) {
  $run: map.get($results, 'run');
  $items-label: 'Tests';

  @if ($run == 1) {
    $items-label: 'Test';
  }

  $pass: map.get($results, 'pass');
  $fail: map.get($results, 'fail');
  $output-to-css: map.get($results, 'output-to-css');
  $items: '#{$run} #{$items-label}';
  $passed: '#{$pass} Passed';
  $failed: '#{$fail} Failed';
  $compiled: null;

  @if ($output-to-css > 0) {
    $compiled: '#{$output-to-css} Output to CSS';
  }

  // Linebreaks
  @if $linebreak {
    $message: ('#{$items}:', '- #{$passed}', '- #{$failed}');

    @if $compiled {
      $message: list.append($message, '- #{$compiled}');
    }

    @return $message;
  }

  // No Linebreaks
  $message: '#{$items}, #{$passed}, #{$failed}';

  @if $compiled {
    $message: '#{$message}, #{$compiled}';
  }

  @return $message;
}
