// 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 && !state.needsChangelogChange) {
        return PackageResult.skip('No non-exempt 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}');
    }
  }
}
