// 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.

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

import 'package:collection/collection.dart';
import 'package:dds/dds_launcher.dart';
import 'package:dwds/data/build_result.dart';
import 'package:dwds/data/connect_request.dart';
import 'package:dwds/data/debug_event.dart';
import 'package:dwds/data/devtools_request.dart';
import 'package:dwds/data/error_response.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/isolate_events.dart';
import 'package:dwds/data/register_event.dart';
import 'package:dwds/data/run_request.dart';
import 'package:dwds/data/service_extension_request.dart';
import 'package:dwds/data/service_extension_response.dart';
import 'package:dwds/src/config/tool_configuration.dart';
import 'package:dwds/src/connections/app_connection.dart';
import 'package:dwds/src/connections/debug_connection.dart';
import 'package:dwds/src/debugging/execution_context.dart';
import 'package:dwds/src/debugging/remote_debugger.dart';
import 'package:dwds/src/debugging/webkit_debugger.dart';
import 'package:dwds/src/dwds_vm_client.dart';
import 'package:dwds/src/events.dart';
import 'package:dwds/src/handlers/injector.dart';
import 'package:dwds/src/handlers/socket_connections.dart';
import 'package:dwds/src/readers/asset_reader.dart';
import 'package:dwds/src/servers/devtools.dart';
import 'package:dwds/src/servers/extension_backend.dart';
import 'package:dwds/src/servers/extension_debugger.dart';
import 'package:dwds/src/services/app_debug_services.dart';
import 'package:dwds/src/services/chrome/chrome_debug_service.dart';
import 'package:dwds/src/services/chrome/chrome_proxy_service.dart';
import 'package:dwds/src/services/expression_compiler.dart';
import 'package:dwds/src/services/web_socket/web_socket_debug_service.dart';
import 'package:dwds/src/services/web_socket/web_socket_proxy_service.dart';
import 'package:dwds/src/utilities/shared.dart';
import 'package:logging/logging.dart';
import 'package:shelf/shelf.dart';
import 'package:sse/server/sse_handler.dart';
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';

/// When enabled, this logs VM service protocol and Chrome debug protocol
/// traffic to disk.
///
/// Note: this should not be checked in enabled.
const _enableLogging = false;

final _logger = Logger('DevHandler');

/// SSE handler to enable development features like hot reload and
/// opening DevTools.
class DevHandler {
  final _subs = <StreamSubscription>[];
  final _sseHandlers = <String, SocketHandler>{};
  final _injectedConnections = <SocketConnection>{};
  final DevTools? _devTools;
  final AssetReader _assetReader;
  final String _hostname;
  final _connectedApps = StreamController<AppConnection>.broadcast();
  final _servicesByAppId = <String, AppDebugServices>{};
  final _appConnectionByAppId = <String, AppConnection>{};
  final Stream<BuildResult> buildResults;
  final Future<ChromeConnection> Function() _chromeConnection;
  final ExtensionBackend? _extensionBackend;
  final StreamController<DebugConnection> extensionDebugConnections =
      StreamController<DebugConnection>();
  final UrlEncoder? _urlEncoder;
  final bool _useSseForDebugProxy;
  final bool _useSseForInjectedClient;
  final DartDevelopmentServiceConfiguration _ddsConfig;
  final bool _launchDevToolsInNewWindow;
  final ExpressionCompiler? _expressionCompiler;
  final DwdsInjector _injected;

  /// Null until [close] is called.
  ///
  /// All subsequent calls to [close] will return this future.
  Future<void>? _closed;

  Stream<AppConnection> get connectedApps => _connectedApps.stream;

  final bool useWebSocketConnection;

  final Duration? sseIgnoreDisconnect;

  DevHandler(
    this._chromeConnection,
    this.buildResults,
    this._devTools,
    this._assetReader,
    this._hostname,
    this._extensionBackend,
    this._urlEncoder,
    this._useSseForDebugProxy,
    this._useSseForInjectedClient,
    this._expressionCompiler,
    this._injected,

    this._ddsConfig,
    this._launchDevToolsInNewWindow, {
    this.useWebSocketConnection = false,
    this.sseIgnoreDisconnect,
  }) {
    _subs.add(buildResults.listen(_emitBuildResults));
    _listen();
    if (_extensionBackend != null) {
      _listenForDebugExtension();
    }
  }

  Handler get handler => (request) async {
    final path = request.requestedUri.path;
    final sseHandler = _sseHandlers[path];
    if (sseHandler != null) {
      return sseHandler.handler(request);
    }
    return Response.notFound('');
  };

  Future<void> close() => _closed ??= () async {
    await Future.wait([for (final sub in _subs) sub.cancel()]);
    for (final handler in _sseHandlers.values) {
      handler.shutdown();
    }
    await Future.wait(
      _servicesByAppId.values.map((service) => service.close()),
    );
    _servicesByAppId.clear();
  }();

  void _emitBuildResults(BuildResult result) {
    if (result.status != BuildStatus.succeeded) return;
    for (final injectedConnection in _injectedConnections) {
      injectedConnection.sink.add(jsonEncode(_serializeMessage(result)));
    }
  }

