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

import 'package:flutter_webrtc/flutter_webrtc.dart';

import '../../../core/network/api_exception.dart';
import '../../../core/proto/control_message.pb.dart';
import '../../auth/domain/auth_repository.dart';
import '../domain/signal_message.dart';
import 'signaling_client.dart';
import 'webrtc_controller.dart';

/// 控制端编排器：组合信令客户端与 WebRTC 控制器，
/// 对外暴露连接/断开/发送指令等高层接口（对应 Android 端 MainActivity 的流程）。
class RemoteController {
  final String serverUrl;
  final AuthRepository authRepository;
  String? token;

  /// 目标被控端设备ID，在发起远程控制时指定。
  String? targetDeviceId;

  String? authType;
  String? authValue;

  SignalingClient? _signaling;
  WebRtcController? _webRtc;
  Timer? _statsTimer;

  /// 本地设备ID（由服务端 REGISTER_SUCCESS 下发）。
  String? _myDeviceId;

  /// 信令是否已注册成功（拿到本机 deviceId）。
  bool get registered => _myDeviceId != null;

  /// 本机设备ID（未注册时为 null）。
  String? get myDeviceId => _myDeviceId;

  /// 是否已发起远程控制（WebRTC 会话存在）。
  bool get controlling => _webRtc != null;

  /// 信令状态变化（如"正在连接…"、"已连接…）。
  void Function(String status)? onStatusChanged;

  /// WebRTC 连接建立（可开始远程控制）。
  void Function()? onConnectionEstablished;

  /// 连接失败。
  void Function(String error)? onConnectionFailed;

  /// 连接断开。
  void Function()? onDisconnected;

  /// ICE 连接断开（用于提示用户并返回连接设置）。
  void Function(String message)? onIceDisconnected;

  /// 目标被控端不在线（服务器回送 TARGET_OFFLINE，用于提示用户并复位 UI）。
  void Function(String message)? onTargetOffline;

  /// 被控端拒绝了连接请求（用于提示用户并复位 UI）。
  void Function(String message)? onConnectionRejected;

  /// 远端视频渲染器就绪。
  void Function(RTCVideoRenderer renderer)? onRemoteStream;

  /// 统计信息刷新（每秒一次）。
  void Function(String stats)? onStats;

  /// 自编码解码纹理已就绪（textureId >= 0）。
  void Function(int textureId)? onSelfCodecReady;

  /// 自编码解码器已释放（连接断开时）。
  void Function()? onSelfCodecLost;

  /// 被控端上报当前生效的串流模式。
  void Function(int mode)? onStreamModeReport;

  /// 被控端/解码器上报分辨率。
  void Function(int width, int height)? onResolutionReported;

  /// 被控端上报当前采集帧率与支持的帧率档位。
  void Function(int width, int height, int fps, List<int> supportedFps)?
      onFpsReport;

  /// 当前平台不支持原生硬解时回调。
  void Function()? onSelfCodecNotSupported;

  /// 令牌失效（4001）：用于触发刷新重连。
  void Function()? onTokenExpired;

  /// 强制下线（4003）：用于跳回登录。
  void Function()? onForceLogout;

  /// 信令注册成功（下发本机 deviceId），此时可发起远程控制。
  void Function(String myDeviceId)? onRegistered;

  RemoteController({
    required this.serverUrl,
    required this.authRepository,
    this.targetDeviceId,
    this.token,
    this.authType,
    this.authValue,
  });

