// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:args/command_runner.dart';
import 'package:file/file.dart';
import 'package:git/git.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:yaml_edit/yaml_edit.dart';

import 'common/core.dart';
import 'common/git_version_finder.dart';
import 'common/package_looping_command.dart';
import 'common/package_state_utils.dart';
import 'common/repository_package.dart';

/// Supported version change types, from smallest to largest component.
enum _VersionIncrementType { build, bugfix, minor }

/// Possible results of attempting to update a CHANGELOG.md file.
enum _ChangelogUpdateOutcome { addedSection, updatedSection, failed }

/// A state machine for the process of updating a CHANGELOG.md.
enum _ChangelogUpdateState {
  /// Looking for the first version section.
  findingFirstSection,

  /// Looking for the first list entry in an existing section.
  findingFirstListItem,

  /// Finished with updates.
  finishedUpdating,
}

/// A command to update the changelog, and optionally version, of packages.
class UpdateReleaseInfoCommand extends PackageLoopingCommand {
  /// Creates a publish metadata updater command instance.
  UpdateReleaseInfoCommand(
    Directory packagesDir, {
    GitDir? gitDir,
  }) : super(packagesDir, gitDir: gitDir) {
    argParser.addOption(_changelogFlag,
        mandatory: true,
        help: 'The changelog entry to add. '
            'Each line will be a separate list entry.');
    argParser.addOption(_versionTypeFlag,
        mandatory: true,
        help: 'The version change level',
        allowed: <String>[
          _versionNext,
          _versionMinimal,
          _versionBugfix,
          _versionMinor,
        ],
        allowedHelp: <String, String>{
          _versionNext:
              'No version change; just adds a NEXT entry to the changelog.',
          _versionBugfix: 'Increments the bugfix version.',
          _versionMinor: 'Increments the minor version.',
          _versionMinimal: 'Depending on the changes to each package: '
              'increments the bugfix version (for publishable changes), '
              "uses NEXT (for changes that don't need to be published), "
              'or skips (if no changes).',
        });
  }

  static const String _changelogFlag = 'changelog';
  static const String _versionTypeFlag = 'version';

  static const String _versionNext = 'next';
  static const String _versionBugfix = 'bugfix';
  static const String _versionMinor = 'minor';
  static const String _versionMinimal = 'minimal';

  // The version change type, if there is a set type for all platforms.
  //
  // If null, either there is no version change, or it is dynamic (`minimal`).
  _VersionIncrementType? _versionChange;

  // The cache of changed files, for dynamic version change determination.
  //
  // Only set for `minimal` version change.
  late final List<String> _changedFiles;

  @override
  final String name = 'update-release-info';

  @override
  final String description = 'Updates CHANGELOG.md files, and optionally the '
      'version in pubspec.yaml, in a way that is consistent with version-check '
      'enforcement.';

  @override
  bool get hasLongOutput => false;

  @override
  Future<void> initializeRun() async {
    if (getStringArg(_changelogFlag).trim().isEmpty) {
      throw UsageException('Changelog message must not be empty.', usage);
    }
    switch (getStringArg(_versionTypeFlag)) {
      case _versionMinor:
        _versionChange = _VersionIncrementType.minor;
        break;
      case _versionBugfix:
        _versionChange = _VersionIncrementType.bugfix;
        break;
      case _versionMinimal:
        final GitVersionFinder gitVersionFinder = await retrieveVersionFinder();
        _changedFiles = await gitVersionFinder.getChangedFiles();
        // Anothing other than a fixed change is null.
        _versionChange = null;
        break;
      case _versionNext:
        _versionChange = null;
        break;
      default:
        throw UnimplementedError('Unimplemented version change type');
    }
  }

  @override
  Future<PackageResult> runForPackage(RepositoryPackage package) async {
    String nextVersionString;

    _VersionIncrementType? versionChange = _versionChange;

    // If the change type is `minimal` determine what changes, if any, are
    // needed.
    if (versionChange == null &&
        getStringArg(_versionTypeFlag) == _versionMinimal) {
      final Directory gitRoot =
          packagesDir.fileSystem.directory((await gitDir).path);
      final String relativePackagePath =
          getRelativePosixPath(package.directory, from: gitRoot);
      final PackageChangeState state = await checkPackageChangeState(package,
          changedPaths: _changedFiles,
          relativePackagePath: relativePackagePath);

      if (!state.hasChanges) {
        return PackageResult.skip('No changes to package');
      }
      if (state.needsVersionChange) {
        versionChange = _VersionIncrementType.bugfix;
      }
    }

    if (versionChange != null) {
      final Version? updatedVersion =
          _updatePubspecVersion(package, versionChange);
      if (updatedVersion == null) {
        return PackageResult.fail(
            <String>['Could not determine current version.']);
      }
      nextVersionString = updatedVersion.toString();
      print('${indentation}Incremented version to $nextVersionString.');
    } else {
      nextVersionString = 'NEXT';
    }

    final _ChangelogUpdateOutcome updateOutcome =
        _updateChangelog(package, nextVersionString);
    switch (updateOutcome) {
      case _ChangelogUpdateOutcome.addedSection:
        print('${indentation}Added a $nextVersionString section.');
        break;
      case _ChangelogUpdateOutcome.updatedSection:
        print('${indentation}Updated NEXT section.');
        break;
      case _ChangelogUpdateOutcome.failed:
        return PackageResult.fail(<String>['Could not update CHANGELOG.md.']);
    }

    return PackageResult.success();
  }