  /// Serializes an outgoing request to the injected client.
  /// For plain Dart types (converted away from built_value), emit the
  /// wire format `[TypeName, json]`.
  Object? _serializeMessage(Object request) {
    return switch (request) {
      ConnectRequest() => ['ConnectRequest', request.toJson()],
      RunRequest() => ['RunRequest', request.toJson()],
      HotReloadRequest() => ['HotReloadRequest', request.toJson()],
      HotRestartRequest() => ['HotRestartRequest', request.toJson()],
      ServiceExtensionRequest() => [
        'ServiceExtensionRequest',
        request.toJson(),
      ],
      BuildResult() => ['BuildResult', request.toJson()],
      DebugEvent() => ['DebugEvent', request.toJson()],
      BatchedDebugEvents() => ['BatchedDebugEvents', request.toJson()],
      DevToolsResponse() => request,
      IsolateStart() => ['IsolateStart', request.toJson()],
      IsolateExit() => ['IsolateExit', request.toJson()],
      ErrorResponse() => ['ErrorResponse', request.toJson()],
      RegisterEvent() => ['RegisterEvent', request.toJson()],
      Map() => request, // Already a raw message (e.g., ping)
      _ => throw UnsupportedError('Unknown request type: $request'),
    };
  }

  /// Deserializes a message from JSON, handling custom fromJson() implementations.
  Object? _deserializeMessage(dynamic decoded) {
    if (decoded case [final String typeName, ...]) {
      // For Map-based RPC data types, the second element is the JSON map.
      final jsonData = switch (decoded) {
        [_, final Map<String, dynamic> map] => map,
        _ => const <String, dynamic>{},
      };

      return switch (typeName) {
        // List-based RPC data types:
        'DevToolsRequest' => DevToolsRequest.fromJson(decoded),
        // Map-based RPC data types:
        'ConnectRequest' => ConnectRequest.fromJson(jsonData),
        'RunRequest' => RunRequest.fromJson(jsonData),
        'HotRestartRequest' => HotRestartRequest.fromJson(jsonData),
        'HotReloadResponse' => HotReloadResponse.fromJson(jsonData),
        'HotRestartResponse' => HotRestartResponse.fromJson(jsonData),
        'ServiceExtensionResponse' => ServiceExtensionResponse.fromJson(
          jsonData,
        ),
        'ErrorResponse' => ErrorResponse.fromJson(jsonData),
        'DebugEvent' => DebugEvent.fromJson(jsonData),
        'BatchedDebugEvents' => BatchedDebugEvents.fromJson(jsonData),
        'IsolateStart' => IsolateStart.fromJson(jsonData),
        'IsolateExit' => IsolateExit.fromJson(jsonData),
        'RegisterEvent' => RegisterEvent.fromJson(jsonData),

        _ => throw FormatException('Unrecognized event type: $typeName'),
      };
    }
    throw FormatException('Unrecognized event type: $decoded');
  }

  /// Sends the provided [request] to all connected injected clients.
  /// Returns the number of clients the request was successfully sent to.
  int _sendRequestToClients(Object request) {
    _logger.finest('Sending request to injected clients: $request');
    var successfulSends = 0;
    for (final injectedConnection in _injectedConnections) {
      try {
        injectedConnection.sink.add(jsonEncode(_serializeMessage(request)));
        successfulSends++;
      } on StateError catch (e) {
        // The sink has already closed (app is disconnected), or another StateError occurred.
        _logger.warning(
          'Failed to send request to client, connection likely closed. Error: $e',
        );
      } catch (e, s) {
        // Catch any other potential errors during sending.
        _logger.severe('Error sending request to client: $e', e, s);
      }
    }
    _logger.fine(
      'Sent request to $successfulSends clients out of ${_injectedConnections.length} total connections',
    );
    return successfulSends;
  }

