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

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

import 'package:dwds/data/debug_event.dart';
import 'package:dwds/data/hot_reload_request.dart';
import 'package:dwds/data/hot_reload_response.dart';
import 'package:dwds/data/hot_restart_request.dart';
import 'package:dwds/data/hot_restart_response.dart';
import 'package:dwds/data/register_event.dart';
import 'package:dwds/data/service_extension_request.dart';
import 'package:dwds/data/service_extension_response.dart';
import 'package:dwds/src/connections/app_connection.dart';
import 'package:dwds/src/events.dart';
import 'package:dwds/src/services/proxy_service.dart';
import 'package:dwds/src/utilities/dart_uri.dart';
import 'package:dwds/src/utilities/shared.dart';
import 'package:logging/logging.dart';
import 'package:vm_service/vm_service.dart' as vm_service;
import 'package:vm_service/vm_service.dart';

/// Defines callbacks for sending messages to the connected client.
/// Returns the number of clients the request was successfully sent to.
typedef SendClientRequest = int Function(Object request);

const _pauseIsolatesOnStartFlag = 'pause_isolates_on_start';

/// Grace period before destroying isolate when no clients are detected.
/// This handles the race condition during page refresh where the old connection
/// closes before the new connection is established, preventing premature isolate destruction.
const _isolateDestructionGracePeriod = Duration(seconds: 15);

/// Tracks hot reload responses from multiple browser windows/tabs.
class _HotReloadTracker {
  final String requestId;
  final Completer<HotReloadResponse> completer;
  final int expectedResponses;
  final List<HotReloadResponse> responses = [];
  final Timer timeoutTimer;

  _HotReloadTracker({
    required this.requestId,
    required this.completer,
    required this.expectedResponses,
    required this.timeoutTimer,
  });

  bool get gotAllResponses => responses.length >= expectedResponses;

  void addResponse(HotReloadResponse response) {
    responses.add(response);
  }

  bool get allSuccessful => responses.every((r) => r.success);

  void dispose() {
    timeoutTimer.cancel();
  }
}

/// Tracks hot restart responses from multiple browser windows/tabs.
class _HotRestartTracker {
  final String requestId;
  final Completer<HotRestartResponse> completer;
  final int expectedResponses;
  final List<HotRestartResponse> responses = [];
  final Timer timeoutTimer;

  _HotRestartTracker({
    required this.requestId,
    required this.completer,
    required this.expectedResponses,
    required this.timeoutTimer,
  });

  bool get gotAllResponses => responses.length >= expectedResponses;

  void addResponse(HotRestartResponse response) {
    responses.add(response);
  }

  bool get allSuccessful => responses.every((r) => r.success);

  void dispose() {
    timeoutTimer.cancel();
  }
}

/// Tracks service extension responses from multiple browser windows/tabs.
class _ServiceExtensionTracker {
  final String requestId;
  final Completer<ServiceExtensionResponse> completer;
  final int expectedResponses;
  final List<ServiceExtensionResponse> responses = [];
  final Timer timeoutTimer;

  _ServiceExtensionTracker({
    required this.requestId,
    required this.completer,
    required this.expectedResponses,
    required this.timeoutTimer,
  });

  bool get gotAllResponses => responses.length >= expectedResponses;

  void addResponse(ServiceExtensionResponse response) {
    responses.add(response);
  }

  bool get allSuccessful => responses.every((r) => r.success);

  void dispose() {
    timeoutTimer.cancel();
  }
}

/// WebSocket-based VM service proxy for web debugging.
class WebSocketProxyService extends ProxyService {
  final _logger = Logger('WebSocketProxyService');

  /// Active service extension trackers by request ID.
  final Map<String, _ServiceExtensionTracker> _pendingServiceExtensionTrackers =
      {};

  /// Sends messages to the client.
  final SendClientRequest sendClientRequest;

  /// App connection for this service.
  AppConnection appConnection;

  /// Active hot reload trackers by request ID.
  final Map<String, _HotReloadTracker> _pendingHotReloads = {};

