// Copyright 2013 The Flutter Authors
// 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:convert';
import 'dart:io' as io;

import 'package:args/command_runner.dart';
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_plugin_tools/src/common/core.dart';
import 'package:flutter_plugin_tools/src/common/file_utils.dart';
import 'package:flutter_plugin_tools/src/common/plugin_utils.dart';
import 'package:flutter_plugin_tools/src/common/process_runner.dart';
import 'package:flutter_plugin_tools/src/common/repository_package.dart';
import 'package:flutter_plugin_tools/src/common/tool_config.dart';
import 'package:git/git.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;
import 'package:platform/platform.dart';
import 'package:quiver/collection.dart';
import 'package:yaml/yaml.dart';
import 'package:yaml_edit/yaml_edit.dart';

import 'mocks.dart';

export 'package:flutter_plugin_tools/src/common/repository_package.dart';

const String _defaultDartConstraint = '>=2.14.0 <4.0.0';
const String _defaultFlutterConstraint = '>=2.5.0';

/// Returns the exe name that command will use when running Flutter on
/// [platform].
String getFlutterCommand(NativePlatform platform) => platform.isWindows ? 'flutter.bat' : 'flutter';

/// Creates a packages directory at an arbitrary location in the given
/// filesystem.
Directory createPackagesDirectory(FileSystem fileSystem) {
  final Directory packagesDir = fileSystem.currentDirectory.childDirectory('packages');
  packagesDir.createSync();
  return packagesDir;
}

/// Details for platform support in a plugin.
@immutable
class PlatformDetails {
  const PlatformDetails(this.type, {this.hasNativeCode = true, this.hasDartCode = false});

  /// The type of support for the platform.
  final PlatformSupport type;

  /// Whether or not the plugin includes native code.
  ///
  /// Ignored for web, which does not have native code.
  final bool hasNativeCode;

  /// Whether or not the plugin includes Dart code.
  ///
  /// Ignored for web, which always has native code.
  final bool hasDartCode;
}

/// Returns the 'example' directory for [package].
///
/// This is deliberately not a method on [RepositoryPackage] since actual tool
/// code should essentially never need this, and instead be using
/// [RepositoryPackage.getExamples] to avoid assuming there's a single example
/// directory. However, needing to construct paths with the example directory
/// is very common in test code.
///
/// This returns a Directory rather than a RepositoryPackage because there is no
/// guarantee that the returned directory is a package.
Directory getExampleDir(RepositoryPackage package) {
  return package.directory.childDirectory('example');
}

/// Creates a plugin package with the given [name] in [packagesDirectory].
///
/// [platformSupport] is a map of platform string to the support details for
/// that platform.
///
/// [extraFiles] is an optional list of plugin-relative paths, using Posix
/// separators, of extra files to create in the plugin.
RepositoryPackage createFakePlugin(
  String name,
  Directory parentDirectory, {
  List<String> examples = const <String>['example'],
  List<String> extraFiles = const <String>[],
  Map<String, PlatformDetails> platformSupport = const <String, PlatformDetails>{},
  String? version = '0.0.1',
  String flutterConstraint = _defaultFlutterConstraint,
  String dartConstraint = _defaultDartConstraint,
}) {
  final RepositoryPackage package = createFakePackage(
    name,
    parentDirectory,
    isFlutter: true,
    examples: examples,
    extraFiles: extraFiles,
    version: version,
    flutterConstraint: flutterConstraint,
    dartConstraint: dartConstraint,
  );

  createFakePubspec(
    package,
    name: name,
    isPlugin: true,
    platformSupport: platformSupport,
    version: version,
    flutterConstraint: flutterConstraint,
    dartConstraint: dartConstraint,
  );

  return package;
}