  /// Starts a [ChromeDebugService] for local debugging.
  Future<ChromeDebugService> _startLocalDebugService(
    ChromeConnection chromeConnection,
    AppConnection appConnection,
  ) async {
    ChromeTab? appTab;
    ExecutionContext? executionContext;
    WipConnection? connection;
    late final debugger = WebkitDebugger(WipDebugger(connection!));
    final appInstanceId = appConnection.request.instanceId;
    for (final tab in await chromeConnection.getTabs()) {
      if (tab.isChromeExtension || tab.isBackgroundPage) continue;

      connection = await tab.connect();
      if (_enableLogging) {
        connection.onSend.listen((message) {
          _log('  wip', '==> $message');
        });
        connection.onReceive.listen((message) {
          _log('  wip', '<== $message');
        });
        connection.onNotification.listen((message) {
          _log('  wip', '<== $message');
        });
      }
      final contextIds = connection.runtime.onExecutionContextCreated
          .map((context) => context.id)
          // There is no way to calculate the number of existing execution
          // contexts so keep receiving them until there is a 50ms gap after
          // receiving the last one.
          .takeUntilGap(const Duration(milliseconds: 50));
      // We enqueue this work as we need to begin listening (`.hasNext`)
      // before events are received.
      safeUnawaited(Future.microtask(connection.runtime.enable));

      await for (final contextId in contextIds) {
        final result = await connection.sendCommand('Runtime.evaluate', {
          'expression': r'window["$dartAppInstanceId"];',
          'contextId': contextId,
        });
        final evaluatedAppId = result.result?['result']?['value'];
        if (evaluatedAppId == appInstanceId) {
          appTab = tab;
          executionContext = RemoteDebuggerExecutionContext(
            contextId,
            debugger,
          );
          break;
        }
      }
      if (appTab != null) break;
      safeUnawaited(connection.close());
    }
    if (appTab == null || connection == null || executionContext == null) {
      throw AppConnectionException(
        'Could not connect to application with appInstanceId: '
        '$appInstanceId',
      );
    }

    return ChromeDebugService.start(
      // We assume the user will connect to the debug service on the same
      // machine. This allows consumers of DWDS to provide a `hostname` for
      // debugging through the Dart Debug Extension without impacting the local
      // debug workflow.
      hostname: 'localhost',
      remoteDebugger: debugger,
      executionContext: executionContext,
      assetReader: _assetReader,
      appConnection: appConnection,
      urlEncoder: _urlEncoder,
      onResponse: (response) {
        if (response['error'] == null) return;
        _logger.finest('VmService proxy responded with an error:\n$response');
        if (_enableLogging) {
          _log('vm', '<== ${response.toString().replaceAll('\n', ' ')}');
        }
      },
      onRequest: (request) {
        if (_enableLogging) {
          _log('vm', '==> ${request.toString().replaceAll('\n', ' ')}');
        }
      },
      // This will provide a websocket based service.
      useSse: false,
      expressionCompiler: _expressionCompiler,
      ddsConfig: _ddsConfig,
    );
  }

  void _log(String type, String message) {
    final logFile = File('${Platform.environment['HOME']}/dwds_log.txt');
    final time = (DateTime.now().millisecondsSinceEpoch % 1000000) / 1000.0;
    logFile.writeAsStringSync(
      '[${time.toStringAsFixed(3).padLeft(7)}s] $type $message\n',
      mode: FileMode.append,
    );
  }

  Future<AppDebugServices> loadAppServices(AppConnection appConnection) async {
    final appId = appConnection.request.appId;
    var appServices = _servicesByAppId[appId];
    if (appServices == null) {
      if (useWebSocketConnection) {
        appServices = await _createWebSocketAppServices(appConnection);
      } else {
        appServices = await _createChromeAppServices(appConnection);
        _setupChromeServiceCleanup(appServices, appConnection);
      }
      _servicesByAppId[appId] = appServices;
    }

    return appServices;
  }

  /// Creates WebSocket-based app services for hot reload functionality.
  Future<AppDebugServices> _createWebSocketAppServices(
    AppConnection appConnection,
  ) async {
    final webSocketDebugService = await WebSocketDebugService.start(
      hostname: 'localhost',
      appConnection: appConnection,
      assetReader: _assetReader,
      sendClientRequest: _sendRequestToClients,
      ddsConfig: _ddsConfig,
    );
    return _createAppDebugServicesWebSocketMode(
      webSocketDebugService,
      appConnection,
    );
  }

  /// Creates Chrome-based app services for full debugging capabilities.
  Future<AppDebugServices> _createChromeAppServices(
    AppConnection appConnection,
  ) async {
    final debugService = await _startLocalDebugService(
      await _chromeConnection(),
      appConnection,
    );
    return _createAppDebugServices(debugService);
  }

  /// Sets up cleanup handling for Chrome-based services.
  void _setupChromeServiceCleanup(
    AppDebugServices appServices,
    AppConnection appConnection,
  ) {
    final chromeProxy = appServices.proxyService;
    if (chromeProxy is ChromeProxyService) {
      safeUnawaited(
        chromeProxy.remoteDebugger.onClose.first.whenComplete(() async {
          await appServices.close();
          _servicesByAppId.remove(appConnection.request.appId);
          _logger.info(
            'Stopped debug service on '
            'ws://${appServices.debugService.hostname}:${appServices.debugService.port}\n',
          );
        }),
      );
    }
  }

