// 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 is newer
  /// than all source files recorded in the depfile.
  static bool isSnapshotFresh({
    required File snapshotFile,
    required File packageConfigFile,
    required File depfile,
    required File metadataFile,
    required List<String> enabledExperiments,
  }) {
    try {
      if (!snapshotFile.existsSync() ||
          !packageConfigFile.existsSync() ||
          !depfile.existsSync() ||
          !metadataFile.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;
      }

      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 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,
      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;
}