  /// Active hot restart trackers by request ID.
  final Map<String, _HotRestartTracker> _pendingHotRestarts = {};

  /// App connection cleanup subscriptions by connection instance ID.
  final Map<String, StreamSubscription<void>> _appConnectionDoneSubscriptions =
      {};

  /// Active connection count for this service.
  int _activeConnectionCount = 0;

  /// Counter for generating unique isolate IDs across page refreshes
  static int _globalIsolateIdCounter = 0;

  bool get _isIsolateRunning => _isolateRunning;

  WebSocketProxyService._(
    this.sendClientRequest,
    vm_service.VM vm,
    this.appConnection,
  ) : super(vm); // Isolate state
  vm_service.IsolateRef? _isolateRef;
  bool _isolateRunning = false;
  vm_service.Event? _currentPauseEvent;
  bool _mainHasStarted = false;

  /// Creates a new isolate for WebSocket debugging.
  @override
  Future<void> createIsolate(
    AppConnection appConnection, {
    bool newConnection = false,
  }) async {
    // Update app connection
    this.appConnection = appConnection;

    // Track this connection
    final connectionId = appConnection.request.instanceId;

    // Check if this connection is already being tracked
    final isNewConnection =
        newConnection ||
        !_appConnectionDoneSubscriptions.containsKey(connectionId);

    if (isNewConnection) {
      _activeConnectionCount++;
      _logger.fine(
        'Adding new connection: $connectionId (total: $_activeConnectionCount)',
      );
    } else {
      _logger.fine(
        'Reconnecting existing connection: $connectionId (total: $_activeConnectionCount)',
      );
    }

    // Auto-cleanup on connection close
    final existingSubscription = _appConnectionDoneSubscriptions[connectionId];
    await existingSubscription?.cancel();
    _appConnectionDoneSubscriptions[connectionId] = appConnection.onDone
        .asStream()
        .listen((_) {
          _handleConnectionClosed(connectionId);
        });

    // If we already have a running isolate, just update the connection and return
    if (_isIsolateRunning && _isolateRef != null) {
      _logger.fine(
        'Reusing existing isolate ${_isolateRef!.id} for connection: $connectionId',
      );
      return;
    }

    // Create isolate reference with unique ID
    final isolateId = '${++_globalIsolateIdCounter}';
    final isolateRef = vm_service.IsolateRef(
      id: isolateId,
      name: 'main()',
      number: isolateId,
      isSystemIsolate: false,
    );

    _isolateRef = isolateRef;
    _isolateRunning = true;
    vm.isolates?.add(isolateRef);
    final timestamp = DateTime.now().millisecondsSinceEpoch;

    _logger.fine(
      'Created new isolate: $isolateId for connection: $connectionId',
    );

    // Send lifecycle events
    _streamNotify(
      vm_service.EventStreams.kIsolate,
      vm_service.Event(
        kind: vm_service.EventKind.kIsolateStart,
        timestamp: timestamp,
        isolate: isolateRef,
      ),
    );
    _streamNotify(
      vm_service.EventStreams.kIsolate,
      vm_service.Event(
        kind: vm_service.EventKind.kIsolateRunnable,
        timestamp: timestamp,
        isolate: isolateRef,
      ),
    );

    // Send pause event if enabled
    if (pauseIsolatesOnStart) {
      final pauseEvent = vm_service.Event(
        kind: vm_service.EventKind.kPauseStart,
        timestamp: timestamp,
        isolate: isolateRef,
      );
      _currentPauseEvent = pauseEvent;
      _streamNotify(vm_service.EventStreams.kDebug, pauseEvent);
    }

    // Complete initialization after isolate is set up
    if (!initializedCompleter.isCompleted) initializedCompleter.complete();
  }

