import 'dart:convert';
import 'dart:io';
import 'package:dio/dio.dart';

enum RequestType { GET, POST, PUT, DELETE }

class MediaType {
  static const String APPLICATION_JSON = "application/json";
  static const String FORM_URLENCODED = "application/x-www-form-urlencoded";
  static const String MULTIPART_FORM = "multipart/form-data";
}

class HTTP {
  String? _url;
  dynamic? _body;
  Map<String, dynamic>? _params; // 新增 params
  Map<String, String>? _header;
  RequestType _requestType = RequestType.GET;
  ContentType? _contentType;

  HTTP._(this._url);

  static HTTP create(String url) => HTTP._(url);

  HTTP setBody(dynamic body) {
    _body = body;
    return this;
  }

  HTTP setParam(Map<String, dynamic> params) {
    _params = params;
    return this;
  }

  HTTP setHeader(Map<String, String> header) {
    _header = header;
    return this;
  }

  HTTP setRequestType(RequestType type) {
    _requestType = type;
    return this;
  }

  HTTP setContentType(ContentType contentType) {
    _contentType = contentType;
    return this;
  }

  bool _hasFile(Map<String, dynamic>? map) {
    if (map == null) return false;
    return map.values.any((element) => element is File);
  }

  Future<dynamic> execute() async {
    try {
      Dio dio = Dio();

      // 设置 header
      if (_header != null) {
        dio.options.headers.addAll(_header!);
      }

      // 自动判断是否有文件
      bool useMultipart = _hasFile(_body) || _hasFile(_params);

      dynamic dataToSend;

      if (useMultipart) {
        FormData formData = FormData();

        void addFields(Map<String, dynamic>? map) {
          if (map == null) return;
          map.forEach((key, value) async {
            if (value is File) {
              String fileName = value.path.split('/').last;
              formData.files.add(
                MapEntry(
                  key,
                  MultipartFile.fromFileSync(value.path, filename: fileName),
                ),
              );
            } else {
              formData.fields.add(MapEntry(key, value.toString()));
            }
          });
        }

        addFields(_body);
        addFields(_params);

        dataToSend = formData;

      } else {
        // 非文件上传
        if (_contentType == MediaType.APPLICATION_JSON) {
          dataToSend = _body != null ? jsonEncode(_body) : null;
        } else if (_contentType == MediaType.FORM_URLENCODED) {
          dataToSend = _body;
        } else {
          dataToSend = _body;
        }
      }
      Response response;
      switch (_requestType) {
        case RequestType.GET:
          response = await dio.get(_url!, queryParameters: _params);
          break;
        case RequestType.POST:
          response = await dio.post(_url!, data: dataToSend, queryParameters: useMultipart ? null : _params);
          break;
        case RequestType.PUT:
          response = await dio.put(_url!, data: dataToSend, queryParameters: useMultipart ? null : _params);
          break;
        case RequestType.DELETE:
          response = await dio.delete(_url!, data: dataToSend, queryParameters: useMultipart ? null : _params);
          break;
      }

      return response.data;
    } catch (e) {
      throw Exception('HTTP request failed: $e');
    }
  }
}