/// Creates a plugin package with the given [name] in [packagesDirectory].
///
/// [extraFiles] is an optional list of package-relative paths, using unix-style
/// separators, of extra files to create in the package.
///
/// If [includeCommonFiles] is true, common but non-critical files like
/// CHANGELOG.md, README.md, and AUTHORS will be included.
///
/// If non-null, [directoryName] will be used for the directory instead of
/// [name].
RepositoryPackage createFakePackage(
  String name,
  Directory parentDirectory, {
  List<String> examples = const <String>['example'],
  List<String> extraFiles = const <String>[],
  bool isFlutter = false,
  String? version = '0.0.1',
  String flutterConstraint = _defaultFlutterConstraint,
  String dartConstraint = _defaultDartConstraint,
  bool includeCommonFiles = true,
  String? directoryName,
  String? publishTo,
}) {
  final package = RepositoryPackage(parentDirectory.childDirectory(directoryName ?? name));
  package.directory.createSync(recursive: true);

  package.libDirectory.createSync();
  createFakePubspec(
    package,
    name: name,
    isFlutter: isFlutter,
    version: version,
    flutterConstraint: flutterConstraint,
    dartConstraint: dartConstraint,
    publishTo: publishTo,
  );
  if (includeCommonFiles) {
    package.changelogFile.writeAsStringSync('''
## $version
  * Some changes.
  ''');
    package.readmeFile.writeAsStringSync('A very useful package');
    package.authorsFile.writeAsStringSync('Google Inc.');
  }

  if (examples.length == 1) {
    createFakePackage(
      '${name}_example',
      package.directory,
      directoryName: examples.first,
      examples: <String>[],
      includeCommonFiles: false,
      isFlutter: isFlutter,
      publishTo: 'none',
      flutterConstraint: flutterConstraint,
      dartConstraint: dartConstraint,
    );
  } else if (examples.isNotEmpty) {
    final Directory examplesDirectory = getExampleDir(package)..createSync();
    for (final exampleName in examples) {
      createFakePackage(
        exampleName,
        examplesDirectory,
        examples: <String>[],
        includeCommonFiles: false,
        isFlutter: isFlutter,
        publishTo: 'none',
        flutterConstraint: flutterConstraint,
        dartConstraint: dartConstraint,
      );
    }
  }

  final p.Context posixContext = p.posix;
  for (final file in extraFiles) {
    childFileWithSubcomponents(
      package.directory,
      posixContext.split(file),
    ).createSync(recursive: true);
  }

  return package;
}

/// Creates a `pubspec.yaml` file for [package].
///
/// [platformSupport] is a map of platform string to the support details for
/// that platform. If empty, no `plugin` entry will be created unless `isPlugin`
/// is set to `true`.
void createFakePubspec(
  RepositoryPackage package, {
  String name = 'fake_package',
  bool isFlutter = true,
  bool isPlugin = false,
  Map<String, PlatformDetails> platformSupport = const <String, PlatformDetails>{},
  String? publishTo,
  String? version,
  String dartConstraint = _defaultDartConstraint,
  String flutterConstraint = _defaultFlutterConstraint,
}) {
  isPlugin |= platformSupport.isNotEmpty;

  var environmentSection =
      '''
environment:
  sdk: "$dartConstraint"
''';
  var dependenciesSection = '''
dependencies:
''';
  var pluginSection = '';

  // Add Flutter-specific entries if requested.
  if (isFlutter) {
    environmentSection +=
        '''
  flutter: "$flutterConstraint"
''';
    dependenciesSection += '''
  flutter:
    sdk: flutter
''';

    if (isPlugin) {
      pluginSection += '''
flutter:
  plugin:
    platforms:
''';
      for (final MapEntry<String, PlatformDetails> platform in platformSupport.entries) {
        pluginSection += _pluginPlatformSection(platform.key, platform.value, name);
      }
    }
  }

  // Default to a fake server to avoid ever accidentally publishing something
  // from a test. Does not use 'none' since that changes the behavior of some
  // commands.
  final publishToSection = 'publish_to: ${publishTo ?? 'http://no_pub_server.com'}';

  final yaml =
      '''
name: $name
${(version != null) ? 'version: $version' : ''}
$publishToSection

$environmentSection

$dependenciesSection

$pluginSection
''';

  package.pubspecFile.createSync();
  package.pubspecFile.writeAsStringSync('${yaml.trim()}\n');
}

/// Creates a `ci_config.yaml` file for [package].
void createFakeCiConfig({required RepositoryPackage package, required bool batchRelease}) {
  final yaml =
      '''
release:
  batch: $batchRelease
''';

  package.ciConfigFile.createSync();
  package.ciConfigFile.writeAsStringSync(yaml);
}

String _pluginPlatformSection(String platform, PlatformDetails support, String packageName) {
  var entry = '';
  // Build the main plugin entry.
  if (support.type == PlatformSupport.federated) {
    entry =
        '''
      $platform:
        default_package: ${packageName}_$platform
''';
  } else {
    final lines = <String>['      $platform:'];
    switch (platform) {
      case platformAndroid:
        lines.add('        package: io.flutter.plugins.fake');
        continue nativeByDefault;
      nativeByDefault:
      case platformIOS:
      case platformLinux:
      case platformMacOS:
      case platformWindows:
        if (support.hasNativeCode) {
          final className = platform == platformIOS ? 'FLTFakePlugin' : 'FakePlugin';
          lines.add('        pluginClass: $className');
        }
        if (support.hasDartCode) {
          lines.add('        dartPluginClass: FakeDartPlugin');
        }
      case platformWeb:
        lines.addAll(<String>[
          '        pluginClass: FakePlugin',
          '        fileName: ${packageName}_web.dart',
        ]);
      default:
        assert(false, 'Unrecognized platform: $platform');
    }
    entry = '${lines.join('\n')}\n';
  }

  return entry;
}

