part of '../../core_app.dart';

const double _pickedImageMaxWidth = 1600;
const double _pickedImageMaxHeight = 1600;
const int _pickedImageQuality = 85;

Future<XFile?> _pickCameraImage(
  ImagePicker imagePicker, {
  bool showPermissionAlert = false,
  WebViewController? controller,
}) async {
  final cameraStatus = await Permission.camera.request();
  if (!cameraStatus.isGranted) {
    if (showPermissionAlert && controller != null) {
      await _showWebAlert(controller, '请先在系统设置中允许相机权限');
    }
    return null;
  }

  try {
    return await imagePicker.pickImage(
      source: ImageSource.camera,
      imageQuality: _pickedImageQuality,
      maxWidth: _pickedImageMaxWidth,
      maxHeight: _pickedImageMaxHeight,
    );
  } on Object catch (error, stackTrace) {
    debugPrint('调用相机拍照失败：$error\n$stackTrace');
    if (showPermissionAlert && controller != null) {
      await _showWebAlert(controller, '无法打开系统相机，请稍后重试');
    }
    return null;
  }
}

Future<List<Map<String, dynamic>>> _serializeXFiles(
  List<XFile> files, {
  required String responseType,
}) async {
  final includeBase64 = responseType == 'base64' || responseType == 'dataUrl';
  final includeDataUrl = responseType == 'dataUrl';

  final serialized = <Map<String, dynamic>>[];
  for (final file in files) {
    String? base64Value;
    final mimeType = _guessMimeType(file.name);

    if (includeBase64 || includeDataUrl) {
      base64Value = base64Encode(await file.readAsBytes());
    }

    serialized.add(<String, dynamic>{
      'name': file.name,
      'uri': Uri.file(file.path).toString(),
      'mimeType': mimeType,
      'size': await file.length(),
      if (responseType == 'base64') 'base64': base64Value,
      if (includeDataUrl && base64Value != null)
        'dataUrl': 'data:$mimeType;base64,$base64Value',
    });
  }
  return serialized;
}

Future<List<Map<String, dynamic>>> _serializePlatformFiles(
  List<PlatformFile> files, {
  required String responseType,
}) async {
  final includeBase64 = responseType == 'base64' || responseType == 'dataUrl';
  final includeDataUrl = responseType == 'dataUrl';

  final serialized = <Map<String, dynamic>>[];
  for (final file in files) {
    final mimeType = _guessMimeType(file.name);
    String? base64Value;

    if (includeBase64 || includeDataUrl) {
      final List<int>? bytes =
          file.bytes ??
          (file.path == null ? null : await XFile(file.path!).readAsBytes());
      if (bytes != null) {
        base64Value = base64Encode(bytes);
      }
    }

    serialized.add(<String, dynamic>{
      'name': file.name,
      'uri': file.path == null ? null : Uri.file(file.path!).toString(),
      'mimeType': mimeType,
      'size': file.size,
      if (responseType == 'base64') 'base64': base64Value,
      if (includeDataUrl && base64Value != null)
        'dataUrl': 'data:$mimeType;base64,$base64Value',
    });
  }
  return serialized;
}

List<String> _xFilesToUriStrings(List<XFile> files) {
  return files.map((file) => Uri.file(file.path).toString()).toList();
}

bool _acceptsImages(List<String> acceptTypes) {
  return acceptTypes
      .map((type) => type.trim())
      .where((type) => type.isNotEmpty)
      .any(_isImageAcceptType);
}

bool _acceptsOnlyImages(List<String> acceptTypes) {
  final normalizedTypes = acceptTypes
      .map((type) => type.trim())
      .where((type) => type.isNotEmpty)
      .toList();
  if (normalizedTypes.isEmpty) {
    return false;
  }
  return normalizedTypes.every(_isImageAcceptType);
}

bool _isImageAcceptType(String acceptType) {
  final value = acceptType.toLowerCase();
  return value.startsWith('image/') ||
      const <String>{
        '.png',
        '.jpg',
        '.jpeg',
        '.webp',
        '.gif',
        '.bmp',
        '.heic',
        '.heif',
      }.contains(value);
}

String _guessMimeType(String fileName) {
  final lower = fileName.toLowerCase();
  if (lower.endsWith('.png')) {
    return 'image/png';
  }
  if (lower.endsWith('.jpg') || lower.endsWith('.jpeg')) {
    return 'image/jpeg';
  }
  if (lower.endsWith('.webp')) {
    return 'image/webp';
  }
  if (lower.endsWith('.gif')) {
    return 'image/gif';
  }
  if (lower.endsWith('.bmp')) {
    return 'image/bmp';
  }
  if (lower.endsWith('.heic')) {
    return 'image/heic';
  }
  if (lower.endsWith('.heif')) {
    return 'image/heif';
  }
  if (lower.endsWith('.pdf')) {
    return 'application/pdf';
  }
  if (lower.endsWith('.txt')) {
    return 'text/plain';
  }
  if (lower.endsWith('.apk')) {
    return 'application/vnd.android.package-archive';
  }
  return 'application/octet-stream';
}

Future<void> _showWebAlert(WebViewController controller, String message) async {
  try {
    await controller.runJavaScript('window.alert(${jsonEncode(message)});');
  } on Object catch (error, stackTrace) {
    debugPrint('展示网页弹窗失败：$error\n$stackTrace');
  }
}

bool _boolValue(Object? value, {bool defaultValue = false}) {
  return switch (value) {
    final bool boolValue => boolValue,
    final String stringValue => stringValue.toLowerCase() == 'true',
    final int intValue => intValue != 0,
    _ => defaultValue,
  };
}