  /// 仅建立信令连接：确保 accessToken 后携带 Bearer 建立 WebSocket，
  /// 待 REGISTER_SUCCESS 拿到本机 deviceId 即完成，**不会**发起远程控制。
  ///
  /// 发起远程控制请在注册成功后调用 [startControl]。
  Future<void> connectSignaling() async {
    onStatusChanged?.call('状态: 正在连接信令服务器...');

    try {
      token = await _ensureToken();
    } catch (e) {
      onStatusChanged?.call('状态: 认证失败 - $e');
      onConnectionFailed?.call(e.toString());
      return;
    }

    final signaling = SignalingClient(serverUrl: serverUrl, token: token);
    _signaling = signaling;
    signaling.onConnected = () {
      onStatusChanged?.call('状态: 已连接信令服务器，等待注册...');
    };
    signaling.onMessage = _handleSignalMessage;
    signaling.onDisconnected = () {
      _myDeviceId = null;
      onStatusChanged?.call('状态: 已断开连接');
      onDisconnected?.call();
    };
    signaling.onError = (error) {
      onStatusChanged?.call('状态: 连接错误 - $error');
      onConnectionFailed?.call(error);
    };
    signaling.onTokenExpired = () async {
      try {
        await authRepository.refresh();
        token = authRepository.accessToken;
        _reconnect();
      } catch (e) {
        onStatusChanged?.call('状态: 令牌刷新失败 - $e');
        onTokenExpired?.call();
      }
    };
    signaling.onForceLogout = () {
      onStatusChanged?.call('状态: 账号已在其他位置登录，已强制下线');
      onForceLogout?.call();
    };
    signaling.connect();
  }

  /// 发起远程控制：在信令注册成功后调用，建立 WebRTC 并向目标设备创建 Offer。
  ///
  /// [target] 目标被控端设备ID；[authType]/[authValue] 为被控端鉴权方式。
  void startControl({
    required String target,
    String? authType,
    String? authValue,
  }) {
    if (!registered) {
      onConnectionFailed?.call('信令未就绪，请稍后重试');
      return;
    }
    if (_webRtc != null) return;
    targetDeviceId = target;
    this.authType = authType;
    this.authValue = authValue;
    _initWebRtc();
  }

  /// 停止远程控制但保持信令连接（便于重新选择设备发起连接）。
  Future<void> stopControl() async {
    _statsTimer?.cancel();
    _statsTimer = null;
    await _webRtc?.close();
    _webRtc = null;
  }

  /// 确保 accessToken 有效：若已有则校验，失效则用 refreshToken 刷新。
  Future<String> _ensureToken() async {
    final existing = authRepository.accessToken;
    if (existing != null) {
      try {
        await authRepository.verify();
        return existing;
      } on ApiException catch (e) {
        if (e.httpCode != 401) return existing;
      }
    }
    final data = await authRepository.refresh();
    return data['accessToken'] as String;
  }

  void _reconnect() {
    _signaling?.disconnect();
    _signaling?.connect();
  }

  void _initWebRtc() {
    final deviceId = _myDeviceId;
    final signaling = _signaling;
    final target = targetDeviceId;
    if (deviceId == null || signaling == null || target == null) {
      onStatusChanged?.call('状态: 未获取到本机设备ID，连接中止');
      return;
    }
    _webRtc = WebRtcController(
      signaling: signaling,
      deviceId: deviceId,
      targetDeviceId: target,
      authType: authType,
      authValue: authValue,
    );
    _webRtc!.onConnectionEstablished = () {
      onConnectionEstablished?.call();
      _startStats();
    };
    _webRtc!.onConnectionFailed = (error) => onConnectionFailed?.call(error);
    _webRtc!.onDisconnected = () {
      onDisconnected?.call();
    };
    _webRtc!.onIceDisconnected = (message) => onIceDisconnected?.call(message);
    _webRtc!.onRemoteStream = (renderer) => onRemoteStream?.call(renderer);
    _webRtc!.onSelfCodecReady = (id) => onSelfCodecReady?.call(id);
    _webRtc!.onSelfCodecLost = () => onSelfCodecLost?.call();
    _webRtc!.onStreamModeReport = (mode) => onStreamModeReport?.call(mode);
    _webRtc!.onResolutionReported = (w, h) => onResolutionReported?.call(w, h);
    _webRtc!.onFpsReport =
        (w, h, fps, list) => onFpsReport?.call(w, h, fps, list);
    _webRtc!.onSelfCodecNotSupported = () => onSelfCodecNotSupported?.call();
    onStatusChanged?.call('状态: 已注册 ($deviceId)，正在发起连接...');
    _webRtc!.initialize().catchError((e) {
      onStatusChanged?.call('状态: 连接失败 - $e');
      onConnectionFailed?.call(e.toString());
    });
  }

