import 'dart:async';

import 'package:flutter/material.dart';

import '../features/workspaces/presentation/workspace_home_page.dart';
import '../integrations/mattermost/mattermost_push_host_integration.dart';
import '../integrations/proto_socket/proto_socket_endpoint_config.dart';
import '../integrations/proto_socket/proto_socket_lifecycle.dart';
import '../integrations/proto_socket/proto_socket_task_service.dart';
import '../integrations/workspace/workspace_launcher.dart';
import 'bootstrap.dart' show applyFullscreenMode;
import 'nomadcode_workbench_shell.dart';

class NomadCodeClientApp extends StatelessWidget {
  final MattermostPushHostIntegration? mattermostHost;
  final GlobalKey<NavigatorState>? navigatorKey;
  final ProtoSocketLifecycle? protoSocketLifecycle;
  final ProtoSocketEndpointConfig? protoSocketConfig;

  const NomadCodeClientApp({
    super.key,
    this.mattermostHost,
    this.navigatorKey,
    this.protoSocketLifecycle,
    this.protoSocketConfig,
  });

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'nomadcode-app',
      navigatorKey: navigatorKey,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.deepPurple,
          brightness: Brightness.dark,
        ),
        useMaterial3: true,
      ),
      home: _NomadCodeClientHome(
        mattermostHost: mattermostHost,
        protoSocketLifecycle: protoSocketLifecycle,
        protoSocketConfig: protoSocketConfig,
      ),
    );
  }
}

class _NomadCodeClientHome extends StatefulWidget {
  final MattermostPushHostIntegration? mattermostHost;
  final ProtoSocketLifecycle? protoSocketLifecycle;
  final ProtoSocketEndpointConfig? protoSocketConfig;

  const _NomadCodeClientHome({
    this.mattermostHost,
    this.protoSocketLifecycle,
    this.protoSocketConfig,
  });

  @override
  State<_NomadCodeClientHome> createState() => _NomadCodeClientHomeState();
}

class _NomadCodeClientHomeState extends State<_NomadCodeClientHome> {
  final WorkspaceLauncher _launcher = WorkspaceLauncher();
  StreamSubscription? _notifSub;
  WorkspaceTaskLoader? _taskLoader;
  bool _connectedByThisWidget = false;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      applyFullscreenMode();
    });

    unawaited(_connectProtoSocketIfEnabled());

    final host = widget.mattermostHost;
    if (host != null) {
      _notifSub = host.onNotification.listen((data) {
        if (data['type'] != 'message') return;
        final message = data['message'] as String? ?? '';
        final channel = data['channel_name'] as String? ?? '';
        final sender = data['sender_name'] as String? ?? '';
        if (!mounted) return;
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text(
              sender.isNotEmpty ? '[$channel] $sender: $message' : message,
              maxLines: 2,
              overflow: TextOverflow.ellipsis,
            ),
            duration: const Duration(seconds: 4),
            behavior: SnackBarBehavior.floating,
          ),
        );
      });
    }
  }

  /// Connects the proto-socket rail only when an endpoint config is present and
  /// explicitly enabled. Any failure is swallowed so the page stays usable on
  /// its mock fallback; only a successful connect wires the task service.
  Future<void> _connectProtoSocketIfEnabled() async {
    final lifecycle = widget.protoSocketLifecycle;
    final config = widget.protoSocketConfig;
    if (lifecycle == null || config == null || !config.enabled) return;
    final startedHere =
        lifecycle.state != ProtoSocketConnectionState.connected &&
        lifecycle.state != ProtoSocketConnectionState.connecting;
    try {
      await lifecycle.connect(config);
      final transport = lifecycle.transport;
      if (transport == null) return;
      if (!mounted) {
        if (startedHere) {
          await lifecycle.disconnect();
        }
        return;
      }
      final taskService = ProtoSocketTaskService(transport);
      setState(() {
        _taskLoader = (_) => taskService.listTasks();
        _connectedByThisWidget = startedHere;
      });
    } catch (_) {
      // Leave the page on mock fallback when the rail cannot connect.
    }
  }

  @override
  void dispose() {
    _notifSub?.cancel();
    // Only tear down the connection this widget actually established.
    final lifecycle = widget.protoSocketLifecycle;
    if (_connectedByThisWidget && lifecycle != null) {
      unawaited(lifecycle.disconnect());
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return NomadCodeWorkbenchShell(
      workspace: WorkspaceHomePage(
        showAppBar: false,
        onLaunchCodeServer: (project) => _launcher.openCodeServer(project),
        loadTasks: _taskLoader,
        protoSocketLifecycle: widget.protoSocketLifecycle,
      ),
    );
  }
}
