import 'dart:async';
import 'dart:convert';
import 'package:chepuhagram/domain/services/api_service.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:web_socket_channel/status.dart' as status;
import 'package:web_socket_channel/io.dart';
import 'package:chepuhagram/core/constants.dart';
import 'package:flutter/widgets.dart';

class SocketService with WidgetsBindingObserver {

  static final SocketService _instance = SocketService._internal();
  factory SocketService() => _instance;
  
  SocketService._internal() {
    WidgetsBinding.instance.addObserver(this);
  }

  WebSocketChannel? _channel;
  final StreamController<Map<String, dynamic>> _messageController =
      StreamController<Map<String, dynamic>>.broadcast();

  // Поток, который будут слушать провайдеры
  Stream<Map<String, dynamic>> get messages => _messageController.stream;

  bool allowConnect = true; // Флаг для контроля подключения

  
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      allowConnect = true;
    } else {
      allowConnect = false;
      disconnect();
    } 
  }

  Future<void> connect(ApiService apiService) async {
    final token = await apiService.getAccessToken();
    if (_channel != null) return; // Уже подключены
    if (token == null || token.isEmpty) {
      print('❌ SocketService.connect: no access token, skipping connect');
      return;
    }
    if (!allowConnect) return; // Не разрешаем подключение

    // В FastAPI эндпоинт обычно ожидает токен в URL или подзаголовке
    final uri = Uri.parse("${AppConstants.wsUrl}/ws?token=$token");

    //_channel = WebSocketChannel.connect(uri);

    _channel = IOWebSocketChannel.connect(
      uri,
      connectTimeout: Duration(seconds: 10),
    );

    try {
      await _channel!.ready;
      _channel!.stream.listen(
        (data) {
          final decoded = jsonDecode(data);
          print("🚀 СООБЩЕНИЕ ПОЛУЧЕНО ИЗ SINK: $decoded");
          _messageController.add(decoded);
        },
        onError: (error) => _reconnect(apiService),
        onDone: () => _reconnect(apiService),
      );
    } on TimeoutException catch (_) {
      _channel = null;
      throw Exception('timeout');
    } catch (e) {
      _channel = null;
      throw Exception("Ошибка подключения: $e");
    }
  }

  Future<void> _reconnect(ApiService apiService) async {
    _channel = null;
    Future.delayed(const Duration(seconds: 5), () => connect(apiService));
  }

  bool sendMessage(Map<String, dynamic> data, {int retryCnt = 0}) {
    if (_channel == null) {
      //print("❌ ОШИБКА: Попытка отправить сообщение через NULL канал.");
      sendMessage(data, retryCnt: retryCnt + 1);
      return false;
    }
    try {
      final encodedData = jsonEncode(data);

      // 1. Проверяем, не закрыт ли sink (у некоторых провайдеров это доступно)
      _channel!.sink.add(encodedData);

      // 2. Добавляем принт подтверждения
      print("🚀 СООБЩЕНИЕ ОТПРАВЛЕНО В SINK: $encodedData");
      return true;
    } catch (e) {
      print("❌ КРИТИЧЕСКАЯ ОШИБКА ПРИ ОТПРАВКЕ: $e");
      return false;
    }
  }

  bool sendReadReceipt(int messageId) {
    return sendMessage({'type': 'read_receipt', 'message_id': messageId});
  }

  void disconnect() {
    _channel?.sink.close(status.normalClosure);
    _channel = null;
  }
}
