// 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:io' as io;

import 'package:file/file.dart';
import 'package:yaml/yaml.dart';

import 'common/core.dart';
import 'common/file_filters.dart';
import 'common/flutter_command_utils.dart';
import 'common/gradle.dart';
import 'common/output_utils.dart';
import 'common/package_looping_command.dart';
import 'common/plugin_utils.dart';
import 'common/pub_utils.dart';
import 'common/repository_package.dart';
import 'common/xcode.dart';

/// A command to run Dart analysis on packages.
class AnalyzeCommand extends PackageLoopingCommand {
  /// Creates a analysis command instance.
  AnalyzeCommand(super.packagesDir, {super.processRunner, super.platform, super.gitDir}) {
    // Platform options.
    // By default, only Dart analysis is run.
    argParser.addFlag(_dartFlag, help: "Runs 'dart analyze'", defaultsTo: true);
    argParser.addFlag(platformAndroid, help: "Runs 'gradle lint' on Android code");
    argParser.addFlag(platformIOS, help: "Runs 'xcodebuild analyze' on iOS code");
    argParser.addFlag(platformMacOS, help: "Runs 'xcodebuild analyze' on macOS code");

    // Dart options.
    // TODO(stuartmorgan): Remove this entirely once the flutter/flutter and dart-lang repo scripts
    // that run flutter/packages analysis have been updated not to pass it.
    argParser.addMultiOption(
      'custom-analysis',
      help: 'Ignored; exists for legacy compatibility only.',
      hide: true,
    );
    argParser.addOption(
      _analysisSdk,
      valueHelp: 'dart-sdk',
      help:
          'An optional path to a Dart SDK; this is used to override the '
          'SDK used to provide analysis.',
    );
    argParser.addFlag(
      _downgradeFlag,
      help:
          'Runs "flutter pub downgrade" before analysis to verify that '
          'the minimum constraints are sufficiently new for APIs used.',
    );
    argParser.addFlag(
      _libOnlyFlag,
      help:
          'Only analyze the lib/ directory of the main package, not the '
          'entire package.',
    );
    argParser.addFlag(
      _skipIfResolvingFailsFlag,
      help:
          'If resolution fails, skip the package. This is only '
          'intended to be used with pathified analysis, where a resolver '
          'failure indicates that no out-of-band failure can result anyway.',
      hide: true,
    );

    // Xcode options.
    argParser.addOption(
      _minIOSVersionArg,
      help:
          'Sets the minimum iOS deployment version to use when compiling, '
          'overriding the default minimum version. This can be used to find '
          'deprecation warnings that will affect the plugin in the future.',
    );
    argParser.addOption(
      _minMacOSVersionArg,
      help:
          'Sets the minimum macOS deployment version to use when compiling, '
          'overriding the default minimum version. This can be used to find '
          'deprecation warnings that will affect the plugin in the future.',
    );
  }

  static const String _dartFlag = 'dart';
  static const String _downgradeFlag = 'downgrade';
  static const String _libOnlyFlag = 'lib-only';
  static const String _analysisSdk = 'analysis-sdk';
  static const String _skipIfResolvingFailsFlag = 'skip-if-resolving-fails';
  static const String _minIOSVersionArg = 'ios-min-version';
  static const String _minMacOSVersionArg = 'macos-min-version';

  late String _dartBinaryPath;

  @override
  final String name = 'analyze';

  @override
  final String description =
      'Analyzes all packages using dart analyze.\n\n'
      'This command requires "dart" and "flutter" to be in your path.';

  /// Checks that there are no package-local analysis_options.yaml files.
  bool _hasLocalAnalysisOptions(RepositoryPackage package) {
    final List<FileSystemEntity> files = package.directory.listSync(
      recursive: true,
      followLinks: false,
    );
    for (final file in files) {
      if (file.basename != 'analysis_options.yaml' && file.basename != '.analysis_options') {
        continue;
      }

      // Skip anything checked out inside of .dart_tool/.
      if (file.path.contains('/.dart_tool/')) {
        continue;
      }

      printError('Found an unexpected analysis_options.yaml at ${file.absolute.path}.');
      printError(
        'If this is an intentional exception to the general repository guidance against having '
        'custom analysis_options.yaml files, add a ci_config.yaml to this package that '
        'sets "allow_custom_analysis_options: true", with a comment explaining why an exception '
        'is needed.',
      );
      return true;
    }
    return false;
  }