  void _handleConnection(SocketConnection injectedConnection) {
    _injectedConnections.add(injectedConnection);
    AppConnection? appConnection;
    injectedConnection.stream.listen((data) async {
      try {
        final message = _deserializeMessage(jsonDecode(data));
        if (message is ConnectRequest) {
          if (appConnection != null) {
            throw StateError(
              'Duplicate connection request from the same app. '
              'Please file an issue at '
              'https://github.com/dart-lang/webdev/issues/new.',
            );
          }
          appConnection = useWebSocketConnection
              ? await _handleWebSocketConnectRequest(
                  message,
                  injectedConnection,
                )
              : await _handleConnectRequest(message, injectedConnection);
        } else {
          final connection = appConnection;
          if (connection == null) {
            throw StateError('Not connected to an application.');
          }
          if (message is DevToolsRequest) {
            await _handleDebugRequest(connection, injectedConnection);
          } else {
            // Handle messages for both WebSocket and Chrome proxy services
            await _handleMessage(connection, message);
          }
        }
      } catch (e, s) {
        // Most likely the app disconnected in the middle of us responding,
        // but we will try and send an error response back to the page just in
        // case it is still running.
        try {
          injectedConnection.sink.add(
            jsonEncode(
              _serializeMessage(ErrorResponse(error: '$e', stackTrace: '$s')),
            ),
          );
        } on StateError catch (_) {
          // The sink has already closed (app is disconnected), swallow the
          // error.
        }
      }
    });

    safeUnawaited(
      injectedConnection.sink.done.then((_) {
        _injectedConnections.remove(injectedConnection);
        final connection = appConnection;
        if (connection != null) {
          final appId = connection.request.appId;
          final services = _servicesByAppId[appId];
          // WebSocket mode doesn't need this because WebSocketProxyService handles connection tracking and cleanup
          if (!useWebSocketConnection) {
            _appConnectionByAppId.remove(appId);
          }
          if (services != null) {
            if (services.connectedInstanceId == null ||
                services.connectedInstanceId == connection.request.instanceId) {
              services.connectedInstanceId = null;
              _handleIsolateExit(connection);
            }
          }
        }
      }),
    );
  }

  /// Handles messages for both WebSocket and Chrome proxy services.
  Future<void> _handleMessage(AppConnection connection, Object? message) async {
    if (message == null) return;

    final appId = connection.request.appId;
    final proxyService = _servicesByAppId[appId]?.proxyService;

    if (proxyService == null) {
      if (message is HotRestartRequest) {
        _logger.finest('No debugger, let the app handle the restart itself.');
        connection.hotRestart(message);
        return;
      }
      _logger.warning(
        'No proxy service found for appId: $appId to process $message',
      );
      return;
    }

    // Handle messages that are specific to certain proxy service types
    if (message is HotReloadResponse) {
      proxyService.completeHotReload(message);
    } else if (message is HotRestartResponse) {
      proxyService.completeHotRestart(message);
    } else if (message is ServiceExtensionResponse) {
      proxyService.completeServiceExtension(message);
    } else if (message is IsolateExit) {
      _handleIsolateExit(connection);
    } else if (message is IsolateStart) {
      await _handleIsolateStart(connection);
    } else if (message is BatchedDebugEvents) {
      proxyService.parseBatchedDebugEvents(message);
    } else if (message is DebugEvent) {
      proxyService.parseDebugEvent(message);
    } else if (message is RegisterEvent) {
      proxyService.parseRegisterEvent(message);
    } else if (message is HotRestartRequest) {
      final services = _servicesByAppId[appId]!;
      if (services.dwdsVmClient is! ChromeDwdsVmClient ||
          services.proxyService is! ChromeProxyService) {
        throw UnsupportedError(
          'In-app restart requests are only supported by '
          'ChromeDwdsVmClient and ChromeProxyService',
        );
      }
      final chromeClient = services.dwdsVmClient as ChromeDwdsVmClient;
      final chromeProxyService = services.proxyService as ChromeProxyService;
      unawaited(
        chromeClient.hotRestart(chromeProxyService, chromeClient.client),
      );
    } else {
      final serviceType = proxyService is WebSocketProxyService
          ? 'WebSocket'
          : 'Chrome';
      throw UnsupportedError(
        'Message type ${message.runtimeType} is not supported in $serviceType mode',
      );
    }
  }

  Future<void> _handleDebugRequest(
    AppConnection appConnection,
    SocketConnection sseConnection,
  ) async {
    if (_devTools == null && !_ddsConfig.serveDevTools) {
      sseConnection.sink.add(
        jsonEncode(
          _serializeMessage(
            DevToolsResponse(
              success: false,
              promptExtension: false,
              error:
                  'Debugging is not enabled.\n\n'
                  'If you are using webdev please pass the --debug flag.\n'
                  'Otherwise check the docs for the tool you are using.',
            ),
          ),
        ),
      );
      return;
    }
    final debuggerStart = DateTime.now();
    AppDebugServices appServices;
    try {
      appServices = await loadAppServices(appConnection);
    } catch (_) {
      final error =
          'Unable to connect debug services to your '
          'application. Most likely this means you are trying to '
          'load in a different Chrome window than was launched by '
          'your development tool.';
      var response = DevToolsResponse(
        success: false,
        promptExtension: false,
        error: error,
      );
      if (_extensionBackend != null) {
        response = DevToolsResponse(
          success: false,
          promptExtension: true,
          error:
              '$error\n\n'
              'Your workflow alternatively supports debugging through the '
              'Dart Debug Extension.\n\n'
              'Would you like to install the extension?',
        );
      }
      sseConnection.sink.add(jsonEncode(_serializeMessage(response)));
      return;
    }

    // Check if we are already running debug services for a different
    // instance of this app.
    if (appServices.connectedInstanceId != null &&
        appServices.connectedInstanceId != appConnection.request.instanceId) {
      sseConnection.sink.add(
        jsonEncode(
          _serializeMessage(
            DevToolsResponse(
              success: false,
              promptExtension: false,
              error:
                  'This app is already being debugged in a different tab. '
                  'Please close that tab or switch to it.',
            ),
          ),
        ),
      );
      return;
    }

    sseConnection.sink.add(
      jsonEncode(
        _serializeMessage(
          DevToolsResponse(success: true, promptExtension: false),
        ),
      ),
    );

    appServices.connectedInstanceId = appConnection.request.instanceId;
    appServices.dwdsStats!.updateLoadTime(
      debuggerStart: debuggerStart,
      devToolsStart: DateTime.now(),
    );
    final chromeProxy = appServices.proxyService;
    if (chromeProxy is ChromeProxyService) {
      await _launchDevTools(
        chromeProxy.remoteDebugger,
        _constructDevToolsUri(
          appServices,
          appServices.debugService.uri,
          ideQueryParam: 'Dwds',
        ),
      );
    }
  }

