import 'package:dio/dio.dart';
import 'package:networks_sdk/src/data/dto/api_response_wrapper.dart';
import 'package:networks_sdk/src/domain/entities/api_error.dart';
import 'package:networks_sdk/src/domain/entities/api_request_type.dart';
import 'package:networks_sdk/src/domain/entities/http_method.dart';


/// API 请求基类
///
/// 使用侧只需：字段 + path + method，其余全部有默认实现。
///
/// ```dart
/// @JsonSerializable()
/// class LoginRequest extends ApiRequestable<LoginData> {
///   final String email;
///   final String password;
///
///   LoginRequest({required this.email, required this.password});
///
///   factory LoginRequest.fromJson(Map<String, dynamic> json) =>
///       _$LoginRequestFromJson(json);
///   @override
///   Map<String, dynamic> toJson() => _$LoginRequestToJson(this);
///
///   @override
///   String get path => '/auth/login';
///   @override
///   HttpMethod get method => HttpMethod.post;
///   @override
///   bool get includeToken => false;
/// }
///
/// // 文件顶层注册一次（一行）
/// final _reg = registerResponse<LoginData>(LoginData.fromJson);
/// ```
abstract class ApiRequestable<T> {
  /// API 路径（如 '/auth/login'）
  String get path;

  /// HTTP 方法
  HttpMethod get method;

  /// 序列化为 JSON（由 @JsonSerializable 自动生成）
  /// 子类 override 返回 `_$XxxToJson(this)` 即可
  Map<String, dynamic> toJson();

  /// 请求参数 — 默认调用 toJson()，upload 类型返回 null
  /// 绝大多数情况无需 override
  Map<String, dynamic>? get parameters =>
      requestType == ApiRequestType.upload ? null : toJson();

  /// 上传请求的 body — upload 类型 override 此方法
  ///
  /// 支持多种上传格式：
  /// - `FormData` — multipart 表单上传到自有后端
  /// - `Uint8List` — 二进制流上传到 S3 presigned URL
  /// - 其他 Dio 支持的类型
  ///
  /// ```dart
  /// // FormData 上传
  /// @override
  /// Object? get uploadData => FormData.fromMap({
  ///   'file': MultipartFile.fromFileSync(filePath),
  /// });
  ///
  /// // 二进制上传（S3 presigned URL）
  /// @override
  /// Object? get uploadData => fileBytes;  // Uint8List
  /// ```
  Object? get uploadData => null;

  /// 自定义 headers（合并时覆盖默认值）
  Map<String, String>? get customHeaders => null;

  /// 请求类型（默认 request，登录 override 为 login）
  ApiRequestType get requestType => ApiRequestType.request;

  /// 是否在 header 中包含 token（默认 true）
  bool get includeToken => true;

  /// 解码响应 — 自动从 fromJson 注册表查找解码器
  ///
  /// **无需 override**，只要注册了响应类型就能自动解码。
  /// 支持无响应数据的接口（如 logout）：data 为 null 时不查注册表，直接返回 null。
  T? decodeResponse(Response response) {
    try {
      final data = response.data;

      if (data is Map<String, dynamic>) {
        // fromJson 查找延迟到实际需要解码时执行
        // → 无 data 的接口（logout / delete）不会触发 StateError
        T fromJsonObject(Object? json) {
          final fromJsonFunc = fromJsonRegistry[T];

          if (fromJsonFunc == null) {
            throw StateError(
              'fromJson not registered for type $T. '
                  'Add: final _reg = registerResponse<$T>($T.fromJson);',
            );
          }

          if (fromJsonFunc is T Function(Object?)) {
            return fromJsonFunc(json);
          }
          if (json is Map<String, dynamic>) {
            final mapFunc = fromJsonFunc as T Function(Map<String, dynamic>);
            return mapFunc(json);
          }
          throw FormatException('Expected Map<String, dynamic>, got ${json.runtimeType}',);
        }

        final wrapper = ApiResponseWrapper<T>.fromJson(data, fromJsonObject);

        // 业务错误码检查
        if (wrapper.code != 0) {
          throw ApiError.apiError(
            code: wrapper.code,
            message: wrapper.message ?? 'API error (code: ${wrapper.code})',
          );
        }

        return wrapper.data;
      }

      return null;
    } catch (e) {
      if (e is ApiError) rethrow;
      throw ApiError.decodingError(e.toString());
    }
  }
}

// ── fromJson 注册表 ──────────────────────────────────────────────────────────

/// 全局 fromJson 注册表
final fromJsonRegistry = <Type, Function>{};

/// 注册响应类型（标准 `Map<String, dynamic>` 类型）
///
/// 在定义 Response 类的文件顶层调用一次即可：
/// ```dart
/// final _reg = registerResponse<LoginData>(LoginData.fromJson);
/// ```
T Function(Map<String, dynamic>)? registerResponse<T>(T Function(Map<String, dynamic>) fromJson,)
{
  fromJsonRegistry[T] = fromJson;
  return fromJson;
}

/// 注册响应类型（`Object?` 类型，支持 List 等复杂结构）
///
/// ```dart
/// final _reg = registerResponseObject<DeviceList>(DeviceList.fromJson);
/// ```
T Function(Object?)? registerResponseObject<T>(
    T Function(Object?) fromJson,
    ) {
  fromJsonRegistry[T] = fromJson;
  return fromJson;
}
