import 'dart:typed_data';
import 'package:dio/dio.dart';
import '../navigation/host_app_channel.dart';
import 'api_exception.dart';
import 'api_response.dart';
import 'mock_interceptor.dart';

class ApiClient {
  late final Dio _dio;
  String? _token;
  final String baseUrl;
  final bool useMock;

  ApiClient({required this.baseUrl, this.useMock = false, bool logEnabled = true}) {
    _dio = Dio(BaseOptions(
      baseUrl: baseUrl,
      connectTimeout: const Duration(seconds: 15),
      receiveTimeout: const Duration(minutes: 30),
      headers: {'Content-Type': 'application/json'},
    ));

    if (logEnabled) {
      _dio.interceptors.add(LogInterceptor(
        requestBody: true,
        responseBody: true,
        requestHeader: true,
        responseHeader: false,
      ));
    }

    _dio.interceptors.add(MockInterceptor(enabled: useMock));

    _dio.interceptors.add(InterceptorsWrapper(
      onRequest: (options, handler) {
        // ═══ 动态读取 HostAppChannel 配置（支持登录后刷新） ═══
        options.baseUrl = HostAppChannel.baseUrl;
        if (HostAppChannel.sn.isNotEmpty) {
          options.headers['sn'] = HostAppChannel.sn;
        }
        if (HostAppChannel.loginId.isNotEmpty) {
          options.headers['LoginId'] = HostAppChannel.loginId;
        }
        options.headers['ErpCategory'] = 'MasterService';
        options.headers['Connection'] = 'close';
        options.headers['Accept-Encoding'] = 'identity';

        if (_token != null) {
          options.headers['Authorization'] = 'Bearer $_token';
        }
        handler.next(options);
      },
      onResponse: (response, handler) {
        final body = response.data;
        if (body is Map<String, dynamic>) {
          final code = body['code'] as int? ?? -1;
          if (code != 0) {
            handler.reject(DioException(
              requestOptions: response.requestOptions,
              response: response,
              error: ApiException(
                code: code,
                message: body['message'] as String? ?? '未知错误',
              ),
            ));
            return;
          }
        }
        handler.next(response);
      },
      onError: (error, handler) {
        if (error.type == DioExceptionType.connectionTimeout ||
            error.type == DioExceptionType.receiveTimeout) {
          handler.next(DioException(
            requestOptions: error.requestOptions,
            error: const NetworkException('网络连接超时'),
          ));
          return;
        }
        handler.next(error);
      },
    ));
  }

  void setToken(String? token) => _token = token;

  Future<ApiResponse<T>> get<T>(
    String path, {
    Map<String, dynamic>? queryParameters,
    T Function(dynamic json)? fromJsonT,
  }) async {
    final response = await _dio.get(path, queryParameters: queryParameters);
    return ApiResponse.fromJson(response.data, fromJsonT);
  }

  Future<ApiResponse<T>> post<T>(
    String path, {
    dynamic data,
    T Function(dynamic json)? fromJsonT,
  }) async {
    final response = await _dio.post(path, data: data);
    return ApiResponse.fromJson(response.data, fromJsonT);
  }

  Future<ApiResponse<T>> put<T>(
    String path, {
    dynamic data,
    T Function(dynamic json)? fromJsonT,
  }) async {
    final response = await _dio.put(path, data: data);
    return ApiResponse.fromJson(response.data, fromJsonT);
  }

  Future<ApiResponse<T>> delete<T>(
    String path, {
    T Function(dynamic json)? fromJsonT,
  }) async {
    final response = await _dio.delete(path);
    return ApiResponse.fromJson(response.data, fromJsonT);
  }

  /// 多文件上传（multipart/form-data）
  Future<ApiResponse<T>> uploadMultipart<T>(
    String path, {
    required List<MultipartFile> files,
    Map<String, dynamic>? extraFields,
    T Function(dynamic json)? fromJsonT,
    void Function(int sent, int total)? onSendProgress,
  }) async {
    final formData = FormData();
    for (final file in files) {
      formData.files.add(MapEntry('files', file));
    }
    if (extraFields != null) {
      for (final entry in extraFields.entries) {
        formData.fields.add(MapEntry(entry.key, entry.value.toString()));
      }
    }
    final response = await _dio.post(
      path,
      data: formData,
      onSendProgress: onSendProgress,
    );
    return ApiResponse.fromJson(response.data, fromJsonT);
  }

  /// 下载文件，返回原始字节
  Future<Uint8List?> downloadFile(String path, {Map<String, dynamic>? queryParameters}) async {
    try {
      final response = await _dio.get(
        path,
        queryParameters: queryParameters,
        options: Options(responseType: ResponseType.bytes),
      );
      if (response.data is Uint8List) {
        return response.data as Uint8List;
      }
      return null;
    } catch (_) {
      return null;
    }
  }
}