  /// Handles a connection being closed.
  void _handleConnectionClosed(String connectionId) {
    _logger.fine('Connection closed: $connectionId');

    // Only decrement if this connection was actually being tracked
    if (_appConnectionDoneSubscriptions.containsKey(connectionId)) {
      // Remove the subscription for this connection
      _appConnectionDoneSubscriptions[connectionId]?.cancel();
      _appConnectionDoneSubscriptions.remove(connectionId);

      // Decrease active connection count
      _activeConnectionCount--;
      _logger.fine(
        'Removed connection: $connectionId (remaining: $_activeConnectionCount)',
      );
      _logger.fine(
        'Current tracked connections: ${_appConnectionDoneSubscriptions.keys.toList()}',
      );

      // Instead of destroying the isolate immediately, check if there are still
      // clients that can receive hot reload requests
      if (_activeConnectionCount <= 0) {
        // Double-check by asking the sendClientRequest callback how many clients are available
        final actualClientCount = sendClientRequest({'type': 'ping'});
        _logger.fine(
          'Actual client count from sendClientRequest: $actualClientCount',
        );

        if (actualClientCount == 0) {
          _logger.fine(
            'No clients available for hot reload, scheduling isolate destruction',
          );
          // Add a delay before destroying the isolate to handle page refresh race condition
          Timer(_isolateDestructionGracePeriod, () {
            // Double-check client count again before destroying
            final finalClientCount = sendClientRequest({'type': 'ping'});
            if (finalClientCount == 0) {
              _logger.fine(
                'Final check confirmed no clients, destroying isolate',
              );
              destroyIsolate();
            } else {
              _logger.fine(
                'Final check found $finalClientCount clients, keeping isolate alive',
              );
              _activeConnectionCount = finalClientCount;
            }
          });
        } else {
          _logger.fine(
            'Still have $actualClientCount clients available, keeping isolate alive',
          );
          // Update our internal counter to match reality
          _activeConnectionCount = actualClientCount;
        }
      } else {
        _logger.fine(
          'Still have $_activeConnectionCount active connections, keeping isolate alive',
        );
      }
    } else {
      _logger.warning(
        'Attempted to close connection that was not tracked: $connectionId',
      );
    }
  }

  /// Destroys the isolate and cleans up state.
  @override
  void destroyIsolate() {
    _logger.fine('Destroying isolate');

    if (!_isIsolateRunning) {
      _logger.fine('Isolate already destroyed, ignoring');
      return;
    }

    final isolateRef = _isolateRef;

    // Cancel all connection subscriptions
    for (final subscription in _appConnectionDoneSubscriptions.values) {
      subscription.cancel();
    }
    _appConnectionDoneSubscriptions.clear();
    _activeConnectionCount = 0;

    // Send exit event
    if (isolateRef != null) {
      _streamNotify(
        vm_service.EventStreams.kIsolate,
        vm_service.Event(
          kind: vm_service.EventKind.kIsolateExit,
          timestamp: DateTime.now().millisecondsSinceEpoch,
          isolate: isolateRef,
        ),
      );
    }

    vm.isolates?.removeWhere((ref) => ref.id == isolateRef?.id);

    // Reset state
    _isolateRef = null;
    _isolateRunning = false;
    _currentPauseEvent = null;
    _mainHasStarted = false;

    if (initializedCompleter.isCompleted) {
      initializedCompleter = Completer<void>();
    }
  }

  /// Sends events to stream controllers.
  void _streamNotify(String streamId, vm_service.Event event) {
    final controller = streamControllers[streamId];
    if (controller == null) return;
    controller.add(event);
  }

  @override
  Future<Success> setLibraryDebuggable(
    String isolateId,
    String libraryId,
    bool isDebuggable,
  ) {
    return rpcNotSupportedFuture('setLibraryDebuggable');
  }

  @override
  Future<Success> setIsolatePauseMode(
    String isolateId, {
    String? exceptionPauseMode,
    bool? shouldPauseOnExit,
  }) async {
    // Not supported in WebSocket mode - return success for compatibility
    return Success();
  }

  @override
  Future<vm_service.Isolate> getIsolate(String isolateId) =>
      wrapInErrorHandlerAsync('getIsolate', () => _getIsolate(isolateId));