  void _handleSignalMessage(SignalMessage message) {
    final type = message.type?.toUpperCase();
    if (type == 'REGISTER_SUCCESS') {
      // 服务端下发本机 deviceId，作为后续 OFFER 的 fromDeviceId。
      final deviceId = message.fromDeviceId;
      _myDeviceId = deviceId;
      onStatusChanged?.call('状态: 已连接信令服务器 ($deviceId)');
      if (deviceId != null)       onRegistered?.call(deviceId);
      // 尝试用服务端 TURN 凭证覆盖默认 ICE 配置。
      _loadTurnCredentials();
      return;
    }
    switch (type) {
      case 'ANSWER':
        final payload = jsonDecode(message.payload!) as Map<String, dynamic>;
        onStatusChanged?.call('状态: 被控端已接受连接，正在建立连接...');
        _webRtc?.handleAnswer(payload['sdp'] as String);
        break;
      case 'ICE_CANDIDATE':
        final payload = jsonDecode(message.payload!) as Map<String, dynamic>;
        _webRtc?.handleIceCandidate(payload);
        break;
      case 'TARGET_OFFLINE':
        final text = message.payload ?? '目标被控端不在线，请确认设备已开启并连接服务器';
        onStatusChanged?.call('状态: $text');
        onTargetOffline?.call(text);
        break;
      case 'CONNECTION_REJECTED':
      case 'REQUEST_ERROR':
      case 'REQUEST_TIMEOUT':
        final text = _parseRejectReason(message.payload);
        onStatusChanged?.call('状态: $text');
        onConnectionRejected?.call(text);
        break;
    }
  }

  /// 解析拒绝原因：优先读取 JSON 中的 reason 字段，否则直接返回原文。
  String _parseRejectReason(String? payload) {
    if (payload == null || payload.isEmpty) return '连接请求失败';
    try {
      final map = jsonDecode(payload) as Map<String, dynamic>;
      final r = map['reason'];
      if (r is String && r.isNotEmpty) return r;
    } catch (_) {}
    return payload;
  }

  /// 拉取 TURN 短期凭证，覆盖默认 ICE 配置（服务端开启时）。
  Future<void> _loadTurnCredentials() async {
    final data = await authRepository.turnCredentials();
    if (data != null && data['iceServers'] is List) {
      final servers = (data['iceServers'] as List)
          .map((e) => Map<String, dynamic>.from(e as Map))
          .toList();
      if (servers.isNotEmpty) {
        WebRtcController.iceServersOverride = servers;
      }
    }
  }

  void _startStats() {
    _statsTimer?.cancel();
    _statsTimer = Timer.periodic(const Duration(seconds: 1), (_) async {
      final text = await _webRtc?.getStatsText();
      if (text != null && text.isNotEmpty) {
        onStats?.call(text);
      }
    });
  }

  /// 发送控制指令（protobuf 二进制）。
  void sendControlCommand(ControlMessage command) {
    _webRtc?.sendControlCommand(command);
  }

  /// 请求被控端切换屏幕采集分辨率。
  void sendResolutionChange(int width, int height, int fps) {
    _webRtc?.sendResolutionChange(width, height, fps);
  }

  /// 请求被控端切换屏幕串流模式（0=WebRTC 全托管 / 1=自编码）。
  Future<void> sendStreamMode(int mode) =>
      _webRtc?.sendStreamMode(mode) ?? Future.value();

  /// 断开连接并释放资源（同时关闭 WebRTC 与信令）。
  Future<void> disconnect() async {
    await stopControl();
    _signaling?.disconnect();
    _signaling = null;
    _myDeviceId = null;
  }
}