  @override
  bool shouldIgnoreFile(String path) {
    // Support files don't affect any analysis.
    if (isRepoLevelNonCodeImpactingFile(path) || isPackageSupportFile(path)) {
      return true;
    }

    // For native code, it depends on the flags.
    if (path.endsWith('.dart')) {
      return !getBoolArg(_dartFlag);
    }
    if (path.endsWith('.java') || path.endsWith('.kt')) {
      return !getBoolArg(platformAndroid);
    }
    if (path.endsWith('.c') ||
        path.endsWith('.cc') ||
        path.endsWith('.cpp') ||
        path.endsWith('.h')) {
      // If C/C++ linting is added, Windows and Linux should be added here.
      return !(getBoolArg(platformIOS) || getBoolArg(platformMacOS));
    }
    if (path.endsWith('.m') || path.endsWith('.mm') || path.endsWith('.swift')) {
      return !(getBoolArg(platformIOS) || getBoolArg(platformMacOS));
    }

    return false;
  }

  @override
  Future<void> initializeRun() async {
    // Use the Dart SDK override if one was passed in.
    final dartSdk = argResults![_analysisSdk] as String?;
    _dartBinaryPath = dartSdk == null ? 'dart' : path.join(dartSdk, 'bin', 'dart');
  }

  @override
  Future<PackageResult> runForPackage(RepositoryPackage package) async {
    final subResults = <String, PackageResult>{};
    if (getBoolArg(_dartFlag)) {
      _printSectionHeading('Running dart analyze.');
      subResults['Dart'] = await _runDartAnalysisForPackage(package);
    }
    if (getBoolArg(platformAndroid)) {
      _printSectionHeading('Running gradle lint.');
      subResults['Android'] = await _runGradleLintForPackage(package);
    }
    if (getBoolArg(platformIOS)) {
      _printSectionHeading('Running iOS xcodebuild analyze.');
      final String minIOSVersion = getStringArg(_minIOSVersionArg);
      subResults['iOS'] = await _runXcodeAnalysisForPackage(
        package,
        FlutterPlatform.ios,
        extraFlags: <String>[
          '-destination',
          'generic/platform=iOS Simulator',
          if (minIOSVersion.isNotEmpty) 'IPHONEOS_DEPLOYMENT_TARGET=$minIOSVersion',
        ],
      );
    }
    if (getBoolArg(platformMacOS)) {
      _printSectionHeading('Running macOS xcodebuild analyze.');
      final String minMacOSVersion = getStringArg(_minMacOSVersionArg);
      subResults['macOS'] = await _runXcodeAnalysisForPackage(
        package,
        FlutterPlatform.macos,
        extraFlags: <String>[
          if (minMacOSVersion.isNotEmpty) 'MACOSX_DEPLOYMENT_TARGET=$minMacOSVersion',
        ],
      );
    }

    // Make sure at least one analysis option was requested.
    if (subResults.isEmpty) {
      printError('At least one analysis option flag must be provided.');
      throw ToolExit(exitInvalidArguments);
    }
    // If only one analysis was requested, just return its result.
    if (subResults.length == 1) {
      return subResults.values.first;
    }
    // Otherwise, aggregate the messages, with the least positive status.
    final failedResults = Map<String, PackageResult>.of(subResults)
      ..removeWhere((String key, PackageResult value) => value.state != RunState.failed);
    final skippedResults = Map<String, PackageResult>.of(subResults)
      ..removeWhere((String key, PackageResult value) => value.state != RunState.skipped);
    // If anything failed, collect all the failure messages, prefixed by type.
    if (failedResults.isNotEmpty) {
      return PackageResult.fail(<String>[
        for (final MapEntry<String, PackageResult> entry in failedResults.entries)
          '${entry.key}${entry.value.details.isEmpty ? '' : ': ${entry.value.details.join(', ')}'}',
      ]);
    }
    // If everything was skipped, mark as skipped with all of the explanations.
    if (skippedResults.length == subResults.length) {
      return PackageResult.skip(
        skippedResults.entries
            .map(
              (MapEntry<String, PackageResult> entry) =>
                  '${entry.key}: ${entry.value.details.first}',
            )
            .join(', '),
      );
    }
    // For all succes, or a mix of success and skip, log any skips but mark as
    // success.
    for (final MapEntry<String, PackageResult> skip in skippedResults.entries) {
      printSkip('Skipped ${skip.key}: ${skip.value.details.first}');
    }
    return PackageResult.success();
  }

