// Copyright (c) 2018, 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 'dart:io';

import 'package:path/path.dart' as p;
import 'package:pub/src/ascii_tree.dart' as ascii_tree;
import 'package:pub/src/io.dart';
import 'package:stack_trace/stack_trace.dart' show Trace;
import 'package:test/test.dart';

import 'ascii_tree_test.dart';
import 'descriptor.dart' as d;
import 'test_pub.dart';

final _isCI = () {
  final p = RegExp(r'^1|(?:true)$', caseSensitive: false);
  final ci = Platform.environment['CI'];
  return ci != null && ci.isNotEmpty && p.hasMatch(ci);
}();

/// Find the current `_test.dart` filename invoked from stack-trace.
String _findCurrentTestFilename() => Trace.current()
    .frames
    .lastWhere(
      (frame) =>
          frame.uri.isScheme('file') &&
          p.basename(frame.uri.toFilePath()).endsWith('_test.dart'),
    )
    .uri
    .toFilePath();

class GoldenTestContext {
  static const _endOfSection = ''
      '--------------------------------'
      ' END OF OUTPUT '
      '---------------------------------\n\n';

  late final String _currentTestFile;
  late final String _testName;

  late String _goldenFilePath;
  late File _goldenFile;
  late String _header;
  final _results = <String>[];
  late bool _shouldRegenerateGolden;
  final bool colors;
  bool _generatedNewData = false; // track if new data is generated
  int _nextSectionIndex = 0;

  GoldenTestContext._(
    this._currentTestFile,
    this._testName, {
    required this.colors,
  }) {
    final rel = p.relative(
      _currentTestFile.replaceAll(RegExp(r'\.dart$'), ''),
      from: p.join(p.current, 'test'),
    );
    _goldenFilePath = p.join(
      'test',
      'testdata',
      'goldens',
      rel,
      // Sanitize the name, and add .ans or .txt.
      '${_testName.replaceAll(RegExp(r'[<>:"/\|?*%#]'), '~')}.${colors ? 'ans' : 'txt'}',
    );
    _goldenFile = File(_goldenFilePath);
    _header = '# GENERATED BY: ${p.relative(_currentTestFile)}\n\n';
  }

  void _readGoldenFile() {
    if (RegExp(r'^1|(?:true)$', caseSensitive: false)
            .hasMatch(Platform.environment['_PUB_TEST_WRITE_GOLDEN'] ?? '') ||
        !_goldenFile.existsSync()) {
      _shouldRegenerateGolden = true;
    } else {
      _shouldRegenerateGolden = false;
      // Read the golden file for this test
      var text = _goldenFile.readAsStringSync().replaceAll('\r\n', '\n');
      // Strip header line
      if (text.startsWith('#') && text.contains('\n\n')) {
        text = text.substring(text.indexOf('\n\n') + 2);
      }
      _results.addAll(text.split(_endOfSection));
    }
  }

  /// Expect section [sectionIndex] to match [actual].
  void _expectSection(int sectionIndex, String actual) {
    if (!_shouldRegenerateGolden &&
        _results.length > sectionIndex &&
        _results[sectionIndex].isNotEmpty) {
      expect(
        actual,
        equals(_results[sectionIndex]),
        reason: 'Expect matching section $sectionIndex from "$_goldenFilePath"',
      );
    } else {
      while (_results.length <= sectionIndex) {
        _results.add('');
      }
      _results[sectionIndex] = actual;
      _generatedNewData = true;
    }
  }

  void _writeGoldenFile() {
    // If we generated new data, then we need to write a new file, and fail the
    // test case, or mark it as skipped.
    if (_generatedNewData) {
      // This enables writing the updated file when run in otherwise hermetic
      // settings.
      //
      // This is to make updating the golden files easier in a bazel environment
      // See https://docs.bazel.build/versions/2.0.0/user-manual.html#run .
      var goldenFile = _goldenFile;
      final workspaceDirectory =
          Platform.environment['BUILD_WORKSPACE_DIRECTORY'];
      if (workspaceDirectory != null) {
        goldenFile = File(p.join(workspaceDirectory, _goldenFilePath));
      }
      goldenFile
        ..createSync(recursive: true)
        ..writeAsStringSync(_header + _results.join(_endOfSection));

      // If running in CI we should fail if the golden file doesn't already
      // exist, or is missing entries.
      // This typically happens if we forgot to commit a file to git.
      if (_isCI) {
        fail('Missing golden file: "$_goldenFilePath", '
            'try running tests again and commit the file');
      } else {
        // If not running in CI, then we consider the test as skipped, we've
        // generated the file, but the user should run the tests again.
        // Or push to CI in which case we'll run the tests again anyways.
        markTestSkipped(
          'Generated golden file: "$_goldenFilePath" instead of running test',
        );
      }
    }
  }

  /// Expect the next section in the golden file to match [actual].
  ///
  /// This will create the section if it is missing.
  ///
  /// **Warning**: Take care when using this in an async context, sections are
  /// numbered based on the other in which calls are made. Hence, ensure
  /// consistent ordering of calls.
  void expectNextSection(String actual) =>
      _expectSection(_nextSectionIndex++, actual);

  /// Run `pub` [args] with [environment] variables in [workingDirectory], and
  /// log stdout/stderr and exit code to golden file.
  Future<void> run(
    List<String> args, {
    Map<String, String?>? environment,
    String? workingDirectory,
    String? stdin,
  }) async {
    // Create new section index number (before doing anything async)
    final sectionIndex = _nextSectionIndex++;
    final s = StringBuffer();
    s.writeln('## Section $sectionIndex');
    await runPubIntoBuffer(
      args,
      s,
      environment: environment,
      workingDirectory: workingDirectory,
      stdin: stdin,
    );

    _expectSection(sectionIndex, s.toString());
  }

  /// Log directory tree structure under [directory] to golden file.
  Future<void> tree([String? directory]) async {
    // Create new section index number (before doing anything async)
    final sectionIndex = _nextSectionIndex++;

    final target = p.join(d.sandbox, directory ?? '.');

    final s = StringBuffer();
    s.writeln('## Section $sectionIndex');
    if (directory != null) {
      s.writeln('\$ cd $directory');
    }
    s.writeln('\$ tree');
    final tree = ascii_tree.fromFiles(
      listDir(target, recursive: true),
      baseDir: target,
      showFileSizes: false,
    );
    s.writeln(colors ? tree : stripColors(tree));

    _expectSection(sectionIndex, s.toString());
  }
}

/// Create a [test] with [GoldenTestContext] which allows running golden tests.
///
/// This will create a golden file containing output of calls to:
///  * [GoldenTestContext.run]
///  * [GoldenTestContext.tree]
///
/// The golden file with the recorded output will be created at:
///   `test/testdata/goldens/path/to/myfile_test/<name>.txt`
/// , when `path/to/myfile_test.dart` is the `_test.dart` file from which this
/// function is called.
///
/// If [colors] is `true` the file will be created with an `.ans` extension that
/// indicates ANSI colors will be used.
///
/// Such a file can eg. be viewed in vscode with this plugin:
/// https://marketplace.visualstudio.com/items?itemName=iliazeus.vscode-ansi
void testWithGolden(
  String name,
  FutureOr<void> Function(GoldenTestContext ctx) fn, {
  bool colors = false,
}) {
  final ctx = GoldenTestContext._(
    _findCurrentTestFilename(),
    name,
    colors: colors,
  );
  test(name, () async {
    ctx._readGoldenFile();
    await fn(ctx);
    ctx._writeGoldenFile();
  });
}
