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

import 'package:collection/collection.dart';
import 'package:package_config/package_config.dart';
import 'package:path/path.dart' as p;
import 'package:pub/pub.dart';

import 'core.dart';
import 'progress.dart';
import 'sdk.dart';

abstract final class ExecutableCompiler {
  /// Suffix appended to the snapshot path to get the depfile path.
  static const depfileExtension = '.d';

  /// Suffix appended to the snapshot path to get the metadata file path.
  ///
  /// The metadata file records the configuration the snapshot was compiled
  /// with, see [buildMetadata].
  static const metadataExtension = '.json';

  /// Version of the metadata file format, bumped when the contents change in
  /// a way older or newer SDKs cannot understand.
  static const metadataVersion = 1;

  /// Returns the expected snapshot path in `.dart_tool/dartdev/bin/`.
  ///
  /// The format matches
  /// `.dart_tool/dartdev/bin/<package>/<relativeScriptPath>.snapshot`.
  /// The SDK version and enabled experiments are stored in the companion
  /// metadata file (`<snapshot>.json`) rather than encoded in the filename, so
  /// that changing SDK or experiments overwrites the snapshot instead of
  /// leaving a stale one behind.
  static String pathOfSnapshot({
    required String workspaceRoot,
    required String packageName,
    required String relativeScriptPath,
  }) {
    return p.normalize(
      p.join(
        workspaceRoot,
        '.dart_tool',
        'dartdev',
        'bin',
        packageName,
        '$relativeScriptPath.snapshot',
      ),
    );
  }

  /// Returns the parent directory for temporary compilation directories in
  /// `.dart_tool/dartdev/tmp/`.
  ///
  /// Keeping temporary directories outside `.dart_tool/dartdev/bin/` ensures
  /// that [sweepStaleTempDirs] sweeps leftover directories across all packages
  /// and subdirectories while never colliding with package subdirectory names.
  static String pathOfTempDir({required String workspaceRoot}) {
    return p.normalize(p.join(workspaceRoot, '.dart_tool', 'dartdev', 'tmp'));
  }

  /// The version of the SDK that compiles the snapshots.
  static String get sdkVersion => Platform.version.split(' ').first;

  /// The configuration a snapshot was compiled with.
  ///
  /// A cached snapshot can only be reused if this matches the configuration of
  /// the current invocation, see [isSnapshotFresh].
  static Map<String, Object?> buildMetadata({
    required List<String> enabledExperiments,
  }) {
    return {
      'version': metadataVersion,
      'sdkVersion': sdkVersion,
      'enabledExperiments': [...enabledExperiments]..sort(),
    };
  }

  /// Parses a Ninja/Makefile-style depfile generated by the compiler.
  ///
  /// The format is:
  ///
  ///     target: dependency1 dependency2 ...
  ///
  /// Spaces in paths are escaped as `\ `, and backslashes as `\\`.
  /// Returns `null` if [content] does not contain the `: ` separator.
  static List<String>? parseDepfile(String content) {
    final colonIndex = content.indexOf(': ');
    if (colonIndex < 0) return null;

    final dependenciesString = content
        .substring(colonIndex + 1)
        .replaceAll(RegExp(r'[\r\n]'), '');
    final dependencies = <String>[];
    var index = 0;
    while (index < dependenciesString.length) {
      while (index < dependenciesString.length &&
          dependenciesString[index] == ' ') {
        index++;
      }
      if (index >= dependenciesString.length) break;
      final buffer = StringBuffer();
      while (index < dependenciesString.length) {
        final char = dependenciesString[index];
        if (char == ' ') {
          break;
        } else if (char == r'\') {
          index++;
          if (index >= dependenciesString.length) {
            // Malformed trailing backslash.
            return null;
          }
          buffer.write(dependenciesString[index]);
        } else {
          buffer.write(char);
        }
        index++;
      }
      if (buffer.isNotEmpty) {
        dependencies.add(buffer.toString());
      }
    }
    return dependencies;
  }