  /// Creates a debug connection for WebSocket mode.
  Future<DebugConnection> createDebugConnectionForWebSocket(
    AppConnection appConnection,
  ) async {
    final appDebugServices = await loadAppServices(appConnection);

    // Initialize WebSocket proxy service
    try {
      final proxyService = appDebugServices.proxyService;
      if (proxyService is! WebSocketProxyService) {
        throw StateError(
          'Expected WebSocketProxyService but got ${proxyService.runtimeType}. ',
        );
      }
      await proxyService.isInitialized;
      _logger.fine('WebSocket proxy service initialized successfully');
    } catch (e) {
      _logger.severe('Failed to initialize WebSocket proxy service: $e');
      rethrow;
    }

    return DebugConnection(appDebugServices);
  }

  /// Creates a debug connection for Chrome mode.
  Future<DebugConnection> createDebugConnectionForChrome(
    AppConnection appConnection,
  ) async {
    final appDebugServices = await loadAppServices(appConnection);

    // Initialize Chrome proxy service
    try {
      final proxyService = appDebugServices.proxyService;
      if (proxyService is! ChromeProxyService) {
        throw StateError(
          'Expected ChromeProxyService but got ${proxyService.runtimeType}. ',
        );
      }
      await proxyService.isInitialized;
      _logger.fine('Chrome proxy service initialized successfully');
    } catch (e) {
      _logger.severe('Failed to initialize Chrome proxy service: $e');
      rethrow;
    }

    return DebugConnection(appDebugServices);
  }

  Future<AppConnection> _handleConnectRequest(
    ConnectRequest message,
    SocketConnection sseConnection,
  ) async {
    // After a page refresh, reconnect to the same app services if they
    // were previously launched and create the new isolate.
    final services = _servicesByAppId[message.appId];
    final existingConnection = _appConnectionByAppId[message.appId];
    // Completer to indicate when the app's main() method is ready to be run.
    // Its future is passed to the AppConnection so that it can be awaited on
    // before running the app's main() method:
    final readyToRunMainCompleter = Completer<void>();
    final connection = AppConnection(
      message,
      sseConnection,
      readyToRunMainCompleter.future,
    );

    if (_canReconnect(existingConnection, message)) {
      // Disconnect any old connection (eg. those in the keep-alive waiting
      // state when reloading the page).
      existingConnection?.shutDown();
      final chromeProxy = services!.proxyService;
      if (chromeProxy is ChromeProxyService) {
        chromeProxy.destroyIsolate();
      }

      // Reconnect to existing service.
      services.connectedInstanceId = message.instanceId;

      final chromeService = services.proxyService;
      if (chromeService is ChromeProxyService) {
        if (chromeService.pauseIsolatesOnStart) {
          // If the pause-isolates-on-start flag is set, we need to wait for
          // the resume event to run the app's main() method.
          _waitForResumeEventToRunMain(
            chromeService.resumeAfterRestartEventsStream,
            readyToRunMainCompleter,
          );
        } else {
          // Otherwise, we can run the app's main() method immediately.
          readyToRunMainCompleter.complete();
        }

        await chromeService.createIsolate(connection);
      }
    } else {
      // If this is the initial app connection, we can run the app's main()
      // method immediately.
      readyToRunMainCompleter.complete();
    }
    _appConnectionByAppId[message.appId] = connection;
    _connectedApps.add(connection);
    return connection;
  }