  Future<vm_service.Isolate> _getIsolate(String isolateId) async {
    if (!_isIsolateRunning || _isolateRef == null) {
      throw vm_service.RPCError(
        'getIsolate',
        vm_service.RPCErrorKind.kInvalidParams.code,
        'No running isolate found for id: $isolateId',
      );
    }
    if (_isolateRef!.id != isolateId) {
      throw vm_service.RPCError(
        'getIsolate',
        vm_service.RPCErrorKind.kInvalidParams.code,
        'Isolate with id $isolateId not found.',
      );
    }

    return vm_service.Isolate(
      id: _isolateRef!.id!,
      name: _isolateRef!.name,
      number: _isolateRef!.number,
      startTime: DateTime.now().millisecondsSinceEpoch,
      isSystemIsolate: _isolateRef!.isSystemIsolate,
      runnable: true,
      pauseEvent: _currentPauseEvent,
    );
  }

  /// Adds events to stream controllers.
  void addEvent(String streamId, vm_service.Event event) {
    final controller = streamControllers[streamId];
    if (controller != null && !controller.isClosed) {
      controller.add(event);
    } else {
      _logger.warning('Cannot add event to closed/missing stream: $streamId');
    }
  }

  static Future<WebSocketProxyService> create(
    SendClientRequest sendClientRequest,
    AppConnection appConnection,
  ) async {
    final vm = vm_service.VM(
      name: 'WebSocketDebugProxy',
      operatingSystem: 'web',
      startTime: DateTime.now().millisecondsSinceEpoch,
      version: 'unknown',
      isolates: [],
      isolateGroups: [],
      systemIsolates: [],
      systemIsolateGroups: [],
      targetCPU: 'Web',
      hostCPU: 'DWDS',
      architectureBits: -1,
      pid: -1,
    );
    final service = WebSocketProxyService._(
      sendClientRequest,
      vm,
      appConnection,
    );
    safeUnawaited(service.createIsolate(appConnection));
    return service;
  }

  /// Returns the root VM object.
  @override
  Future<vm_service.VM> getVM() => wrapInErrorHandlerAsync('getVM', _getVM);

  Future<vm_service.VM> _getVM() {
    return captureElapsedTime(() async {
      // Ensure the VM's isolate list is synchronized with our actual state
      if (_isIsolateRunning && _isolateRef != null) {
        // Make sure our isolate is in the VM's isolate list
        final isolateExists =
            vm.isolates?.any((ref) => ref.id == _isolateRef!.id) ?? false;
        if (!isolateExists) {
          vm.isolates?.add(_isolateRef!);
        }
      } else {
        // If no isolate is running, make sure the list is empty
        vm.isolates?.clear();
      }

      return vm;
    }, (result) => DwdsEvent.getVM());
  }

  /// Not available in WebSocket mode.
  dynamic get remoteDebugger {
    throw UnsupportedError(
      'remoteDebugger not available in WebSocketProxyService.\n'
      'Called from:\n${StackTrace.current}',
    );
  }

  @override
  Future<vm_service.ReloadReport> reloadSources(
    String isolateId, {
    bool? force,
    bool? pause,
    String? rootLibUri,
    String? packagesUri,
  }) async {
    _logger.info('Attempting a hot reload');
    try {
      await _performWebSocketHotReload();
      _logger.info('Hot reload completed successfully');
      return _ReloadReportWithMetadata(success: true);
    } catch (e) {
      _logger.warning('Hot reload failed: $e');
      return _ReloadReportWithMetadata(success: false, notices: [e.toString()]);
    }
  }

  /// Handles hot restart requests.
  Future<Map<String, dynamic>> hotRestart() async {
    _logger.info('Attempting a hot restart');

    try {
      await _performWebSocketHotRestart();
      _logger.info('Hot restart completed successfully');
      return {'result': vm_service.Success().toJson()};
    } catch (e) {
      _logger.warning('Hot restart failed: $e');
      return {
        'error': {
          'code': vm_service.RPCErrorKind.kInternalError.code,
          'message': 'Hot restart failed: $e',
        },
      };
    }
  }

