import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'tcp_client_state.dart';
import 'tcp_connection_status.dart';

class TcpClientCubit extends Cubit<TcpClientState> {
  Socket? _socket;

  String? _address;
  int? _port;
  int _timeout = 5000;
  int _maxRetryCount = 3;
  int _retryInterval = 2000;
  int _currentRetry = 0;

  Timer? _reconnectTimer;
  Timer? _heartbeatTimer;
  bool _isManualDisconnect = false;
  bool _isConnecting = false;

  /// Socket 数据监听的订阅，需要在 close 时显式取消
  StreamSubscription<dynamic>? _socketSub;

  final StreamController<Uint8List> _dataController =
      StreamController.broadcast();

  /// 接收到的数据流
  Stream<Uint8List> get onData => _dataController.stream;

  TcpClientCubit() : super(const TcpClientState());

  /// 配置连接参数
  void config({
    required String address,
    required int port,
    int timeout = 5000,
    int maxRetry = 3,
    int retryInterval = 2000,
  }) {
    _address = address;
    _port = port;
    _timeout = timeout;
    _maxRetryCount = maxRetry;
    _retryInterval = retryInterval;
    emit(state.copyWith(address: address, port: port));
  }

  /// 连接服务器
  Future<bool> connect() async {
    if (_address == null || _port == null) {
      emit(state.copyWith(error: '未配置地址或端口'));
      return false;
    }
    if (state.isConnected) return true;
    if (_isConnecting) return false;

    _isConnecting = true;
    _isManualDisconnect = false;
    emit(state.copyWith(
        connectionStatus: TcpConnectionStatus.connecting, clearError: true));

    try {
      _socket = await Socket.connect(
        _address!,
        _port!,
        timeout: Duration(milliseconds: _timeout),
      );

      if (isClosed) {
        _socket?.close();
        _socket = null;
        return false;
      }

      _socket!.setOption(SocketOption.tcpNoDelay, true);
      _listenSocket();

      _currentRetry = 0;
      emit(state.copyWith(connectionStatus: TcpConnectionStatus.connected));
      _startHeartbeat();
      return true;
    } catch (e) {
      if (isClosed) return false;
      emit(state.copyWith(
        connectionStatus: TcpConnectionStatus.error,
        error: e.toString(),
      ));
      _tryReconnect();
      return false;
    } finally {
      _isConnecting = false;
    }
  }

  /// 监听 Socket 数据
  void _listenSocket() {
    _socketSub?.cancel();
    _socketSub = _socket!.listen(
      (data) {
        final uint8List = Uint8List.fromList(data);
        if (!_dataController.isClosed) {
          _dataController.add(uint8List);
        }
      },
      onError: (e) {
        if (isClosed) return;
        emit(state.copyWith(
          connectionStatus: TcpConnectionStatus.error,
          error: e.toString(),
        ));
        _tryReconnect();
      },
      onDone: () {
        if (!_isManualDisconnect && !isClosed) {
          _tryReconnect();
        }
      },
    );
  }

  /// 自动重连
  void _tryReconnect() {
    if (isClosed) return;
    if (_isManualDisconnect) return;
    if (_currentRetry >= _maxRetryCount) {
      emit(state.copyWith(connectionStatus: TcpConnectionStatus.disconnected));
      return;
    }

    _currentRetry++;
    emit(state.copyWith(connectionStatus: TcpConnectionStatus.reconnecting));

    _reconnectTimer?.cancel();
    _reconnectTimer = Timer(Duration(milliseconds: _retryInterval), () {
      if (!isClosed) connect();
    });
  }

  /// 发送 Uint8List
  Future<bool> send(Uint8List data) async {
    if (_socket == null || !state.isConnected) return false;
    try {
      _socket!.add(data);
      await _socket!.flush();
      return true;
    } catch (e) {
      return false;
    }
  }

  /// 发送十六进制字符串
  Future<bool> sendHex(String hex) async {
    hex = hex.replaceAll(RegExp(r'\s+'), '');
    if (hex.length % 2 != 0) return false;

    try {
      List<int> bytes = [];
      for (int i = 0; i < hex.length; i += 2) {
        bytes.add(int.parse(hex.substring(i, i + 2), radix: 16));
      }
      return await send(Uint8List.fromList(bytes));
    } catch (e) {
      return false;
    }
  }

  /// 发送字符串 UTF8
  Future<bool> sendString(String msg) async {
    return await send(Uint8List.fromList(msg.codeUnits));
  }

  /// 心跳保活（每 15 秒发送一次）
  void _startHeartbeat() {
    _heartbeatTimer?.cancel();
    _heartbeatTimer = Timer.periodic(const Duration(seconds: 15), (timer) {
      if (state.isConnected) {
        sendHex('00 00 00 00');
      }
    });
  }

  /// 手动断开
  void disconnect() {
    _isManualDisconnect = true;
    _reconnectTimer?.cancel();
    _heartbeatTimer?.cancel();
    _socketSub?.cancel();
    _socketSub = null;
    _socket?.close();
    _socket = null;
    if (!isClosed) {
      emit(state.copyWith(connectionStatus: TcpConnectionStatus.disconnected));
    }
  }

  @override
  Future<void> close() {
    _isManualDisconnect = true;
    _reconnectTimer?.cancel();
    _heartbeatTimer?.cancel();
    _socketSub?.cancel();
    _socketSub = null;
    _socket?.close();
    _socket = null;
    _dataController.close();
    return super.close();
  }
}
