import 'dart:convert'; import 'dart:typed_data'; import 'package:cloud_functions/cloud_functions.dart'; import 'package:firebase_storage/firebase_storage.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../household/data/household_providers.dart'; /// Ergebnis der KI-Erkennung (PlantNet + Claude über die Cloud Function). class RecognitionResult { const RecognitionResult({ required this.scientificName, required this.germanName, required this.confidence, required this.description, required this.careNotes, required this.wateringIntervalDays, required this.fertilizingIntervalDays, }); final String scientificName; final String germanName; final double confidence; final String description; final String careNotes; final int wateringIntervalDays; final int fertilizingIntervalDays; /// Anzeige-Name: "Fensterblatt (Monstera deliciosa)". String get displaySpecies => germanName.isNotEmpty ? '$germanName ($scientificName)' : scientificName; } class PlantRecognitionService { PlantRecognitionService(this._functions, this._storage, this._householdIdGetter); final FirebaseFunctions _functions; final FirebaseStorage _storage; final String? Function() _householdIdGetter; /// Ruft die Cloud Function auf (PlantNet + Claude) – dauert einige Sekunden. Future identify(Uint8List imageBytes) async { final callable = _functions.httpsCallable('identifyPlant'); final response = await callable.call>({ 'imageBase64': base64Encode(imageBytes), }); final data = response.data; return RecognitionResult( scientificName: data['scientificName'] as String? ?? '', germanName: data['germanName'] as String? ?? '', confidence: (data['confidence'] as num?)?.toDouble() ?? 0, description: data['description'] as String? ?? '', careNotes: data['careNotes'] as String? ?? '', wateringIntervalDays: (data['wateringIntervalDays'] as num?)?.toInt() ?? 7, fertilizingIntervalDays: (data['fertilizingIntervalDays'] as num?)?.toInt() ?? 28, ); } /// Lädt das Foto in den Haushalts-Ordner in Storage und liefert die URL. Future uploadPhoto(Uint8List imageBytes) async { final householdId = _householdIdGetter(); if (householdId == null) { throw StateError('Kein Haushalt geladen – Aktion nicht möglich.'); } final ref = _storage.ref( 'households/$householdId/plant-photos/' '${DateTime.now().millisecondsSinceEpoch}.jpg', ); await ref.putData( imageBytes, SettableMetadata(contentType: 'image/jpeg'), ); return ref.getDownloadURL(); } } final plantRecognitionServiceProvider = Provider((ref) { return PlantRecognitionService( FirebaseFunctions.instanceFor(region: 'europe-west3'), FirebaseStorage.instance, () => ref.read(householdIdProvider).value, ); });