  /// Checks whether [snapshotFile] is up to date with respect to its inputs.
  ///
  /// Returns `true` if the snapshot exists, was compiled by this SDK with
  /// [enabledExperiments], is newer than [packageConfigFile] and
  /// [platformDill], and is newer than all source files recorded in the
  /// depfile.
  ///
  /// The depfile does not list the SDK libraries, and SDK builds from source
  /// share a version string, so checking [platformDill] is what catches a
  /// snapshot compiled against an older build of the platform libraries.
  static bool isSnapshotFresh({
    required File snapshotFile,
    required File packageConfigFile,
    required File depfile,
    required File metadataFile,
    required File platformDill,
    required List<String> enabledExperiments,
  }) {
    try {
      if (!snapshotFile.existsSync() ||
          !packageConfigFile.existsSync() ||
          !depfile.existsSync() ||
          !metadataFile.existsSync() ||
          !platformDill.existsSync()) {
        return false;
      }

      // The snapshot is only usable if it was built with the same compiler and
      // the same compilation options.
      final Object? metadata;
      try {
        metadata = jsonDecode(metadataFile.readAsStringSync());
      } on FormatException {
        return false;
      }
      final expectedMetadata = buildMetadata(
        enabledExperiments: enabledExperiments,
      );
      final actualExperiments = metadata is Map<String, Object?>
          ? metadata['enabledExperiments']
          : null;
      if (metadata is! Map<String, Object?> ||
          metadata['version'] != expectedMetadata['version'] ||
          metadata['sdkVersion'] != expectedMetadata['sdkVersion'] ||
          actualExperiments is! List ||
          !const ListEquality<Object?>().equals(
            actualExperiments,
            expectedMetadata['enabledExperiments'] as List<String>,
          )) {
        return false;
      }

      final snapshotModified = snapshotFile.lastModifiedSync();
      if (packageConfigFile.lastModifiedSync().isAfter(snapshotModified)) {
        return false;
      }
      if (platformDill.lastModifiedSync().isAfter(snapshotModified)) {
        return false;
      }

      final depfileContent = depfile.readAsStringSync();
      final dependencies = parseDepfile(depfileContent);
      if (dependencies == null) return false;

      for (final depPath in dependencies) {
        final depFile = File(depPath);
        if (!depFile.existsSync()) return false;
        if (depFile.lastModifiedSync().isAfter(snapshotModified)) return false;
      }

      return true;
    } on FileSystemException {
      return false;
    }
  }

  /// Compiles or returns the cached snapshot for [resolvedExecutable].
  ///
  /// The snapshot is compiled with [enabledExperiments] enabled, and a cached
  /// snapshot is only reused if it was compiled by this SDK with the same
  /// experiments, is newer than [packageConfigPath] and the SDK's VM platform
  /// dill, and is newer than all source dependencies recorded in its depfile.
  ///
  /// If [verbose] is `true`, a `Built <package>:<executable>.` status line is
  /// written to stderr after a successful compilation.
  ///
  /// Returns a [DartExecutableWithPackageConfig] pointing to the snapshot file.
  static Future<DartExecutableWithPackageConfig> compile({
    required DartExecutableWithPackageConfig resolvedExecutable,
    List<String> enabledExperiments = const [],
    bool verbose = false,
  }) async {
    final executablePath = resolvedExecutable.executable;
    final packageConfigPath = resolvedExecutable.packageConfig;
    if (packageConfigPath == null) {
      // Direct file with no package config. Not snapshotted.
      return resolvedExecutable;
    }

    final packageConfigAbsolute = p.absolute(packageConfigPath);
    final packageConfig = await loadPackageConfigUri(
      p.toUri(packageConfigAbsolute),
    );

    final executableAbsolute = p.absolute(executablePath);
    final package = packageConfig.packageOf(p.toUri(executableAbsolute));
    if (package == null) {
      // Could not determine package. Return resolved executable as-is.
      return resolvedExecutable;
    }

    final packageRootPath = p.fromUri(package.root);
    if (!p.isWithin(packageRootPath, executableAbsolute)) {
      return resolvedExecutable;
    }

    final relativeScriptPath = p.relative(
      executableAbsolute,
      from: packageRootPath,
    );

    // Determine workspace root from .dart_tool/package_config.json
    final workspaceRoot = p.dirname(p.dirname(packageConfigAbsolute));
    final snapshotPath = pathOfSnapshot(
      workspaceRoot: workspaceRoot,
      packageName: package.name,
      relativeScriptPath: relativeScriptPath,
    );

    final snapshotFile = File(snapshotPath);
    final packageConfigFile = File(packageConfigAbsolute);
    final depfile = File('$snapshotPath$depfileExtension');
    final metadataFile = File('$snapshotPath$metadataExtension');

    if (!isSnapshotFresh(
      snapshotFile: snapshotFile,
      packageConfigFile: packageConfigFile,
      depfile: depfile,
      metadataFile: metadataFile,
      platformDill: File(sdk.vmPlatformDill),
      enabledExperiments: enabledExperiments,
    )) {
      final displayName =
          '${package.name}:${p.basenameWithoutExtension(executablePath)}';
      await _compileToSnapshot(
        executablePath: executableAbsolute,
        displayName: displayName,
        outputPath: snapshotPath,
        tempParentPath: pathOfTempDir(workspaceRoot: workspaceRoot),
        packageConfigPath: packageConfigAbsolute,
        enabledExperiments: enabledExperiments,
        verbose: verbose,
      );
    }

    return DartExecutableWithPackageConfig(
      executable: _relativeOrAbsolute(snapshotPath, p.current),
      packageConfig: packageConfigPath,
    );
  }

