// Copyright 2014 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 'dart:io';

import 'package:process/process.dart';

import './globals.dart';

/// A wrapper around git process calls that can be mocked for unit testing.
class Git {
  const Git(this.processManager);

  final ProcessManager processManager;

  Future<String> getOutput(
    List<String> args,
    String explanation, {
    required String workingDirectory,
    bool allowFailures = false,
  }) async {
    final ProcessResult result = await _run(args, workingDirectory);
    if (result.exitCode == 0) {
      return stdoutToString(result.stdout);
    }
    _reportFailureAndExit(args, workingDirectory, result, explanation);
  }

  Future<int> run(
    List<String> args,
    String explanation, {
    bool allowNonZeroExitCode = false,
    required String workingDirectory,
  }) async {
    late final ProcessResult result;
    try {
      result = await _run(args, workingDirectory);
    } on ProcessException {
      _reportFailureAndExit(args, workingDirectory, result, explanation);
    }
    if (result.exitCode != 0 && !allowNonZeroExitCode) {
      _reportFailureAndExit(args, workingDirectory, result, explanation);
    }
    return result.exitCode;
  }

  Future<ProcessResult> _run(List<String> args, String workingDirectory) async {
    return processManager.run(
      <String>['git', ...args],
      workingDirectory: workingDirectory,
      environment: <String, String>{'GIT_TRACE': '1'},
    );
  }

  Never _reportFailureAndExit(
    List<String> args,
    String workingDirectory,
    ProcessResult result,
    String explanation,
  ) {
    final StringBuffer message = StringBuffer();
    if (result.exitCode != 0) {
      message.writeln(
        'Command "git ${args.join(' ')}" failed in directory "$workingDirectory" to '
        '$explanation. Git exited with error code ${result.exitCode}.',
      );
    } else {
      message.writeln('Command "git ${args.join(' ')}" failed to $explanation.');
    }
    if ((result.stdout as String).isNotEmpty) {
      message.writeln('stdout from git:\n${result.stdout}\n');
    }
    if ((result.stderr as String).isNotEmpty) {
      message.writeln('stderr from git:\n${result.stderr}\n');
    }
    throw GitException(message.toString(), args);
  }
}

enum GitExceptionType {
  /// Git push failed because the remote branch contained commits the local did
  /// not.
  ///
  /// Either the local branch was wrong, and needs a rebase before pushing
  /// again, or the remote branch needs to be overwritten with a force push.
  ///
  /// Example output:
  ///
  /// ```
  /// To github.com:user/engine.git
  ///
  ///  ! [rejected]            HEAD -> cherrypicks-flutter-2.8-candidate.3 (non-fast-forward)
  /// error: failed to push some refs to 'github.com:user/engine.git'
  /// hint: Updates were rejected because the tip of your current branch is behind
  /// hint: its remote counterpart. Integrate the remote changes (e.g.
  /// hint: 'git pull ...') before pushing again.
  /// hint: See the 'Note about fast-forwards' in 'git push --help' for details.
  /// ```
  PushRejected,
}

/// An exception created because a git subprocess failed.
///
/// Known git failures will be assigned a [GitExceptionType] in the [type]
/// field. If this field is null it means and unknown git failure.
class GitException implements Exception {
  GitException(this.message, this.args) {
    if (_pushRejectedPattern.hasMatch(message)) {
      type = GitExceptionType.PushRejected;
    } else {
      // because type is late final, it must be explicitly set before it is
      // accessed.
      type = null;
    }
  }

  static final RegExp _pushRejectedPattern = RegExp(
    r'Updates were rejected because the tip of your current branch is behind',
  );

  final String message;
  final List<String> args;
  late final GitExceptionType? type;

  @override
  String toString() => 'Exception on command "${args.join(' ')}": $message';
}