  /// Completes hot reload with response from client.
  @override
  void completeHotReload(HotReloadResponse response) {
    final tracker = _pendingHotReloads[response.id];

    if (tracker == null) {
      _logger.warning(
        'Received hot reload response but no pending tracker found (id: ${response.id})',
      );
      return;
    }

    tracker.addResponse(response);

    if (tracker.gotAllResponses) {
      _pendingHotReloads.remove(response.id);
      tracker.dispose();

      if (tracker.allSuccessful) {
        tracker.completer.complete(response);
      } else {
        final failedResponses = tracker.responses.where((r) => !r.success);
        final errorMessages = failedResponses
            .map((r) => r.errorMessage ?? 'Unknown error')
            .join('; ');
        tracker.completer.completeError(
          'Hot reload failed in some clients: $errorMessages',
        );
      }
    }
  }

  /// Completes hot restart with response from client.
  @override
  void completeHotRestart(HotRestartResponse response) {
    final tracker = _pendingHotRestarts[response.id];

    if (tracker == null) {
      _logger.warning(
        'Received hot restart response but no pending tracker found (id: ${response.id})',
      );
      return;
    }

    tracker.addResponse(response);

    if (tracker.gotAllResponses) {
      _pendingHotRestarts.remove(response.id);
      tracker.dispose();

      if (tracker.allSuccessful) {
        tracker.completer.complete(response);
      } else {
        final failedResponses = tracker.responses.where((r) => !r.success);
        final errorMessages = failedResponses
            .map((r) => r.errorMessage ?? 'Unknown error')
            .join('; ');
        tracker.completer.completeError(
          'Hot restart failed in some clients: $errorMessages',
        );
      }
    }
  }

  /// Performs WebSocket-based hot reload.
  Future<void> _performWebSocketHotReload({String? requestId}) async {
    final id = requestId ?? createId();

    // Check if there's already a pending hot reload with this ID
    if (_pendingHotReloads.containsKey(id)) {
      throw StateError('Hot reload already pending for ID: $id');
    }

    const timeout = Duration(seconds: 10);
    _logger.info('Sending HotReloadRequest with ID ($id) to client');

    // Send the request and get the number of connected clients
    final clientCount = await Future.microtask(() {
      return sendClientRequest(HotReloadRequest((b) => b.id = id));
    });

    if (clientCount == 0) {
      throw StateError('No clients available for hot reload');
    }

    // Create tracker for this hot reload request
    final completer = Completer<HotReloadResponse>();
    final timeoutTimer = Timer(timeout, () {
      final tracker = _pendingHotReloads.remove(id);
      if (tracker != null) {
        tracker.dispose();
        if (!completer.isCompleted) {
          completer.completeError(
            TimeoutException(
              'Hot reload timed out - received ${tracker.responses.length}/$clientCount responses',
              timeout,
            ),
          );
        }
      }
    });

    final tracker = _HotReloadTracker(
      requestId: id,
      completer: completer,
      expectedResponses: clientCount,
      timeoutTimer: timeoutTimer,
    );

    _pendingHotReloads[id] = tracker;

    try {
      final response = await completer.future;
      if (!response.success) {
        throw Exception(response.errorMessage ?? 'Client reported failure');
      }
    } catch (e) {
      // Clean up tracker if still present
      final remainingTracker = _pendingHotReloads.remove(id);
      remainingTracker?.dispose();
      rethrow;
    }
  }