  /// Prefix of the temporary directories compilation output is written to.
  static const _tempDirPrefix = 'tmp';

  /// Age at which a leftover temporary directory is considered abandoned.
  ///
  /// Temporary directories are removed when compilation finishes, but they
  /// survive if the process is killed before that (for example with Ctrl+C).
  /// The threshold is generous so that a temporary directory belonging to a
  /// slow compilation in another process is never removed.
  static const defaultStaleTempDirAge = Duration(hours: 1);

  /// Removes temporary directories in [tempParentDir] that were left behind by
  /// compilations interrupted before they could clean up after themselves.
  ///
  /// A temporary directory is only removed if it has not been modified for
  /// [maxAge], so that directories in use by a concurrent compilation are
  /// left alone.
  ///
  /// This is best-effort: failures are ignored, as another process may be
  /// using the directory, or we may not be allowed to delete it.
  static void sweepStaleTempDirs(
    Directory tempParentDir, {
    Duration maxAge = defaultStaleTempDirAge,
  }) {
    final now = DateTime.now();
    final List<FileSystemEntity> entities;
    try {
      entities = tempParentDir.listSync(followLinks: false);
    } on FileSystemException {
      return;
    }
    for (final entity in entities) {
      if (entity is! Directory) continue;
      if (!p.basename(entity.path).startsWith(_tempDirPrefix)) continue;
      try {
        if (now.difference(entity.statSync().modified) < maxAge) continue;
        entity.deleteSync(recursive: true);
      } on FileSystemException {
        // Ignore.
      }
    }
  }

  static Future<void> _compileToSnapshot({
    required String executablePath,
    required String displayName,
    required String outputPath,
    required String tempParentPath,
    required String packageConfigPath,
    required List<String> enabledExperiments,
    required bool verbose,
  }) async {
    final outputDir = Directory(p.dirname(outputPath));
    if (!outputDir.existsSync()) {
      outputDir.createSync(recursive: true);
    }
    final tempParentDir = Directory(tempParentPath);
    if (!tempParentDir.existsSync()) {
      tempParentDir.createSync(recursive: true);
    }

    sweepStaleTempDirs(tempParentDir);
    final incrementalDillPath = '$outputPath.incremental';
    final tempDir = tempParentDir.createTempSync(_tempDirPrefix);
    final tempDill = p.join(tempDir.path, 'out.dill');
    final tempDepfile = '$tempDill$depfileExtension';
    final tempMetadataFile = '$tempDill$metadataExtension';
    final depfilePath = '$outputPath$depfileExtension';
    final metadataPath = '$outputPath$metadataExtension';

    // If an existing snapshot or incremental dill is present, copy it to a
    // temporary file and pass it as `--initialize-from-dill` to speed up
    // subsequent compilations without holding a file lock on the destination.
    final outputFile = File(outputPath);
    final depfile = File(depfilePath);
    final metadataFile = File(metadataPath);
    final incrementalFile = File(incrementalDillPath);
    String? initializeFromDill;
    final sourceDill = outputFile.existsSync()
        ? outputFile
        : (incrementalFile.existsSync() ? incrementalFile : null);
    if (sourceDill != null) {
      final tempInitDill = p.join(tempDir.path, 'init.dill');
      try {
        sourceDill.copySync(tempInitDill);
        initializeFromDill = tempInitDill;
      } on FileSystemException {
        // Ignore: fall back to compiling from scratch.
      }
    }

    try {
      final compilerSnapshot = sdk.frontendServerAotSnapshot;
      final aotRuntime = sdk.dartAotRuntime;
      final vmPlatformDill = sdk.vmPlatformDill;
      final sdkRoot = p.canonicalize(sdk.sdkPath);

      if (!checkArtifactExists(compilerSnapshot, logError: false) ||
          !checkArtifactExists(aotRuntime, logError: false) ||
          !checkArtifactExists(vmPlatformDill, logError: false)) {
        throw CompilationException(
          'Missing compiler snapshot, AOT runtime, or platform dill in Dart SDK. '
          'Have you built the full Dart SDK?',
        );
      }

      Future<void> runCompiler() async {
        final compileArgs = <String>[
          compilerSnapshot,
          '--sdk-root=$sdkRoot',
          '--platform=${p.toUri(vmPlatformDill)}',
          '--target=vm',
          '--packages=$packageConfigPath',
          for (final experiment in enabledExperiments)
            '--enable-experiment=$experiment',
          if (initializeFromDill != null)
            '--initialize-from-dill=$initializeFromDill',
          '--output-dill=$tempDill',
          '--depfile=$tempDepfile',
          '--incremental',
          '--no-print-incremental-dependencies',
          executablePath,
        ];

        final ProcessResult result;
        try {
          result = await Process.run(aotRuntime, compileArgs);
        } on ProcessException catch (e) {
          throw CompilationException(
            'Failed to start frontend compiler process ($aotRuntime): $e',
          );
        }

        if (result.exitCode == 0) {
          final tempFile = File(tempDill);
          if (!tempFile.existsSync() || !File(tempDepfile).existsSync()) {
            throw CompilationException(
              'Compilation did not produce expected output files at `$tempDill`.',
            );
          }
          File(tempMetadataFile).writeAsStringSync(
            jsonEncode(buildMetadata(enabledExperiments: enabledExperiments)),
          );
          // Delete any pre-existing metadata file before publishing the new
          // snapshot so that an interrupted rebuild cannot leave the new
          // snapshot paired with stale metadata.
          _tryDelete(metadataFile);
          await _renameFile(tempDill, outputPath);
          await _renameFile(tempDepfile, depfilePath);
          // Published last: without it the snapshot is considered stale, so a
          // crash in the middle of publishing cannot result in a snapshot
          // being reused with the wrong configuration.
          await _renameFile(tempMetadataFile, metadataPath);
          _tryDelete(incrementalFile);
        } else {
          final tempFile = File(tempDill);
          if (tempFile.existsSync()) {
            await _renameFile(tempDill, incrementalDillPath);
          }
          for (final file in [outputFile, depfile, metadataFile]) {
            _tryDelete(file);
          }
          final errorLines = _extractCompilerErrorMessages(
            '${result.stdout}\n${result.stderr}',
          );
          throw CompilationException(
            '${ansi.yellow}Failed to build $displayName:${ansi.none}\n$errorLines',
          );
        }
      }

      try {
        await progress(
          'Building package executable',
          runCompiler,
          transient: true,
          output: ProgressOutput.stderr,
        );
        if (verbose) {
          log.stderr('Built ${ansi.bold}$displayName${ansi.none}.');
        }
      } on CompilationException {
        rethrow;
      } catch (e) {
        throw CompilationException(
          '${ansi.yellow}Failed to build $displayName:${ansi.none}\n$e',
        );
      }
    } finally {
      if (tempDir.existsSync()) {
        try {
          tempDir.deleteSync(recursive: true);
        } on FileSystemException {
          // Ignore.
        }
      }
    }
  }