  /// Handles WebSocket mode connection requests with multi-window support.
  Future<AppConnection> _handleWebSocketConnectRequest(
    ConnectRequest message,
    SocketConnection sseConnection,
  ) async {
    // After a page refresh, reconnect to the same app services if they
    // were previously launched and create the new isolate.
    final services = _servicesByAppId[message.appId];
    final existingConnection = _appConnectionByAppId[message.appId];
    // Completer to indicate when the app's main() method is ready to be run.
    // Its future is passed to the AppConnection so that it can be awaited on
    // before running the app's main() method:
    final readyToRunMainCompleter = Completer<void>();
    final connection = AppConnection(
      message,
      sseConnection,
      readyToRunMainCompleter.future,
    );

    if (_canReconnect(existingConnection, message)) {
      // Reconnect to existing service.
      await _reconnectToService(
        services!,
        existingConnection,
        connection,
        message,
        readyToRunMainCompleter,
      );
    } else {
      // New browser window or initial connection: run main() immediately
      readyToRunMainCompleter.complete();

      // For WebSocket mode, we need to proactively create and emit a debug connection
      try {
        if (services != null) {
          // If we are reconnecting to an existing app but not the same instance,
          // ensure the isolate is started for the new connection before creating
          // the debug connection, otherwise it will hang waiting for initialization.
          await _handleIsolateStart(connection);
        }

        // Initialize the WebSocket service and create debug connection
        final debugConnection = await createDebugConnectionForWebSocket(
          connection,
        );

        // Emit the debug connection through the extension stream
        extensionDebugConnections.add(debugConnection);
      } catch (e, s) {
        _logger.warning('Failed to create WebSocket debug connection: $e\n$s');
      }
    }
    _appConnectionByAppId[message.appId] = connection;
    _connectedApps.add(connection);
    _logger.fine('App connection established for: ${message.appId}');
    return connection;
  }

  /// Allow connection reuse for page refreshes and same instance reconnections
  bool _canReconnect(
    AppConnection? existingConnection,
    ConnectRequest message,
  ) {
    final services = _servicesByAppId[message.appId];

    if (services == null) {
      return false;
    }

    if (existingConnection?.request.instanceId == message.instanceId) {
      return true;
    }

    final isKeepAliveReconnect =
        existingConnection?.isInKeepAlivePeriod == true;
    final hasNoActiveConnection = services.connectedInstanceId == null;
    final noExistingConnection = existingConnection == null;

    return (isKeepAliveReconnect && hasNoActiveConnection) ||
        (noExistingConnection && hasNoActiveConnection);
  }

  /// Handles reconnection to existing services for web-socket mode.
  Future<void> _reconnectToService(
    AppDebugServices services,
    AppConnection? existingConnection,
    AppConnection newConnection,
    ConnectRequest message,
    Completer<void> readyToRunMainCompleter,
  ) async {
    // Disconnect old connection
    existingConnection?.shutDown();
    services.connectedInstanceId = message.instanceId;

    _logger.finest('WebSocket service reconnected for app: ${message.appId}');

    final wsService = services.proxyService;
    if (wsService is WebSocketProxyService) {
      _setupMainExecution(
        wsService.pauseIsolatesOnStart,
        wsService.resumeAfterRestartEventsStream,
        readyToRunMainCompleter,
      );
    } else {
      readyToRunMainCompleter.complete();
    }

    await _handleIsolateStart(newConnection);
  }

  /// Sets up main() execution timing based on pause settings.
  void _setupMainExecution(
    bool pauseIsolatesOnStart,
    Stream<String>? resumeEventsStream,
    Completer<void> readyToRunMainCompleter,
  ) {
    if (pauseIsolatesOnStart && resumeEventsStream != null) {
      _waitForResumeEventToRunMain(resumeEventsStream, readyToRunMainCompleter);
    } else {
      readyToRunMainCompleter.complete();
    }
  }

  /// Waits for a resume event to trigger the app's main() method.
  ///
  /// The [readyToRunMainCompleter]'s future will be passed to the
  /// [AppConnection] so that it can be awaited on before running the app's
  /// main() method.
  void _waitForResumeEventToRunMain(
    Stream<String> resumeEventsStream,
    Completer<void> readyToRunMainCompleter,
  ) {
    StreamSubscription<String>? resumeEventsSubscription;
    resumeEventsSubscription = resumeEventsStream.listen((_) async {
      await resumeEventsSubscription!.cancel();
      readyToRunMainCompleter.complete();
    });
  }

  /// Handles isolate exit events for both WebSocket and Chrome-based debugging.
  void _handleIsolateExit(AppConnection appConnection) {
    final appId = appConnection.request.appId;

    if (useWebSocketConnection) {
      _logger.fine(
        'Isolate exit handled by WebSocket proxy service for app: $appId',
      );
    } else {
      final proxyService = _servicesByAppId[appId]?.proxyService;
      if (proxyService is ChromeProxyService) {
        proxyService.destroyIsolate();
      }
    }
  }

  /// Handles isolate start events for both WebSocket and Chrome-based debugging.
  Future<void> _handleIsolateStart(AppConnection appConnection) async {
    final appId = appConnection.request.appId;

    if (useWebSocketConnection) {
      final proxyService = _servicesByAppId[appId]?.proxyService;
      if (proxyService is WebSocketProxyService) {
        await proxyService.createIsolate(appConnection);
      }
    } else {
      final proxyService = _servicesByAppId[appId]?.proxyService;
      if (proxyService is ChromeProxyService) {
        await proxyService.createIsolate(appConnection);
      }
    }
  }

