// Copyright (c) 2019, 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 'package:build/build.dart';
import 'package:build_config/build_config.dart';
import 'package:build_runner_core/build_runner_core.dart';
import 'package:build_runner_core/src/generate/phase.dart';
import 'package:io/io.dart';
import 'package:logging/logging.dart';

import '../logging/std_io_logging.dart';
import '../package_graph/build_config_overrides.dart';
import 'base_command.dart';

/// A command that validates the build environment.
class DoctorCommand extends BuildRunnerCommand {
  @override
  String get name => 'doctor';

  @override
  bool get hidden => true;

  @override
  String get description => 'Check for misconfiguration of the build.';

  @override
  Future<int> run() async {
    final options = readOptions();
    final verbose = options.verbose ?? false;
    Logger.root.level = verbose ? Level.ALL : Level.INFO;
    final logSubscription =
        Logger.root.onRecord.listen(stdIOLogListener(verbose: verbose));

    final config = await _loadBuilderDefinitions();

    var isOk = true;
    for (final builderApplication in builderApplications) {
      final builderOk = _checkBuildExtensions(builderApplication, config);
      isOk = isOk && builderOk;
    }

    if (isOk) {
      logger.info('No problems found!\n');
    }
    await logSubscription.cancel();
    return isOk ? ExitCode.success.code : ExitCode.config.code;
  }

  Future<Map<String, BuilderDefinition>> _loadBuilderDefinitions() async {
    final packageGraph = PackageGraph.forThisPackage();
    final buildConfigOverrides =
        await findBuildConfigOverrides(packageGraph, null);
    Future<BuildConfig> _packageBuildConfig(PackageNode package) async {
      if (buildConfigOverrides.containsKey(package.name)) {
        return buildConfigOverrides[package.name];
      }
      try {
        return await BuildConfig.fromBuildConfigDir(package.name,
            package.dependencies.map((n) => n.name), package.path);
      } on ArgumentError catch (e) {
        logger.severe(
            'Failed to parse a `build.yaml` file for ${package.name}', e);
        return BuildConfig.useDefault(
            package.name, package.dependencies.map((n) => n.name));
      }
    }

    final allConfig = await Future.wait(
        packageGraph.allPackages.values.map(_packageBuildConfig));
    final allBuilders = <String, BuilderDefinition>{};
    for (final config in allConfig) {
      allBuilders.addAll(config.builderDefinitions);
    }
    return allBuilders;
  }

  /// Returns true of [builderApplication] has sane build extension
  /// configuration.
  ///
  /// If there are any problems they will be logged and `false` returned.
  bool _checkBuildExtensions(BuilderApplication builderApplication,
      Map<String, BuilderDefinition> config) {
    var phases = builderApplication.buildPhaseFactories
        .map((f) => f(PackageNode(null, null, null, isRoot: true),
            BuilderOptions.empty, InputSet.anything, InputSet.anything, true))
        .whereType<InBuildPhase>()
        .toList();
    if (phases.isEmpty) return true;
    if (!config.containsKey(builderApplication.builderKey)) return false;

    var problemFound = false;
    var allowed = Map.of(config[builderApplication.builderKey].buildExtensions);
    for (final phase in phases.whereType<InBuildPhase>()) {
      final extensions = phase.builder.buildExtensions;
      for (final extension in extensions.entries) {
        if (!allowed.containsKey(extension.key)) {
          logger.warning('Builder ${builderApplication.builderKey} '
              'uses input extension ${extension.key} '
              'which is not specified in the `build.yaml`');
          problemFound = true;
          continue;
        }
        final allowedOutputs = List.of(allowed[extension.key]);
        for (final output in extension.value) {
          if (!allowedOutputs.contains(output)) {
            logger.warning('Builder ${builderApplication.builderKey} '
                'outputs $output  from ${extension.key} '
                'which is not specified in the `build.yaml`');
            problemFound = true;
          }
          // Allow subsequent phases to use these outputs as inputs
          if (allowedOutputs.length > 1) {
            allowed.putIfAbsent(output, () => []).addAll(allowedOutputs);
          }
        }
      }
    }
    return !problemFound;
  }
}