  static void _tryDelete(File file) {
    try {
      if (file.existsSync()) file.deleteSync();
    } on FileSystemException {
      // Ignore.
    }
  }

  static String _extractCompilerErrorMessages(String output) {
    String? boundaryKey;
    final lines = <String>[];
    for (final rawLine in LineSplitter.split(output)) {
      final trimmed = rawLine.trim();
      if (boundaryKey == null && trimmed.startsWith('result ')) {
        boundaryKey = trimmed.substring('result '.length).trim();
        continue;
      }
      if (boundaryKey != null &&
          (trimmed == boundaryKey || trimmed.startsWith('$boundaryKey '))) {
        continue;
      }
      lines.add(rawLine);
    }
    return lines.join('\n').trim();
  }

  static String _relativeOrAbsolute(String path, String from) {
    try {
      return p.normalize(p.relative(path, from: from));
    } on p.PathException {
      return p.normalize(path);
    }
  }

  /// Number of times replacing a locked file is retried on Windows.
  static const _windowsRenameAttempts = 10;

  static Future<void> _renameFile(String from, String to) async {
    final fromFile = File(from);
    if (!fromFile.existsSync()) return;
    final toFile = File(to);

    if (!Platform.isWindows) {
      fromFile.renameSync(to);
      return;
    }

    // On Windows the destination can be transiently locked (by antivirus, or
    // by another process executing the snapshot), so retry for a short while.
    for (var attempt = 0; attempt < _windowsRenameAttempts; attempt++) {
      try {
        _tryDelete(toFile);
        fromFile.renameSync(to);
        return;
      } on FileSystemException {
        await Future.delayed(const Duration(milliseconds: 20));
      }
    }

    // Still locked. Copying over the destination is more likely to succeed
    // than replacing it, as it does not require removing the locked file.
    fromFile.copySync(to);
    _tryDelete(fromFile);
  }
}

final class CompilationException implements Exception {
  final String message;
  CompilationException(this.message);

  @override
  String toString() => message;
}