  /// Performs WebSocket-based hot restart.
  Future<void> _performWebSocketHotRestart({String? requestId}) async {
    final id = requestId ?? createId();

    // Check if there's already a pending hot restart with this ID
    if (_pendingHotRestarts.containsKey(id)) {
      throw StateError('Hot restart already pending for ID: $id');
    }

    const timeout = Duration(seconds: 15);
    _logger.info('Sending HotRestartRequest with ID ($id) to client');

    // Send the request and get the number of connected clients
    final clientCount = await Future.microtask(() {
      return sendClientRequest(HotRestartRequest((b) => b.id = id));
    });

    if (clientCount == 0) {
      throw StateError('No clients available for hot restart');
    }

    // Create tracker for this hot restart request
    final completer = Completer<HotRestartResponse>();
    final timeoutTimer = Timer(timeout, () {
      final tracker = _pendingHotRestarts.remove(id);
      if (tracker != null) {
        tracker.dispose();
        if (!completer.isCompleted) {
          completer.completeError(
            TimeoutException(
              'Hot restart timed out - received ${tracker.responses.length}/$clientCount responses',
              timeout,
            ),
          );
        }
      }
    });

    final tracker = _HotRestartTracker(
      requestId: id,
      completer: completer,
      expectedResponses: clientCount,
      timeoutTimer: timeoutTimer,
    );

    _pendingHotRestarts[id] = tracker;

    try {
      final response = await completer.future;
      if (!response.success) {
        throw Exception(response.errorMessage ?? 'Client reported failure');
      }
    } catch (e) {
      // Clean up tracker if still present
      final remainingTracker = _pendingHotRestarts.remove(id);
      remainingTracker?.dispose();
      rethrow;
    }
  }

  @override
  Future<Response> callServiceExtension(
    String method, {
    String? isolateId,
    Map? args,
  }) => wrapInErrorHandlerAsync(
    'callServiceExtension',
    () => _callServiceExtension(method, args: args),
  );

  /// Calls a service extension on the client.
  Future<Response> _callServiceExtension(String method, {Map? args}) async {
    final requestId = createId();

    // Check if there's already a pending service extension with this ID
    if (_pendingServiceExtensionTrackers.containsKey(requestId)) {
      throw StateError(
        'Service extension call already pending for ID: $requestId',
      );
    }

    final request = ServiceExtensionRequest.fromArgs(
      id: requestId,
      method: method,
      args:
          args != null ? Map<String, dynamic>.from(args) : <String, dynamic>{},
    );

    // Send the request and get the number of connected clients
    final clientCount = sendClientRequest(request);

    if (clientCount == 0) {
      throw StateError('No clients available for service extension');
    }

    // Create tracker for this service extension request
    const timeout = Duration(seconds: 10);
    final completer = Completer<ServiceExtensionResponse>();
    final timeoutTimer = Timer(timeout, () {
      final tracker = _pendingServiceExtensionTrackers.remove(requestId);
      if (tracker != null) {
        tracker.dispose();
        if (!completer.isCompleted) {
          completer.completeError(
            TimeoutException(
              'Service extension $method timed out - received ${tracker.responses.length}/$clientCount responses',
              timeout,
            ),
          );
        }
      }
    });

    final tracker = _ServiceExtensionTracker(
      requestId: requestId,
      completer: completer,
      expectedResponses: clientCount,
      timeoutTimer: timeoutTimer,
    );

    _pendingServiceExtensionTrackers[requestId] = tracker;

    try {
      final response = await completer.future;

      if (response.errorMessage != null) {
        throw RPCError(
          method,
          response.errorCode ?? RPCErrorKind.kServerError.code,
          response.errorMessage!,
        );
      }
      return Response()..json = response.result;
    } catch (e) {
      // Clean up tracker if still present
      final remainingTracker = _pendingServiceExtensionTrackers.remove(
        requestId,
      );
      remainingTracker?.dispose();
      rethrow;
    }
  }

  /// Completes service extension with response.
  @override
  void completeServiceExtension(ServiceExtensionResponse response) {
    final id = response.id;

    final tracker = _pendingServiceExtensionTrackers[id];

    if (tracker == null) {
      _logger.warning(
        'No pending tracker found for service extension (id: $id)',
      );
      return;
    }

    tracker.addResponse(response);

    if (tracker.gotAllResponses) {
      _pendingServiceExtensionTrackers.remove(id);
      tracker.dispose();

      if (tracker.allSuccessful) {
        tracker.completer.complete(response);
      } else {
        final failedResponses = tracker.responses.where((r) => !r.success);
        final errorMessages = failedResponses
            .map((r) => r.errorMessage ?? 'Unknown error')
            .join('; ');
        tracker.completer.completeError(
          'Service extension failed in some clients: $errorMessages',
        );
      }
    }
  }

