// Copyright (c) 2023, 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.

@Tags(['daily'])
@Timeout(Duration(minutes: 3))
library;

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:path/path.dart' as p;
import 'package:test/test.dart';

// TODO(elliette): Move to a cron job. This tests that the currently published
// Webdev can be activated and serve a web app. It is intended to catch any
// regressions due to changes in the Dart SDK.

enum StreamType { stdout, stderr }

const processTimeout = Duration(minutes: 1);

void main() {
  Process? createProcess;
  Process? activateProcess;
  Process? serveProcess;
  Directory? tempDir0;

  final testScript = File(
    p.join(p.dirname(Platform.script.toFilePath()), 'test.dart'),
  ).readAsStringSync();
  final thisScript = File.fromUri(
    Uri.parse(
      testScript.substring(
        testScript.lastIndexOf('import', testScript.indexOf('as test;')) + 8,
        testScript.indexOf('as test;') - 2,
      ),
    ),
  );
  final packageDir = p.dirname(p.dirname(thisScript.path));

  Future<void> expectStdoutAndCleanExit(
    Process process, {
    required String expectedStdout,
  }) async {
    final stdoutCompleter = _captureOutput(
      process,
      streamType: StreamType.stdout,
      stopCaptureFuture: process.exitCode,
    );
    final stderrCompleter = _captureOutput(
      process,
      streamType: StreamType.stderr,
      stopCaptureFuture: process.exitCode,
    );
    final exitCode = await _waitForExitOrTimeout(process);
    final stderrLogs = await stderrCompleter.future;
    final stdoutLogs = await stdoutCompleter.future;
    expect(
      exitCode,
      equals(0),
      // Include the stderr and stdout logs if the process does not terminate
      // cleanly:
      reason: 'stderr: $stderrLogs, stdout: $stdoutLogs',
    );
    expect(stderrLogs, isEmpty);
    expect(stdoutLogs, contains(expectedStdout));
  }

  Future<void> expectStdoutThenExit(
    Process process, {
    required String expectedStdout,
  }) async {
    final expectedStdoutCompleter = _waitForStdoutOrTimeout(
      process,
      expectedStdout: expectedStdout,
    );
    final stderrCompleter = _captureOutput(
      process,
      streamType: StreamType.stderr,
      stopCaptureFuture: expectedStdoutCompleter.future,
    );
    final stdoutLogs = await expectedStdoutCompleter.future;
    final stderrLogs = await stderrCompleter.future;
    expect(
      stdoutLogs,
      contains(expectedStdout),
      // Also include the stderr if the stdout is not expected.
      reason: 'stderr: $stderrLogs',
    );
  }

  setUp(() async {
    tempDir0 = Directory.systemTemp.createTempSync('installation_test');

    await Process.run('dart', ['pub', 'global', 'deactivate', 'webdev']);
  });

  tearDown(() async {
    // Kill any stale processes:
    if (createProcess != null) {
      Process.killPid(createProcess!.pid, ProcessSignal.sigint);
      createProcess = null;
    }
    if (activateProcess != null) {
      Process.killPid(activateProcess!.pid, ProcessSignal.sigint);
      activateProcess = null;
    }
    if (serveProcess != null) {
      Process.killPid(serveProcess!.pid, ProcessSignal.sigint);
      serveProcess = null;
    }
  });

  test('can activate and serve webdev', () async {
    final tempDir = tempDir0!;
    final tempPath = tempDir.path;

    // Verify that we can create a new Dart app:
    createProcess = await Process.start('dart', [
      'create',
      '--template',
      'web',
      'temp_app',
    ], workingDirectory: tempPath);
    await expectStdoutAndCleanExit(
      createProcess!,
      expectedStdout: 'Created project temp_app in temp_app!',
    );
    final appPath = p.join(tempPath, 'temp_app');
    expect(await Directory(appPath).exists(), isTrue);

    // Verify that `dart pub global activate` works:
    activateProcess = await Process.start('dart', [
      'pub',
      'global',
      'activate',
      'webdev',
    ]);
    await expectStdoutAndCleanExit(
      activateProcess!,
      expectedStdout: 'Activated webdev',
    );

    // Verify that `webdev serve` works for our new app:
    serveProcess = await Process.start('dart', [
      'pub',
      'global',
      'run',
      'webdev',
      'serve',
    ], workingDirectory: appPath);
    await expectStdoutThenExit(
      serveProcess!,
      expectedStdout: 'Serving `web` on',
    );
  });

  test('activate and serve webdev fails with offline', () async {
    final tempDir = tempDir0!;
    final tempPath = tempDir.path;

    // Verify that we can create a new Dart app:
    createProcess = await Process.start('dart', [
      'create',
      '--no-pub',
      '--template',
      'web',
      'temp_app',
    ], workingDirectory: tempPath);
    await expectStdoutAndCleanExit(
      createProcess!,
      expectedStdout: 'Created project temp_app in temp_app!',
    );
    final appPath = p.join(tempPath, 'temp_app');
    expect(await Directory(appPath).exists(), isTrue);

    // Verify that `dart pub global activate` works:
    activateProcess = await Process.start('dart', [
      'pub',
      'global',
      'activate',
      '--source',
      'path',
      packageDir,
    ]);
    await expectStdoutAndCleanExit(
      activateProcess!,
      expectedStdout: 'Activated webdev',
    );

    // Verify that `webdev serve` works for our new app:
    serveProcess = await Process.start('dart', [
      'pub',
      'global',
      'run',
      'webdev',
      'serve',
      '--offline',
      'web:8081',
    ], workingDirectory: appPath);
    await expectStdoutThenExit(
      serveProcess!,
      expectedStdout: 'Cannot open file\n  pubspec.lock\n',
    );
  });
}

Future<int> _waitForExitOrTimeout(Process process) {
  Timer(processTimeout, () {
    process.kill(ProcessSignal.sigint);
  });
  return process.exitCode;
}

/// Returns the stdout for the [process] once the [expectedStdout] is found.
///
/// Otherwise returns all the stdout up to the [processTimeout].
Completer<String> _waitForStdoutOrTimeout(
  Process process, {
  required String expectedStdout,
}) {
  var output = '';
  final completer = Completer<String>();

  Timer(processTimeout, () {
    process.kill(ProcessSignal.sigint);
    if (!completer.isCompleted) {
      completer.complete(output);
    }
  });
  process.stdout.transform(utf8.decoder).listen((line) {
    output += line;
    if (line.contains(expectedStdout)) {
      process.kill(ProcessSignal.sigint);
      if (!completer.isCompleted) {
        completer.complete(output);
      }
    }
  });

  return completer;
}

Completer<String> _captureOutput(
  Process process, {
  required StreamType streamType,
  required Future stopCaptureFuture,
}) {
  final stream = streamType == StreamType.stdout
      ? process.stdout
      : process.stderr;
  final completer = Completer<String>();
  var output = '';
  stream.transform(utf8.decoder).listen((line) {
    output += line;
    if (line.contains('[SEVERE]')) {
      process.kill(ProcessSignal.sigint);
      if (!completer.isCompleted) {
        completer.complete(output);
      }
    }
  });
  unawaited(
    stopCaptureFuture.then((_) {
      if (!completer.isCompleted) {
        completer.complete(output);
      }
    }),
  );
  return completer;
}