  void _listen() {
    _subs.add(
      _injected.devHandlerPaths.listen((devHandlerPath) async {
        final uri = Uri.parse(devHandlerPath);
        if (!_sseHandlers.containsKey(uri.path)) {
          final handler = _useSseForInjectedClient
              ? SseSocketHandler(
                  // We provide an essentially indefinite keep alive duration because
                  // the underlying connection could be lost while the application
                  // is paused. The connection will get re-established after a resume
                  // or cleaned up on a full page refresh.
                  SseHandler(
                    uri,
                    keepAlive: const Duration(days: 3000),
                    ignoreDisconnect: sseIgnoreDisconnect,
                  ),
                )
              : WebSocketSocketHandler();
          _sseHandlers[uri.path] = handler;
          final injectedConnections = handler.connections;
          while (await injectedConnections.hasNext) {
            _handleConnection(await injectedConnections.next);
          }
        }
      }),
    );
  }

  Future<AppDebugServices> _createAppDebugServices(
    ChromeDebugService debugService,
  ) async {
    final dwdsStats = DwdsStats();
    DartDevelopmentServiceLauncher? dds;
    if (_ddsConfig.enable) {
      dds = await debugService.startDartDevelopmentService();
    }
    final vmClient = await ChromeDwdsVmClient.create(debugService, dds?.wsUri);
    final appDebugService = AppDebugServices(
      debugService: debugService,
      dwdsVmClient: vmClient,
      dwdsStats: dwdsStats,
      dds: dds,
    );
    final encodedUri = await debugService.encodedUri;
    _logger.info('Debug service listening on $encodedUri\n');
    final chromeProxy = appDebugService.proxyService;
    if (chromeProxy is ChromeProxyService) {
      await chromeProxy.remoteDebugger.sendCommand(
        'Runtime.evaluate',
        params: {
          'expression':
              'console.log('
              '"This app is linked to the debug service: $encodedUri"'
              ');',
        },
      );
    }

    // Notify that DWDS has been launched and a debug connection has been made:
    _maybeEmitDwdsLaunchEvent();

    return appDebugService;
  }

  Future<AppDebugServices> _createAppDebugServicesWebSocketMode(
    WebSocketDebugService webSocketDebugService,
    AppConnection appConnection,
  ) async {
    DartDevelopmentServiceLauncher? dds;
    if (_ddsConfig.enable) {
      dds = await webSocketDebugService.startDartDevelopmentService();
    }
    final wsVmClient = await WebSocketDwdsVmClient.create(
      webSocketDebugService,
      dds?.wsUri,
    );
    final wsAppDebugService = AppDebugServices(
      debugService: webSocketDebugService,
      dwdsVmClient: wsVmClient,
      dds: dds,
    );

    safeUnawaited(_handleIsolateStart(appConnection));
    final debugServiceUri = webSocketDebugService.uri;
    _logger.info('Debug service listening on $debugServiceUri\n');

    // Notify that DWDS has been launched and a debug connection has been made:
    _maybeEmitDwdsLaunchEvent();

    return wsAppDebugService;
  }

  Future<void> _listenForDebugExtension() async {
    final extensionBackend = _extensionBackend;
    if (extensionBackend == null) {
      _logger.severe('No debug extension backend. Debugging will not work.');
      return;
    }

    while (await extensionBackend.connections.hasNext) {
      final extensionDebugger = await extensionBackend.extensionDebugger;
      _startExtensionDebugService(extensionDebugger);
    }
  }

  /// Starts a [ChromeProxyService] for Dart Debug Extension.
  void _startExtensionDebugService(ExtensionDebugger extensionDebugger) {
    // Waits for a `DevToolsRequest` to be sent from the extension background
    // when the extension is clicked.
    extensionDebugger.devToolsRequestStream.listen((devToolsRequest) async {
      try {
        await _handleDevToolsRequest(extensionDebugger, devToolsRequest);
        _logger.finest('DevTools request processed successfully');
      } catch (error) {
        _logger.severe('Encountered error handling DevTools request.');
        extensionDebugger.closeWithError(error);
      }
    });
  }