  /// Parses the [RegisterEvent] and emits a corresponding Dart VM Service
  /// protocol [Event].
  @override
  void parseRegisterEvent(RegisterEvent registerEvent) {
    if (!_isIsolateRunning || _isolateRef == null) {
      _logger.warning('Cannot register service extension - no isolate running');
      return;
    }

    final service = registerEvent.eventData;

    // Emit ServiceExtensionAdded event for tooling
    final event = vm_service.Event(
      kind: vm_service.EventKind.kServiceExtensionAdded,
      timestamp: DateTime.now().millisecondsSinceEpoch,
      isolate: _isolateRef!,
    );
    event.extensionRPC = service;

    _streamNotify(vm_service.EventStreams.kIsolate, event);
  }

  /// Parses the [BatchedDebugEvents] and emits corresponding Dart VM Service
  /// protocol [Event]s.
  @override
  void parseBatchedDebugEvents(BatchedDebugEvents debugEvents) {
    for (final debugEvent in debugEvents.events) {
      parseDebugEvent(debugEvent);
    }
  }

  /// Parses the [DebugEvent] and emits a corresponding Dart VM Service
  /// protocol [Event].
  @override
  void parseDebugEvent(DebugEvent debugEvent) {
    if (!_isIsolateRunning || _isolateRef == null) {
      _logger.warning('Cannot parse debug event - no isolate running');
      return;
    }

    _streamNotify(
      vm_service.EventStreams.kExtension,
      vm_service.Event(
          kind: vm_service.EventKind.kExtension,
          timestamp: DateTime.now().millisecondsSinceEpoch,
          isolate: _isolateRef!,
        )
        ..extensionKind = debugEvent.kind
        ..extensionData = vm_service.ExtensionData.parse(
          jsonDecode(debugEvent.eventData) as Map<String, dynamic>,
        ),
    );
  }

  @override
  Future<Success> setFlag(String name, String value) =>
      wrapInErrorHandlerAsync('setFlag', () => _setFlag(name, value));

  Future<Success> _setFlag(String name, String value) async {
    if (!currentVmServiceFlags.containsKey(name)) {
      return rpcNotSupportedFuture('setFlag');
    }

    assert(value == 'true' || value == 'false');
    final oldValue = currentVmServiceFlags[name];
    currentVmServiceFlags[name] = value == 'true';

    // Handle pause_isolates_on_start flag changes
    if (name == _pauseIsolatesOnStartFlag &&
        value == 'true' &&
        oldValue == false) {
      // Send pause event for existing isolate if not already paused
      if (_isIsolateRunning &&
          _isolateRef != null &&
          _currentPauseEvent == null) {
        final pauseEvent = vm_service.Event(
          kind: vm_service.EventKind.kPauseStart,
          timestamp: DateTime.now().millisecondsSinceEpoch,
          isolate: _isolateRef!,
        );
        _currentPauseEvent = pauseEvent;
        _streamNotify(vm_service.EventStreams.kDebug, pauseEvent);
      }
    }

    return Success();
  }

  @override
  Future<UriList> lookupResolvedPackageUris(
    String isolateId,
    List<String> uris, {
    bool? local,
  }) => wrapInErrorHandlerAsync(
    'lookupResolvedPackageUris',
    () => _lookupResolvedPackageUris(isolateId, uris),
  );

  Future<UriList> _lookupResolvedPackageUris(
    String _,
    List<String> uris,
  ) async {
    await isInitialized;
    return UriList(uris: uris.map(DartUri.toResolvedUri).toList());
  }

  /// Pauses execution of the isolate.
  @override
  Future<Success> pause(String isolateId) =>
      wrapInErrorHandlerAsync('pause', () => _pause(isolateId));

