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

@TestOn('vm')
@Timeout(Duration(minutes: 2))
import 'dart:async';

import 'package:dwds/src/debugging/debugger.dart';
import 'package:dwds/src/debugging/frame_computer.dart';
import 'package:dwds/src/debugging/inspector.dart';
import 'package:dwds/src/debugging/location.dart';
import 'package:dwds/src/debugging/skip_list.dart';
import 'package:logging/logging.dart';
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart' hide LogRecord;
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'
    show CallFrame, DebuggerPausedEvent, StackTrace, WipCallFrame, WipScript;

import 'fixtures/debugger_data.dart';
import 'fixtures/fakes.dart';
import 'fixtures/utilities.dart';

late AppInspector inspector;
late Debugger debugger;
late FakeWebkitDebugger webkitDebugger;
late StreamController<DebuggerPausedEvent> pausedController;
late Locations locations;
late SkipLists skipLists;

class TestStrategy extends FakeStrategy {
  TestStrategy(super.assetReader);

  @override
  Future<String> moduleForServerPath(String entrypoint, String appUri) async =>
      'foo.ddc.js';

  @override
  Future<String> serverPathForModule(String entrypoint, String module) async =>
      'foo/ddc';
}

final sourceMapContents =
    '{"version":3,"sourceRoot":"","sources":["main.dart"],"names":[],'
    '"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUwB,IAAtB,WAAM;AAKJ,'
    'IAHF,4BAAkB,aAAa,SAAC,GAAG;AACb,MAApB,WAAM;AACN,YAAgC,+CAAO,AAAK,oBAAO,'
    'yCAAC,WAAW;IAChE;AAC0D,IAA3D,AAAS,AAAK,0DAAO;AAAe,kBAAO;;;AAEvC,gBAAQ;'
    'AAGV,IAFI,kCAAqC,QAAC;AACX,MAA/B,WAAM,AAAwB,0BAAP,QAAF,AAAE,KAAK,GAAP;'
    ';EAEzB","file":"main.ddc.js"}';

final sampleSyncFrame = WipCallFrame({
  'callFrameId': '{"ordinal":0,"injectedScriptId":2}',
  'functionName': '',
  'functionLocation': {
    'scriptId': '69',
    'lineNumber': 88,
    'columnNumber': 72,
  },
  'location': {'scriptId': '69', 'lineNumber': 37, 'columnNumber': 0},
  'url': '',
  'scopeChain': [],
  'this': {'type': 'undefined'},
});

final sampleAsyncFrame = CallFrame({
  'functionName': 'myFunc',
  'url': '',
  'scriptId': '71',
  'lineNumber': 40,
  'columnNumber': 1,
});

final Map<String, WipScript> scripts = {
  '69': WipScript(<String, dynamic>{
    'url': 'http://127.0.0.1:8081/foo.ddc.js',
  }),
  '71': WipScript(<String, dynamic>{
    'url': 'http://127.0.0.1:8081/bar.ddc.js',
  }),
};

void main() async {
  setUpAll(() async {
    webkitDebugger = FakeWebkitDebugger(scripts: scripts);
    pausedController = StreamController<DebuggerPausedEvent>();
    webkitDebugger.onPaused = pausedController.stream;
    final toolConfiguration = TestToolConfiguration.withLoadStrategy(
      loadStrategy: TestStrategy(FakeAssetReader()),
    );
    setGlobalsForTesting(
      toolConfiguration: toolConfiguration,
    );
    final root = 'fakeRoot';
    locations = Locations(
      FakeAssetReader(sourceMap: sourceMapContents),
      FakeModules(),
      root,
    );
    locations.initialize('fake_entrypoint');
    skipLists = SkipLists();
    debugger = await Debugger.create(
      webkitDebugger,
      (_, __) {},
      locations,
      skipLists,
      root,
    );
    inspector = FakeInspector(webkitDebugger, fakeIsolate: simpleIsolate);
    debugger.updateInspector(inspector);
  });

  /// Test that we get expected variable values from a hard-coded
  /// stack frame.
  test('frames 1', () async {
    final stackComputer = FrameComputer(debugger, frames1);
    final frames = await stackComputer.calculateFrames();
    expect(frames, isNotNull);
    expect(frames, isNotEmpty);

    final firstFrameVars = frames[0].vars!;
    final frame1Variables = firstFrameVars.map((each) => each.name).toList();
    expect(frame1Variables, ['a', 'b']);
  });

  test('creates async frames', () async {
    final stackComputer = FrameComputer(
      debugger,
      [sampleSyncFrame],
      asyncStackTrace: StackTrace({
        'callFrames': [sampleAsyncFrame.json],
        'parent': StackTrace({
          'callFrames': [sampleAsyncFrame.json],
        }).json,
      }),
    );

    final frames = await stackComputer.calculateFrames();
    expect(frames, hasLength(5));

    expect(frames[0].kind, FrameKind.kRegular);
    expect(frames[1].kind, FrameKind.kAsyncSuspensionMarker);
    expect(frames[2].kind, FrameKind.kAsyncCausal);
    expect(frames[3].kind, FrameKind.kAsyncSuspensionMarker);
    expect(frames[4].kind, FrameKind.kAsyncCausal);
  });

  test('elides multiple async frames', () async {
    final stackComputer = FrameComputer(
      debugger,
      [sampleSyncFrame],
      asyncStackTrace: StackTrace({
        'callFrames': [sampleAsyncFrame.json],
        'parent': StackTrace({
          'callFrames': [],
          'parent': StackTrace({
            'callFrames': [sampleAsyncFrame.json],
            'parent': StackTrace({
              'callFrames': [],
            }).json,
          }).json,
        }).json,
      }),
    );

    final frames = await stackComputer.calculateFrames();
    expect(frames, hasLength(5));

    expect(frames[0].kind, FrameKind.kRegular);
    expect(frames[1].kind, FrameKind.kAsyncSuspensionMarker);
    expect(frames[2].kind, FrameKind.kAsyncCausal);
    expect(frames[3].kind, FrameKind.kAsyncSuspensionMarker);
    expect(frames[4].kind, FrameKind.kAsyncCausal);
  });

  setUp(() {
    // We need to provide an Isolate so that the code doesn't bail out on a null
    // check before it has a chance to throw.
    inspector = FakeInspector(webkitDebugger, fakeIsolate: simpleIsolate);
    debugger.updateInspector(inspector);
  });

  group('errors', () {
    setUp(() {
      // We need to provide an Isolate so that the code doesn't bail out on a null
      // check before it has a chance to throw.
      inspector = FakeInspector(webkitDebugger, fakeIsolate: simpleIsolate);
      debugger.updateInspector(inspector);
    });

    test('errors in the zone are caught and logged', () async {
      // Add a DebuggerPausedEvent with a null parameter to provoke an error.
      pausedController.sink.add(
        DebuggerPausedEvent({
          'method': '',
          'params': {
            'reason': 'other',
            'callFrames': [
              {'callFrameId': '', 'functionName': ''},
            ],
          },
        }),
      );
      expect(
        Debugger.logger.onRecord,
        emitsThrough(
          predicate(
            (LogRecord log) => log.message == 'Error calculating Dart frames',
          ),
        ),
      );
    });
  });
}