  Future<void> _handleDevToolsRequest(
    ExtensionDebugger extensionDebugger,
    DevToolsRequest devToolsRequest,
  ) async {
    // TODO(grouma) - Ideally we surface those warnings to the extension so
    // that it can be displayed to the user through an alert.
    final tabUrl = devToolsRequest.tabUrl;
    final appId = devToolsRequest.appId;
    if (tabUrl == null) {
      throw StateError(
        'Failed to start extension debug service. '
        'Missing tab url in DevTools request for app with id: $appId',
      );
    }
    final connection = _appConnectionByAppId[appId];
    if (connection == null) {
      throw StateError(
        'Failed to start extension debug service. '
        'Not connected to an app with id: $appId',
      );
    }
    final executionContext = extensionDebugger.executionContext;
    if (executionContext == null) {
      throw StateError(
        'Failed to start extension debug service. '
        'No execution context for app with id: $appId',
      );
    }

    final debuggerStart = DateTime.now();
    var appServices = _servicesByAppId[appId];
    if (appServices == null) {
      final debugService = await ChromeDebugService.start(
        hostname: _hostname,
        remoteDebugger: extensionDebugger,
        executionContext: executionContext,
        assetReader: _assetReader,
        appConnection: connection,
        urlEncoder: _urlEncoder,
        onResponse: (response) {
          if (response['error'] == null) return;
          _logger.finest('VmService proxy responded with an error:\n$response');
        },
        useSse: _useSseForDebugProxy,
        expressionCompiler: _expressionCompiler,
        ddsConfig: _ddsConfig,
      );
      appServices = await _createAppDebugServices(debugService);
      extensionDebugger.sendEvent('dwds.debugUri', debugService.uri);
      final encodedUri = await debugService.encodedUri;
      extensionDebugger.sendEvent('dwds.encodedUri', encodedUri);
      final chromeProxy = appServices.proxyService;
      if (chromeProxy is ChromeProxyService) {
        safeUnawaited(
          chromeProxy.remoteDebugger.onClose.first.whenComplete(() async {
            chromeProxy.destroyIsolate();
            await appServices?.close();
            _servicesByAppId.remove(devToolsRequest.appId);
            _logger.info(
              'Stopped debug service on '
              '${await appServices?.debugService.encodedUri}\n',
            );
          }),
        );
      }
      extensionDebugConnections.add(DebugConnection(appServices));
      _servicesByAppId[appId] = appServices;
    }

    _maybeEmitDwdsAttachEvent(devToolsRequest);

    // If we don't have a DevTools instance, then are connecting to an IDE.
    // Therefore return early instead of opening DevTools:
    if (_devTools == null) return;

    final encodedUri = await appServices.debugService.encodedUri;

    appServices.dwdsStats!.updateLoadTime(
      debuggerStart: debuggerStart,
      devToolsStart: DateTime.now(),
    );

    emitEvent(DwdsEvent.devtoolsLaunch());
    // Send the DevTools URI to the Dart Debug Extension so that it can open it:
    final devToolsUri = _constructDevToolsUri(
      appServices,
      encodedUri,
      ideQueryParam: 'ChromeDevTools',
    );
    return extensionDebugger.sendEvent('dwds.devtoolsUri', devToolsUri);
  }

  Future<void> _launchDevTools(
    RemoteDebugger remoteDebugger,
    String devToolsUri,
  ) async {
    // TODO(grouma) - We may want to log the debugServiceUri if we don't launch
    // DevTools so that users can manually connect.
    emitEvent(DwdsEvent.devtoolsLaunch());
    await remoteDebugger.sendCommand(
      'Target.createTarget',
      params: {'newWindow': _launchDevToolsInNewWindow, 'url': devToolsUri},
    );
  }

  String _constructDevToolsUri(
    AppDebugServices appDebugServices,
    String serviceUri, {
    String ideQueryParam = '',
  }) {
    final devToolsUri = _devTools?.uri ?? appDebugServices.devToolsUri;
    if (devToolsUri == null) {
      throw StateError('DevHandler: DevTools is not available');
    }
    return devToolsUri
        .replace(
          pathSegments: [
            // Strips any trailing slashes from the original path
            ...devToolsUri.pathSegments.whereNot((e) => e.isEmpty),
            'debugger',
          ],
          queryParameters: {
            ...devToolsUri.queryParameters,
            'uri': serviceUri,
            if (ideQueryParam.isNotEmpty) 'ide': ideQueryParam,
          },
        )
        .toString();
  }

  static void _maybeEmitDwdsAttachEvent(DevToolsRequest request) {
    if (request.client != null) {
      emitEvent(
        DwdsEvent.dwdsAttach(
          client: request.client!,
          isFlutterApp:
              globalToolConfiguration.loadStrategy.buildSettings.isFlutterApp,
        ),
      );
    }
  }

  static void _maybeEmitDwdsLaunchEvent() {
    if (globalToolConfiguration.appMetadata.codeRunner != null) {
      emitEvent(
        DwdsEvent.dwdsLaunch(
          codeRunner: globalToolConfiguration.appMetadata.codeRunner!,
          isFlutterApp:
              globalToolConfiguration.loadStrategy.buildSettings.isFlutterApp,
        ),
      );
    }
  }
}

class AppConnectionException implements Exception {
  final String details;

  AppConnectionException(this.details);
}

extension<T> on Stream<T> {
  /// Forwards events from the original stream until a period of at least [gap]
  /// occurs in between events, in which case the returned stream will end.
  Stream<T> takeUntilGap(Duration gap) {
    final controller = isBroadcast
        ? StreamController<T>.broadcast(sync: true)
        : StreamController<T>(sync: true);

    late StreamSubscription<T> subscription;
    Timer? gapTimer;
    controller.onListen = () {
      subscription = listen(
        (e) {
          controller.add(e);
          gapTimer?.cancel();
          gapTimer = Timer(gap, () {
            subscription.cancel();
            controller.close();
          });
        },
        onError: controller.addError,
        onDone: controller.close,
      );
    };
    // Not handling pause/resume
    return controller.stream;
  }
}