  _ChangelogUpdateOutcome _updateChangelog(
      RepositoryPackage package, String version) {
    if (!package.changelogFile.existsSync()) {
      printError('${indentation}Missing CHANGELOG.md.');
      return _ChangelogUpdateOutcome.failed;
    }

    final String newHeader = '## $version';
    final RegExp listItemPattern = RegExp(r'^(\s*[-*])');

    final StringBuffer newChangelog = StringBuffer();
    _ChangelogUpdateState state = _ChangelogUpdateState.findingFirstSection;
    bool updatedExistingSection = false;

    for (final String line in package.changelogFile.readAsLinesSync()) {
      switch (state) {
        case _ChangelogUpdateState.findingFirstSection:
          final String trimmedLine = line.trim();
          if (trimmedLine.isEmpty) {
            // Discard any whitespace at the top of the file.
          } else if (trimmedLine == '## NEXT') {
            // Replace the header with the new version (which may also be NEXT).
            newChangelog.writeln(newHeader);
            // Find the existing list to add to.
            state = _ChangelogUpdateState.findingFirstListItem;
          } else {
            // The first content in the file isn't a NEXT section, so just add
            // the new section.
            <String>[
              newHeader,
              '',
              ..._changelogAdditionsAsList(),
              '',
              line, // Don't drop the current line.
            ].forEach(newChangelog.writeln);
            state = _ChangelogUpdateState.finishedUpdating;
          }
          break;
        case _ChangelogUpdateState.findingFirstListItem:
          final RegExpMatch? match = listItemPattern.firstMatch(line);
          if (match != null) {
            final String listMarker = match[1]!;
            // Add the new items on top. If the new change is changing the
            // version, then the new item should be more relevant to package
            // clients than anything that was already there. If it's still
            // NEXT, the order doesn't matter.
            <String>[
              ..._changelogAdditionsAsList(listMarker: listMarker),
              line, // Don't drop the current line.
            ].forEach(newChangelog.writeln);
            state = _ChangelogUpdateState.finishedUpdating;
            updatedExistingSection = true;
          } else if (line.trim().isEmpty) {
            // Scan past empty lines, but keep them.
            newChangelog.writeln(line);
          } else {
            printError('  Existing NEXT section has unrecognized format.');
            return _ChangelogUpdateOutcome.failed;
          }
          break;
        case _ChangelogUpdateState.finishedUpdating:
          // Once changes are done, add the rest of the lines as-is.
          newChangelog.writeln(line);
          break;
      }
    }

    package.changelogFile.writeAsStringSync(newChangelog.toString());

    return updatedExistingSection
        ? _ChangelogUpdateOutcome.updatedSection
        : _ChangelogUpdateOutcome.addedSection;
  }

  /// Returns the changelog to add as a Markdown list, using the given list
  /// bullet style (default to the repository standard of '*'), and adding
  /// any missing periods.
  ///
  /// E.g., 'A line\nAnother line.' will become:
  /// ```
  /// [ '* A line.', '* Another line.' ]
  /// ```
  Iterable<String> _changelogAdditionsAsList({String listMarker = '*'}) {
    return getStringArg(_changelogFlag).split('\n').map((String entry) {
      String standardizedEntry = entry.trim();
      if (!standardizedEntry.endsWith('.')) {
        standardizedEntry = '$standardizedEntry.';
      }
      return '$listMarker $standardizedEntry';
    });
  }

  /// Updates the version in [package]'s pubspec according to [type], returning
  /// the new version, or null if there was an error updating the version.
  Version? _updatePubspecVersion(
      RepositoryPackage package, _VersionIncrementType type) {
    final Pubspec pubspec = package.parsePubspec();
    final Version? currentVersion = pubspec.version;
    if (currentVersion == null) {
      printError('${indentation}No version in pubspec.yaml');
      return null;
    }

    // For versions less than 1.0, shift the change down one component per
    // Dart versioning conventions.
    final _VersionIncrementType adjustedType = currentVersion.major > 0
        ? type
        : _VersionIncrementType.values[type.index - 1];

    final Version newVersion = _nextVersion(currentVersion, adjustedType);

    // Write the new version to the pubspec.
    final YamlEditor editablePubspec =
        YamlEditor(package.pubspecFile.readAsStringSync());
    editablePubspec.update(<String>['version'], newVersion.toString());
    package.pubspecFile.writeAsStringSync(editablePubspec.toString());

    return newVersion;
  }

  Version _nextVersion(Version version, _VersionIncrementType type) {
    switch (type) {
      case _VersionIncrementType.minor:
        return version.nextMinor;
      case _VersionIncrementType.bugfix:
        return version.nextPatch;
      case _VersionIncrementType.build:
        final int buildNumber =
            version.build.isEmpty ? 0 : version.build.first as int;
        return Version(version.major, version.minor, version.patch,
            build: '${buildNumber + 1}');
    }
  }
}