/// Run the command [runner] with the given [args] and return
/// what was printed.
/// A custom [errorHandler] can be used to handle the runner error as desired without throwing.
Future<List<String>> runCapturingPrint(
  CommandRunner<void> runner,
  List<String> args, {
  void Function(Error error)? errorHandler,
  void Function(Exception error)? exceptionHandler,
}) async {
  final prints = <String>[];
  final spec = ZoneSpecification(
    print: (_, _, _, String message) {
      prints.add(message);
    },
  );
  try {
    await Zone.current.fork(specification: spec).run<Future<void>>(() => runner.run(args));
  } on Error catch (e) {
    if (errorHandler == null) {
      rethrow;
    }
    errorHandler(e);
  } on Exception catch (e) {
    if (exceptionHandler == null) {
      rethrow;
    }
    exceptionHandler(e);
  }

  return prints;
}

/// Information about a process to return from [RecordingProcessRunner].
class FakeProcessInfo {
  const FakeProcessInfo(
    this.process, [
    this.expectedInitialArgs = const <String>[],
    this.runCallback,
  ]);

  /// The process to return.
  final io.Process process;

  /// The expected start of the argument array for the call.
  ///
  /// This does not have to be a full list of arguments, only enough of the
  /// start to ensure that the call is as expected.
  final List<String> expectedInitialArgs;

  /// If present, a function to call when the process would be run.
  ///
  /// This can be used to validate state at specific points in a command run,
  /// such as temporary file modifications.
  final void Function()? runCallback;
}

/// A mock [ProcessRunner] which records process calls.
class RecordingProcessRunner extends ProcessRunner {
  final List<ProcessCall> recordedCalls = <ProcessCall>[];

  /// Maps an executable to a list of processes that should be used for each
  /// successive call to it via [run], [runAndStream], or [start].
  ///
  /// If `expectedInitialArgs` are provided for a fake process, trying to
  /// return that process when the arguments don't match will throw a
  /// [StateError]. This allows tests to enforce that the fake results are
  /// for the expected calls when the process name itself isn't enough to tell
  /// (e.g., multiple different `dart` or `flutter` calls), without going all
  /// the way to a complex argument matching scheme that can make tests
  /// difficult to write and debug.
  final Map<String, List<FakeProcessInfo>> mockProcessesForExecutable =
      <String, List<FakeProcessInfo>>{};

  @override
  Future<int> runAndStream(
    String executable,
    List<String> args, {
    Directory? workingDir,
    Map<String, String>? environment,
    bool exitOnError = false,
  }) async {
    recordedCalls.add(ProcessCall(executable, args, workingDir?.path));
    final io.Process? processToReturn = _runFakeProcess(executable, args);
    final int exitCode = processToReturn == null ? 0 : await processToReturn.exitCode;
    if (exitOnError && (exitCode != 0)) {
      throw io.ProcessException(executable, args);
    }
    return Future<int>.value(exitCode);
  }

  /// Returns [io.ProcessResult] created from [mockProcessesForExecutable].
  @override
  Future<io.ProcessResult> run(
    String executable,
    List<String> args, {
    Directory? workingDir,
    Map<String, String>? environment,
    bool exitOnError = false,
    bool logOnError = false,
    Encoding stdoutEncoding = io.systemEncoding,
    Encoding stderrEncoding = io.systemEncoding,
  }) async {
    recordedCalls.add(ProcessCall(executable, args, workingDir?.path));

    final io.Process? process = _runFakeProcess(executable, args);
    final List<String>? processStdout = await process?.stdout
        .transform(stdoutEncoding.decoder)
        .toList();
    final String stdout = processStdout?.join() ?? '';
    final List<String>? processStderr = await process?.stderr
        .transform(stderrEncoding.decoder)
        .toList();
    final String stderr = processStderr?.join() ?? '';

    final result = process == null
        ? io.ProcessResult(1, 0, '', '')
        : io.ProcessResult(process.pid, await process.exitCode, stdout, stderr);

    if (exitOnError && (result.exitCode != 0)) {
      throw io.ProcessException(executable, args);
    }

    return Future<io.ProcessResult>.value(result);
  }

  @override
  Future<io.Process> start(
    String executable,
    List<String> args, {
    Directory? workingDirectory,
  }) async {
    recordedCalls.add(ProcessCall(executable, args, workingDirectory?.path));
    return Future<io.Process>.value(_runFakeProcess(executable, args) ?? MockProcess());
  }

