import 'dart:async';

import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';

/// 自编码解码器（控制端）。
///
/// 接收来自 `video` DataChannel 的二进制分片（由被控端 [SelfCodecEncoder] 产生），
/// 通过原生 Android `MediaCodec` 硬解码，并渲染到 Flutter 纹理（`Texture`）。
///
/// 为保证与 `WebRTCControlled` 的编码器在二进制协议上完全一致，协议的
/// 分片重组、H.264 参数集解析与硬解、纹理渲染全部在原生侧完成；
/// 本类仅负责与原生侧通信。对应 Android 端 `SelfCodecDecoder`。
///
/// 注意：原生解码器目前仅在 Android 平台实现。其它平台（Windows / Linux /
/// Web / iOS）调用 [create] 会失败并回调 [onError]，调用方应回退到
/// WebRTC 默认媒体流。
class SelfCodecDecoder {
  static const MethodChannel _channel =
      MethodChannel('com.ttstd.fluttercontroller/self_codec');

  /// 串流模式常量（与 ControlMessage.stream_mode 对齐）。
  static const int streamModeWebRtc = 0;
  static const int streamModeSelfCodec = 1;

  int? _textureId;
  bool _disposed = false;
  bool _handlerSet = false;

  /// 解码输出尺寸变化（宽/高，单位像素）。
  final void Function(int width, int height)? onSize;

  /// 错误回调（如当前平台不支持硬解）。
  final void Function(String error)? onError;

  SelfCodecDecoder({this.onSize, this.onError}) {
    _channel.setMethodCallHandler(_handleNativeCall);
    _handlerSet = true;
  }

  Future<dynamic> _handleNativeCall(MethodCall call) async {
    switch (call.method) {
      case 'onSize':
        final args = call.arguments;
        final w = args is Map ? (args['width'] as int? ?? 0) : 0;
        final h = args is Map ? (args['height'] as int? ?? 0) : 0;
        if (w > 0 && h > 0) onSize?.call(w, h);
        break;
      case 'onError':
        final msg = call.arguments is String ? call.arguments as String : '';
        if (msg.isNotEmpty) onError?.call(msg);
        break;
    }
  }

  /// 创建解码纹理。成功返回纹理 id（>=0），失败返回 null。
  Future<int?> create() async {
    if (_disposed) return null;
    try {
      final id = await _channel.invokeMethod<int>('create');
      if (id == null || id < 0) return null;
      _textureId = id;
      return _textureId;
    } on PlatformException catch (e) {
      onError?.call('创建自编码解码纹理失败: ${e.message}');
      return null;
    } catch (e) {
      onError?.call('创建自编码解码纹理失败: $e');
      return null;
    }
  }

  /// 已创建的纹理 id；未创建或已释放时为 null。
  int? get textureId => _textureId;

  /// 用于渲染解码画面的纹理控件。
  Widget build(BuildContext context) {
    final id = _textureId;
    if (id == null) return const SizedBox.shrink();
    return Texture(textureId: id);
  }

  /// 喂入来自 video DataChannel 的二进制分片。
  Future<void> feed(Uint8List chunk) async {
    if (_disposed || _textureId == null) return;
    try {
      await _channel.invokeMethod<void>('feed', chunk);
    } catch (_) {
      // 解码未就绪或被释放时忽略。
    }
  }

  /// 启用/停用解码（仅自编码模式为 true）。
  Future<void> setEnabled(bool enabled) async {
    if (_disposed || _textureId == null) return;
    try {
      await _channel.invokeMethod<void>('setEnabled', enabled);
    } catch (_) {
      // 忽略。
    }
  }

  /// 读取解码耗时统计。返回包含以下键的 Map（毫秒），失败返回 null：
  /// - lastMs：最近一帧解码耗时；
  /// - avgMs：最近窗口内的平均解码耗时；
  /// - maxMs：峰值解码耗时；
  /// - count：累计已解码帧数。
  Future<Map<String, dynamic>?> getStats() async {
    if (_disposed || _textureId == null) return null;
    try {
      final res = await _channel.invokeMethod<dynamic>('getStats');
      if (res is Map) return res.cast<String, dynamic>();
    } catch (_) {
      // 解码未就绪或被释放时忽略。
    }
    return null;
  }

  /// 释放原生解码资源。重复调用安全。
  Future<void> dispose() async {
    if (_disposed) return;
    _disposed = true;
    if (_handlerSet) {
      _channel.setMethodCallHandler(null);
      _handlerSet = false;
    }
    try {
      await _channel.invokeMethod<void>('dispose');
    } catch (_) {
      // 忽略。
    }
    _textureId = null;
  }
}