  Future<Success> _pause(String _) async {
    // Create a pause event and store it
    if (_isolateRef != null) {
      final pauseEvent = vm_service.Event(
        kind: vm_service.EventKind.kPauseInterrupted,
        timestamp: DateTime.now().millisecondsSinceEpoch,
        isolate: _isolateRef!,
      );
      _currentPauseEvent = pauseEvent;
      _streamNotify(vm_service.EventStreams.kDebug, pauseEvent);
    }

    return Success();
  }

  /// Resumes execution of the isolate.
  @override
  Future<Success> resume(String isolateId, {String? step, int? frameIndex}) =>
      wrapInErrorHandlerAsync('resume', () => _resume(isolateId));

  Future<Success> _resume(String isolateId) async {
    if (hasPendingRestart && !resumeAfterRestartEventsController.isClosed) {
      resumeAfterRestartEventsController.add(isolateId);
    } else {
      if (!_mainHasStarted) {
        try {
          appConnection.runMain();
          _mainHasStarted = true;
        } catch (e) {
          if (e.toString().contains('Main has already started')) {
            _mainHasStarted = true;
          } else {
            rethrow;
          }
        }
      }
    }

    // Clear pause state and send resume event to notify debugging tools
    if (_currentPauseEvent != null && _isolateRef != null) {
      _currentPauseEvent = null;
      final resumeEvent = vm_service.Event(
        kind: vm_service.EventKind.kResume,
        timestamp: DateTime.now().millisecondsSinceEpoch,
        isolate: _isolateRef!,
      );
      _streamNotify(vm_service.EventStreams.kDebug, resumeEvent);
    }

    return Success();
  }

  @override
  Future<UriList> lookupPackageUris(String isolateId, List<String> uris) =>
      wrapInErrorHandlerAsync(
        'lookupPackageUris',
        () => _lookupPackageUris(isolateId, uris),
      );

  Future<UriList> _lookupPackageUris(String _, List<String> uris) async {
    await isInitialized;
    return UriList(uris: uris.map(DartUri.toPackageUri).toList());
  }

  @override
  Future<Success> registerService(String service, String alias) {
    return rpcNotSupportedFuture('registerService');
  }

  @override
  Future<FlagList> getFlagList() =>
      wrapInErrorHandlerAsync('getFlagList', _getFlagList);

  Future<FlagList> _getFlagList() async {
    // Return basic flag list for WebSocket mode
    return FlagList(
      flags: [
        Flag(
          name: _pauseIsolatesOnStartFlag,
          comment: 'If enabled, isolates are paused on start',
          valueAsString: pauseIsolatesOnStart.toString(),
        ),
      ],
    );
  }

  @override
  Future<vm_service.Stack> getStack(
    String isolateId, {
    String? idZoneId,
    int? limit,
  }) => wrapInErrorHandlerAsync('getStack', () => _getStack(isolateId));

  Future<vm_service.Stack> _getStack(String isolateId) async {
    if (!_isIsolateRunning || _isolateRef == null) {
      throw vm_service.RPCError(
        'getStack',
        vm_service.RPCErrorKind.kInvalidParams.code,
        'No running isolate found for id: $isolateId',
      );
    }
    if (_isolateRef!.id != isolateId) {
      throw vm_service.RPCError(
        'getStack',
        vm_service.RPCErrorKind.kInvalidParams.code,
        'Isolate with id $isolateId not found.',
      );
    }

    // Return empty stack since we're in WebSocket mode without Chrome debugging
    return vm_service.Stack(
      frames: [],
      asyncCausalFrames: [],
      awaiterFrames: [],
    );
  }
}

/// Extended ReloadReport that includes additional metadata in JSON output.
class _ReloadReportWithMetadata extends vm_service.ReloadReport {
  final List<String>? notices;
  _ReloadReportWithMetadata({super.success, this.notices});

  @override
  Map<String, dynamic> toJson() {
    final jsonified = <String, Object?>{
      'type': 'ReloadReport',
      'success': success ?? false,
    };
    if (notices != null) {
      jsonified['notices'] = notices!.map((e) => {'message': e}).toList();
    }
    return jsonified;
  }
}