  /// Returns the fake process for the given executable and args after running
  /// any callback it provides.
  io.Process? _runFakeProcess(String executable, List<String> args) {
    final List<FakeProcessInfo> fakes =
        mockProcessesForExecutable[executable] ?? <FakeProcessInfo>[];
    if (fakes.isNotEmpty) {
      final FakeProcessInfo fake = fakes.removeAt(0);
      if (args.length < fake.expectedInitialArgs.length ||
          !listsEqual(args.sublist(0, fake.expectedInitialArgs.length), fake.expectedInitialArgs)) {
        throw StateError(
          'Next fake process for $executable expects arguments '
          '[${fake.expectedInitialArgs.join(', ')}] but was called with '
          'arguments [${args.join(', ')}]',
        );
      }
      fake.runCallback?.call();
      return fake.process;
    }
    return null;
  }
}

/// A recorded process call.
@immutable
class ProcessCall {
  const ProcessCall(this.executable, this.args, this.workingDir);

  /// The executable that was called.
  final String executable;

  /// The arguments passed to [executable] in the call.
  final List<String> args;

  /// The working directory this process was called from.
  final String? workingDir;

  @override
  bool operator ==(Object other) {
    return other is ProcessCall &&
        executable == other.executable &&
        listsEqual(args, other.args) &&
        workingDir == other.workingDir;
  }

  @override
  int get hashCode => Object.hash(executable, args, workingDir);

  @override
  String toString() {
    final command = <String>[executable, ...args];
    return '"${command.join(' ')}" in $workingDir';
  }
}

/// Sets up standard mocking common to most command unit test setUp methods,
/// including a packages directory in an in-memory filesystem, and a mock
/// process handling (including git commands sent by GitDir).
///
/// The returned GitDir instance forwards to a mock process runner, as described
/// in [createForwardingMockGitDir]. This process runner is separate, so that
/// tests can easily treat most git commands called as internal implementation
/// details, and assert on the exact list of non-git commands that are run.
({
  Directory packagesDir,
  RecordingProcessRunner processRunner,
  RecordingProcessRunner gitProcessRunner,
  GitDir gitDir,
})
configureBaseCommandMocks({
  NativePlatform? platform,
  RecordingProcessRunner? customProcessRunner,
  RecordingProcessRunner? customGitProcessRunner,
}) {
  final FileSystem fileSystem = MemoryFileSystem(
    style: (platform?.isWindows ?? false) ? FileSystemStyle.windows : FileSystemStyle.posix,
  );
  final Directory packagesDir = createPackagesDirectory(fileSystem);

  final RecordingProcessRunner processRunner = customProcessRunner ?? RecordingProcessRunner();

  final RecordingProcessRunner gitProcessRunner =
      customGitProcessRunner ?? RecordingProcessRunner();
  final GitDir gitDir = createForwardingMockGitDir(
    packagesDir: packagesDir,
    processRunner: gitProcessRunner,
  );

  return (
    packagesDir: packagesDir,
    processRunner: processRunner,
    gitProcessRunner: gitProcessRunner,
    gitDir: gitDir,
  );
}

void setToolConfig(
  Directory repoRoot, {
  String repoName = 'flutter/packages',
  String? minFlutterVersion,
  String? minDartVersion,
  List<String>? pinnedDependencies,
  List<String>? unpinnedDependencies,
  Map<String, String>? packageLabels,
}) {
  final editor = YamlEditor('{repo_name: $repoName}');
  if (minFlutterVersion != null) {
    editor.update(['min_flutter'], minFlutterVersion);
  }
  if (minDartVersion != null) {
    editor.update(['min_dart'], minDartVersion);
  }
  if (pinnedDependencies != null || unpinnedDependencies != null) {
    const allowedDependenciesKey = 'allowed_dependencies';
    const pinnedKey = 'pinned';
    const unpinnedKey = 'unpinned';
    editor.update([allowedDependenciesKey], YamlMap());
    if (pinnedDependencies != null) {
      editor.update([allowedDependenciesKey, pinnedKey], YamlList());
      for (final String dependency in pinnedDependencies) {
        editor.appendToList([allowedDependenciesKey, pinnedKey], dependency);
      }
    }
    if (unpinnedDependencies != null) {
      editor.update([allowedDependenciesKey, unpinnedKey], YamlList());
      for (final String dependency in unpinnedDependencies) {
        editor.appendToList([allowedDependenciesKey, unpinnedKey], dependency);
      }
    }
  }
  if (packageLabels != null) {
    editor.update(['package_labels'], YamlMap());
    for (final MapEntry<String, String> entry in packageLabels.entries) {
      editor.update(['package_labels', entry.key], entry.value);
    }
  }
  repoRoot.childFile('.repo_tool_config.yaml').writeAsStringSync(editor.toString());
  clearToolConfigCache();
}