  void _printSectionHeading(String heading) {
    print('\n$heading');
    print('--------------------');
  }

  /// Runs Dart analysis for the given package, and returns the result that
  /// applies to that analysis.
  Future<PackageResult> _runDartAnalysisForPackage(RepositoryPackage package) async {
    final bool libOnly = getBoolArg(_libOnlyFlag);

    if (libOnly && !package.libDirectory.existsSync()) {
      return PackageResult.skip('No lib/ directory.');
    }

    if (getBoolArg(_downgradeFlag)) {
      if (!await _runPubCommand(package, 'downgrade')) {
        return PackageResult.fail(<String>['Unable to resolve downgraded dependencies']);
      }
    }

    // Analysis runs over the package and all subpackages (unless only lib/ is
    // being analyzed), so all of them need `flutter pub get` run before
    // analyzing. `example` packages can be skipped since 'flutter pub get'
    // automatically runs `pub get` in examples as part of handling the parent
    // directory.
    final packagesToGet = <RepositoryPackage>[package, if (!libOnly) ...package.getSubpackages()];
    for (final packageToGet in packagesToGet) {
      if (packageToGet.directory.basename != 'example' ||
          !RepositoryPackage(packageToGet.directory.parent).pubspecFile.existsSync()) {
        if (!await _runPubCommand(packageToGet, 'get')) {
          if (getBoolArg(_skipIfResolvingFailsFlag)) {
            // Re-run, capturing output, to see if the failure was a resolver
            // failure. (This is slightly inefficient, but this should be a
            // very rare case.)
            const resolverFailureMessage = 'version solving failed';
            final io.ProcessResult result = await processRunner.run(flutterCommand, <String>[
              'pub',
              'get',
            ], workingDir: packageToGet.directory);
            if ((result.stderr as String).contains(resolverFailureMessage) ||
                (result.stdout as String).contains(resolverFailureMessage)) {
              logWarning('Skipping package due to pub resolution failure.');
              return PackageResult.skip('Resolution failed.');
            }
          }
          return PackageResult.fail(<String>['Unable to get dependencies']);
        }
      }
    }

    // Require an explicit opt-in to use custom analysis options, since it's very easy to
    // accidentally introduce them to the repo (e.g., with 'flutter create').
    if (!(package.parseCIConfig()?.allowCustomAnalysisOptions ?? false) &&
        _hasLocalAnalysisOptions(package)) {
      return PackageResult.fail(<String>['Unexpected local analysis options']);
    }
    final int mainExitCode = await processRunner.runAndStream(_dartBinaryPath, <String>[
      'analyze',
      '--fatal-infos',
      if (libOnly) 'lib',
    ], workingDir: package.directory);

    var skillsExitCode = 0;
    var skillsErrors = <String>[];
    if (!libOnly && (package.parseCIConfig()?.analyzeSkills ?? false)) {
      skillsErrors = _validateAgentsSkillsDirectory(package);
      if (skillsErrors.isEmpty) {
        skillsExitCode = await processRunner.runAndStream(_dartBinaryPath, <String>[
          'analyze',
          '--fatal-infos',
          '.agents/skills',
        ], workingDir: package.directory);
      }
    }

    final errors = <String>[
      if (mainExitCode != 0) 'Main package analysis failed',
      if (skillsExitCode != 0) 'Skills analysis failed',
      ...skillsErrors,
    ];

    final customCheckRunners = <_CustomLinter>[
      _CustomLinter(dependencyName: 'cognitive_complexity', run: _runCognitiveComplexityForPackage),
    ];

    // Skip custom linters during downgrade as metrics are redundant and vulnerable to dependency issues.
    if (!getBoolArg(_downgradeFlag)) {
      final Pubspec pubspec = package.parsePubspec();
      for (final runner in customCheckRunners) {
        final bool hasDependency = pubspec.devDependencies.containsKey(runner.dependencyName);
        if (hasDependency) {
          errors.addAll(await runner.run(package));
        }
      }
    }

    return errors.isEmpty ? PackageResult.success() : PackageResult.fail(errors);
  }

