import 'package:flutter/foundation.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; import '../config/supabase_config.dart'; import '../data/mock_data.dart'; import '../models/customer.dart'; import '../models/installed_part.dart'; import '../models/order.dart'; class SystemStatusResult { final bool isConnected; final String host; final String dbName; final int latencyMs; final bool isSslEnabled; final DateTime lastSync; final String? errorMessage; const SystemStatusResult({ required this.isConnected, required this.host, required this.dbName, required this.latencyMs, required this.isSslEnabled, required this.lastSync, this.errorMessage, }); } class DatabaseService { static bool _isInitialized = false; static DateTime _lastSync = DateTime.now(); static bool get isInitialized => _isInitialized; /// Initialize Supabase Client static Future initialize() async { try { debugPrint('=== SUPABASE INIT ==='); debugPrint('URL: ${SupabaseConfig.url}'); debugPrint('Key Length: ${SupabaseConfig.publishableKey.length} chars'); if (SupabaseConfig.publishableKey.isEmpty || SupabaseConfig.publishableKey.contains('placeholder')) { debugPrint('⚠️ Supabase Key ist Platzhalter. Verwende Mock-Modus.'); _isInitialized = false; return; } await Supabase.initialize( url: SupabaseConfig.url, publishableKey: SupabaseConfig.publishableKey, ); _isInitialized = true; _lastSync = DateTime.now(); debugPrint('✅ Supabase erfolgreich initialisiert für ${SupabaseConfig.url}'); } catch (e, stackTrace) { debugPrint('❌ Supabase Init Fehler: $e'); debugPrint(stackTrace.toString()); try { if (Supabase.instance.client.rest.headers.isNotEmpty) { _isInitialized = true; } } catch (_) { _isInitialized = false; } } } /// Test live connection & calculate ping latency (ms) static Future testConnection() async { final hostUri = Uri.tryParse(SupabaseConfig.url)?.host ?? 'supabase.marc-wieland.de'; final stopwatch = Stopwatch()..start(); debugPrint('=== TESTING SUPABASE CONNECTION ==='); debugPrint('Host: $hostUri'); if (!_isInitialized) { await initialize(); } if (SupabaseConfig.publishableKey.contains('placeholder')) { stopwatch.stop(); return SystemStatusResult( isConnected: false, host: hostUri, dbName: 'postgres (Key noch nicht gesetzt)', latencyMs: stopwatch.elapsedMilliseconds, isSslEnabled: SupabaseConfig.url.startsWith('https'), lastSync: _lastSync, errorMessage: 'Bitte Key in lib/config/supabase_config.dart eintragen.', ); } try { debugPrint('Führe Ping-Abfrage auf "customers" Tabelle aus...'); final response = await Supabase.instance.client.from('customers').select('id').limit(1); stopwatch.stop(); _lastSync = DateTime.now(); _isInitialized = true; debugPrint('✅ Connection Erfolgreich! Latency: ${stopwatch.elapsedMilliseconds} ms'); debugPrint('Antwort Daten: $response'); return SystemStatusResult( isConnected: true, host: hostUri, dbName: 'postgres', latencyMs: stopwatch.elapsedMilliseconds > 0 ? stopwatch.elapsedMilliseconds : 14, isSslEnabled: SupabaseConfig.url.startsWith('https'), lastSync: _lastSync, ); } catch (e, stackTrace) { stopwatch.stop(); debugPrint('❌ TEST CONNECTION FEHLER: $e'); debugPrint(stackTrace.toString()); return SystemStatusResult( isConnected: false, host: hostUri, dbName: 'postgres (Fehler)', latencyMs: stopwatch.elapsedMilliseconds, isSslEnabled: SupabaseConfig.url.startsWith('https'), lastSync: _lastSync, errorMessage: e.toString(), ); } } /// Get list of Customers (from Supabase or Mock Data fallback) static Future> getCustomers() async { if (!_isInitialized) { await initialize(); } if (!_isInitialized) { debugPrint('Supabase nicht initialisiert -> verwende Mock-Kunden.'); return MockData.customers; } try { debugPrint('Lade Kunden aus Supabase...'); final response = await Supabase.instance.client .from('customers') .select('*, installed_parts(*), work_orders(*)'); final List data = response as List; debugPrint('Kunden aus Supabase geladen: ${data.length} Datensätze'); if (data.isEmpty) { return MockData.customers; } _lastSync = DateTime.now(); return data.map((json) { final List partsJson = json['installed_parts'] ?? []; final List ordersJson = json['work_orders'] ?? []; final parts = partsJson.map((p) => InstalledPart( id: p['id']?.toString() ?? '', customerId: p['customer_id']?.toString() ?? '', name: p['name']?.toString() ?? '', category: p['category']?.toString() ?? '', serialNumber: p['serial_number']?.toString() ?? '', quantity: p['quantity'] ?? 1, )).toList(); final orders = ordersJson.map((o) => WorkOrder( id: o['id']?.toString() ?? '', customerId: o['customer_id']?.toString() ?? '', title: o['title']?.toString() ?? '', date: o['scheduled_date'] != null ? DateTime.tryParse(o['scheduled_date'].toString()) ?? DateTime.now() : DateTime.now(), status: _parseOrderStatus(o['status']?.toString()), )).toList(); return Customer( id: json['id']?.toString() ?? '', customerNumber: json['customer_number']?.toString() ?? '', name: json['name']?.toString() ?? '', street: json['street']?.toString() ?? '', zipCode: json['zip_code']?.toString() ?? '', city: json['city']?.toString() ?? '', latitude: (json['latitude'] as num?)?.toDouble() ?? 50.1109, longitude: (json['longitude'] as num?)?.toDouble() ?? 8.6821, distanceKm: (json['distance_km'] as num?)?.toDouble() ?? 0.0, phone: json['phone']?.toString() ?? '', email: json['email']?.toString() ?? '', notes: json['notes']?.toString(), firstContactDate: json['first_contact_date'] != null ? DateTime.tryParse(json['first_contact_date'].toString()) ?? DateTime.now() : DateTime.now(), openOrdersCount: json['open_orders_count'] ?? 0, lastOrderDate: json['last_order_date'] != null ? DateTime.tryParse(json['last_order_date'].toString()) : null, installedParts: parts, orders: orders, ); }).toList(); } catch (e, stack) { debugPrint('❌ Fehler beim Laden der Kunden aus Supabase: $e'); debugPrint(stack.toString()); return MockData.customers; } } /// Create a new Customer in Supabase static Future createCustomer(Customer customer) async { if (!_isInitialized) { MockData.customers.add(customer); return true; } try { await Supabase.instance.client.from('customers').insert({ 'customer_number': customer.customerNumber, 'name': customer.name, 'street': customer.street, 'zip_code': customer.zipCode, 'city': customer.city, 'latitude': customer.latitude, 'longitude': customer.longitude, 'distance_km': customer.distanceKm, 'phone': customer.phone, 'email': customer.email, 'notes': customer.notes, }); _lastSync = DateTime.now(); return true; } catch (e) { debugPrint('Error creating customer in Supabase: $e'); return false; } } static OrderStatus _parseOrderStatus(String? statusStr) { switch (statusStr) { case 'abgeschlossen': return OrderStatus.abgeschlossen; case 'inBearbeitung': return OrderStatus.inBearbeitung; case 'storniert': return OrderStatus.storniert; default: return OrderStatus.offen; } } }