import 'dart:io';

import 'package:flutter_test/flutter_test.dart';

void main() {
  test(
    'version CLI resolves tags and pubspec fallback',
    () async {
      final project = await Directory.systemTemp.createTemp(
        'smplayer-version-',
      );
      addTearDown(() => project.delete(recursive: true));
      await File(
        '${project.path}/pubspec.yaml',
      ).writeAsString('version: 1.2.3+4\n');

      await _git(project.path, ['init', '-q']);
      await _git(project.path, ['config', 'user.email', 'test@example.com']);
      await _git(project.path, ['config', 'user.name', 'Version Test']);
      await _git(project.path, ['add', 'pubspec.yaml']);
      await _git(project.path, ['commit', '-qm', 'initial']);
      await _git(project.path, ['tag', 'v1.9.9']);
      await _git(project.path, ['tag', 'v1.10.0']);

      expect(await _run(project.path, ['current', 'pc']), '1.10.0');
      expect(await _run(project.path, ['current', 'macos']), '1.10.0');
      expect(await _run(project.path, ['current', 'android']), '1.2.3');
      expect(
        await _run(project.path, ['next', 'windows']),
        'windows 1.10.1 v1.10.0',
      );
      expect(
        await _run(project.path, ['next', 'android']),
        'android 1.2.3 pubspec:1.2.3',
      );
      expect(await _run(project.path, ['build-number', '1.2.3+4']), '1002003');
      expect(
        await _run(project.path, ['tag', 'both', '--dry-run']),
        '[windows] v1.10.0 -> v1.10.1\n'
        '  DryRun: skip create/push.\n'
        '[android] pubspec:1.2.3 -> android-v1.2.3\n'
        '  DryRun: skip create/push.',
      );
    },
    timeout: const Timeout(Duration(minutes: 2)),
  );
}

Future<String> _run(String projectRoot, List<String> arguments) async {
  final result = await Process.run(_dartExecutablePath(), [
    File('scripts/version.dart').absolute.path,
    ...arguments,
    '--project-root',
    projectRoot,
  ]);
  expect(result.exitCode, 0, reason: '${result.stderr}');
  return '${result.stdout}'.trim();
}

String _dartExecutablePath() {
  final resolvedExecutable = File(Platform.resolvedExecutable);
  final executableName = resolvedExecutable.uri.pathSegments.last.toLowerCase();
  if (!executableName.startsWith('flutter_tester')) {
    return resolvedExecutable.path;
  }

  var flutterRoot = resolvedExecutable.parent;
  for (var parentLevel = 0; parentLevel < 5; parentLevel++) {
    flutterRoot = flutterRoot.parent;
  }
  final executableFileName = Platform.isWindows ? 'dart.exe' : 'dart';
  return File(
    '${flutterRoot.path}${Platform.pathSeparator}bin${Platform.pathSeparator}'
    'cache${Platform.pathSeparator}dart-sdk${Platform.pathSeparator}bin'
    '${Platform.pathSeparator}$executableFileName',
  ).path;
}

Future<void> _git(String projectRoot, List<String> arguments) async {
  final result = await Process.run(
    'git',
    arguments,
    workingDirectory: projectRoot,
  );
  expect(result.exitCode, 0, reason: '${result.stderr}');
}