  /// Retrieves the configured cognitive complexity threshold from the local
  /// `analysis_options.yaml` if it exists and is configured.
  int? _getLinterThreshold(RepositoryPackage package) {
    final File optionsFile = package.directory.childFile('analysis_options.yaml');
    if (!optionsFile.existsSync()) {
      return null;
    }
    try {
      final Object? yaml = loadYaml(optionsFile.readAsStringSync());
      if (yaml is YamlMap) {
        final Object? linter = yaml['cognitive_complexity'];
        if (linter is YamlMap) {
          final Object? threshold = linter['fail-threshold'];
          if (threshold is int) {
            return threshold;
          }
        }
      }
    } catch (_) {
      // Ignore errors parsing invalid/incomplete files.
    }
    return null;
  }

  bool _isGeneratedDartFile(String filePath) {
    return filePath.endsWith('.g.dart') ||
        filePath.endsWith('.mocks.dart') ||
        filePath.endsWith('.gen.dart');
  }

  /// Runs the `cognitive_complexity` metrics analyzer on the package.
  ///
  /// Assumes `cognitive_complexity` is present in `dev_dependencies`.
  Future<List<String>> _runCognitiveComplexityForPackage(RepositoryPackage package) async {
    if (!package.libDirectory.existsSync()) {
      return <String>[];
    }
    final filesToAnalyze = <String>[];
    for (final FileSystemEntity entity in package.libDirectory.listSync(recursive: true)) {
      if (entity is File && entity.path.endsWith('.dart') && !_isGeneratedDartFile(entity.path)) {
        final String relativePath = path.relative(entity.path, from: package.directory.path);
        filesToAnalyze.add(relativePath.replaceAll(r'\', '/'));
      }
    }
    if (filesToAnalyze.isEmpty) {
      return <String>[];
    }
    filesToAnalyze.sort();

    print('Running cognitive_complexity analysis...');
    final int? threshold = _getLinterThreshold(package);
    final args = <String>[
      'run',
      'cognitive_complexity',
      if (threshold != null) ...<String>[
        // --fail-threshold only controls the exit code, while --threshold
        // controls which functions are printed in the output table (default 0).
        // Pass both so that only failing functions are printed in CI logs.
        '--threshold',
        threshold.toString(),
        '--fail-threshold',
        threshold.toString(),
      ],
      ...filesToAnalyze,
    ];
    final int linterExitCode = await processRunner.runAndStream(
      _dartBinaryPath,
      args,
      workingDir: package.directory,
    );
    if (linterExitCode != 0) {
      final thresholdMessage = threshold != null ? ' (configured threshold: $threshold)' : '';
      return <String>[
        'Metrics violations found$thresholdMessage. See the package\'s local "analysis_options.yaml" for configured thresholds.',
      ];
    }

    return <String>[];
  }

  /// Validates that `.agents/skills` contains Dart code if configured for skills analysis.
  ///
  /// Returns a list of error strings if the package is configured for skills analysis
  /// but no Dart code was found. Returns an empty list on success.
  List<String> _validateAgentsSkillsDirectory(RepositoryPackage package) {
    bool hasDartFiles(Directory dir) {
      if (!dir.existsSync()) {
        return false;
      }
      return dir
          .listSync(recursive: true)
          .any((FileSystemEntity entity) => entity is File && entity.path.endsWith('.dart'));
    }

    final Directory agentsSkillsDir = package.directory
        .childDirectory('.agents')
        .childDirectory('skills');

    if (!hasDartFiles(agentsSkillsDir)) {
      printError(
        'Configured to analyze skills for ${package.directory.basename}, but no Dart code was found in .agents/skills.',
      );
      return <String>['No Dart code found in .agents/skills'];
    }

    return <String>[];
  }

  Future<bool> _runPubCommand(RepositoryPackage package, String command) async {
    return runPubCommand(
      <String>[command],
      package,
      processRunner,
      platform,
      dartSdkPathOverride: _dartBinaryPath,
      // 'get' and 'downgrade' resolve examples as well, so check
      // those as well when deciding between `flutter` and `dart`.
      recursiveFlutterCheck: true,
    );
  }

  /// Runs Gradle lint analysis for the given package, and returns the result
  /// that applies to that analysis.
  Future<PackageResult> _runGradleLintForPackage(RepositoryPackage package) async {
    if (!pluginSupportsPlatform(platformAndroid, package, requiredMode: PlatformSupport.inline) ||
        !package.platformDirectory(FlutterPlatform.android).existsSync()) {
      return PackageResult.skip('Package does not contain native Android plugin code');
    }

    for (final RepositoryPackage example in package.getExamples()) {
      final project = GradleProject(example, processRunner: processRunner, platform: platform);

      if (!project.isConfigured()) {
        final bool buildSuccess = await runConfigOnlyBuild(
          example,
          processRunner,
          platform,
          FlutterPlatform.android,
        );
        if (!buildSuccess) {
          printError('Unable to configure Gradle project.');
          return PackageResult.fail(<String>['Unable to configure Gradle.']);
        }
      }

      final String packageName = package.directory.basename;

      // Only lint one build mode to avoid extra work.
      // Only lint the plugin project itself, to avoid failing due to errors in
      // dependencies.
      //
      // TODO(stuartmorgan): Consider adding an XML parser to read and summarize
      //  all results. Currently, only the first three errors will be shown
      //  inline, and the rest have to be checked via the CI-uploaded artifact.
      final int exitCode = await project.runCommand('$packageName:lintDebug');
      if (exitCode != 0) {
        return PackageResult.fail();
      }
    }

    return PackageResult.success();
  }

  /// Analyzes [plugin] for [targetPlatform].
  Future<PackageResult> _runXcodeAnalysisForPackage(
    RepositoryPackage package,
    FlutterPlatform targetPlatform, {
    List<String> extraFlags = const <String>[],
  }) async {
    final platformString = targetPlatform == FlutterPlatform.ios ? 'iOS' : 'macOS';
    if (!pluginSupportsPlatform(
      targetPlatform.name,
      package,
      requiredMode: PlatformSupport.inline,
    )) {
      return PackageResult.skip('Package does not contain native $platformString plugin code');
    }

    final xcode = Xcode(processRunner: processRunner, log: true);
    final errors = <String>[];
    for (final RepositoryPackage example in package.getExamples()) {
      // Unconditionally re-run build with --debug --config-only, to ensure that
      // the project is in a debug state even if it was previously configured.
      print('Running flutter build --config-only...');
      final bool buildSuccess = await runConfigOnlyBuild(
        example,
        processRunner,
        platform,
        targetPlatform,
        buildDebug: true,
      );
      if (!buildSuccess) {
        printError('Unable to prepare native project files.');
        errors.add(
          'Unable to build ${getRelativePosixPath(example.directory, from: package.directory)}.',
        );
        continue;
      }

      // Running tests and static analyzer.
      final String examplePath = getRelativePosixPath(
        example.directory,
        from: package.directory.parent,
      );
      print('Running $platformString tests and analyzer for $examplePath...');
      final int exitCode = await xcode.runXcodeBuild(
        example.directory,
        platformString,
        // Clean before analyzing to remove cached swiftmodules from previous
        // runs, which can cause conflicts.
        actions: <String>['clean', 'analyze'],
        workspace: '${platformString.toLowerCase()}/Runner.xcworkspace',
        scheme: 'Runner',
        configuration: 'Debug',
        hostPlatform: platform,
        extraFlags: <String>[...extraFlags, 'GCC_TREAT_WARNINGS_AS_ERRORS=YES'],
      );
      if (exitCode == 0) {
        printSuccess('$examplePath ($platformString) passed analysis.');
      } else {
        printError('$examplePath ($platformString) failed analysis.');
        errors.add(
          '${getRelativePosixPath(example.directory, from: package.directory)} failed analysis.',
        );
      }
    }
    return errors.isEmpty ? PackageResult.success() : PackageResult.fail(errors);
  }
}

/// Represents a custom linter check that is executed during package analysis.
class _CustomLinter {
  const _CustomLinter({required this.dependencyName, required this.run});

  /// The name of the package dependency that triggers this custom check.
  ///
  /// The check is only executed if this dependency is listed in the package's
  /// `dev_dependencies`.
  final String dependencyName;

  /// The runner function that executes the custom check.
  final Future<List<String>> Function(RepositoryPackage) run;
}
