import 'package:shared_preferences/shared_preferences.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; import '../models/taxi_model.dart'; import './supabase_service.dart'; /// Service for managing taxi data and favorites functionality class TaxiService { static TaxiService? _instance; static TaxiService get instance => _instance ??= TaxiService._(); TaxiService._(); final SupabaseClient _client = SupabaseService.client; static const String _favoritesKey = 'favorite_taxi_ids'; /// Get distinct corregimientos from active taxis Future> getCorregimientos() async { try { final response = await _client .from('taxis') .select('corregimiento') .eq('is_active', true) .order('corregimiento'); if (response.isEmpty) return []; // Extract unique corregimientos final Set uniqueCorregimientos = {}; for (final item in response) { final corregimiento = item['corregimiento'] as String?; if (corregimiento != null && corregimiento.isNotEmpty) { uniqueCorregimientos.add(corregimiento); } } return uniqueCorregimientos.toList()..sort(); } catch (e) { throw Exception('Failed to fetch corregimientos: $e'); } } /// Get available shifts List getShifts() { return ['Day', 'Evening', 'Night']; } /// Search taxis with optional corregimiento, shift, and text filters Future> searchTaxis({ String? selectedCorregimiento, String? selectedShift, String? searchText, }) async { try { var query = _client.from('taxis').select('*').eq('is_active', true); // Apply corregimiento filter if (selectedCorregimiento != null && selectedCorregimiento.isNotEmpty) { query = query.eq('corregimiento', selectedCorregimiento); } // Apply shift filter if (selectedShift != null && selectedShift.isNotEmpty) { // Convert display name to database value String dbShift = selectedShift.toLowerCase(); query = query.eq('shift', dbShift); } // Apply text search filter if (searchText != null && searchText.isNotEmpty) { query = query.or('name.ilike.%$searchText%,phone.ilike.%$searchText%'); } final response = await query.order('name'); return response .map((json) => TaxiModel.fromJson(json)) .toList(); } catch (e) { throw Exception('Failed to search taxis: $e'); } } /// Get user's favorite taxi IDs (from Supabase or local storage) Future> getFavoriteTaxiIds() async { try { // Check if user is authenticated final user = _client.auth.currentUser; if (user != null) { // Get favorites from Supabase final response = await _client .from('favorite_taxis') .select('taxi_id') .eq('user_id', user.id); return response .map((item) => item['taxi_id'] as String) .toList(); } else { // Get favorites from local storage return await _getLocalFavorites(); } } catch (e) { // Fallback to local storage if Supabase fails return await _getLocalFavorites(); } } /// Toggle favorite status for a taxi Future toggleFavorite(String taxiId) async { try { final user = _client.auth.currentUser; if (user != null) { // Handle Supabase favorites return await _toggleSupabaseFavorite(user.id, taxiId); } else { // Handle local storage favorites return await _toggleLocalFavorite(taxiId); } } catch (e) { // Fallback to local storage return await _toggleLocalFavorite(taxiId); } } /// Check if taxi is favorited Future isFavorite(String taxiId) async { final favorites = await getFavoriteTaxiIds(); return favorites.contains(taxiId); } /// Handle Supabase favorite toggle Future _toggleSupabaseFavorite(String userId, String taxiId) async { try { // Check if favorite exists final existing = await _client .from('favorite_taxis') .select('id') .eq('user_id', userId) .eq('taxi_id', taxiId) .maybeSingle(); if (existing != null) { // Remove favorite await _client .from('favorite_taxis') .delete() .eq('user_id', userId) .eq('taxi_id', taxiId); return false; } else { // Add favorite await _client.from('favorite_taxis').insert({ 'user_id': userId, 'taxi_id': taxiId, }); return true; } } catch (e) { throw Exception('Failed to toggle Supabase favorite: $e'); } } /// Handle local storage favorite toggle Future _toggleLocalFavorite(String taxiId) async { try { final prefs = await SharedPreferences.getInstance(); final favorites = prefs.getStringList(_favoritesKey) ?? []; if (favorites.contains(taxiId)) { favorites.remove(taxiId); await prefs.setStringList(_favoritesKey, favorites); return false; } else { favorites.add(taxiId); await prefs.setStringList(_favoritesKey, favorites); return true; } } catch (e) { throw Exception('Failed to toggle local favorite: $e'); } } /// Get favorites from local storage Future> _getLocalFavorites() async { try { final prefs = await SharedPreferences.getInstance(); return prefs.getStringList(_favoritesKey) ?? []; } catch (e) { return []; } } /// Clear all local favorites (for testing/reset) Future clearLocalFavorites() async { try { final prefs = await SharedPreferences.getInstance(); await prefs.remove(_favoritesKey); } catch (e) { // Silent fail for clearing favorites } } /// Sync local favorites to Supabase when user authenticates Future syncLocalFavoritesToSupabase() async { try { final user = _client.auth.currentUser; if (user == null) return; final localFavorites = await _getLocalFavorites(); if (localFavorites.isEmpty) return; // Get existing Supabase favorites final supabaseFavorites = await _client .from('favorite_taxis') .select('taxi_id') .eq('user_id', user.id); final existingIds = supabaseFavorites .map((item) => item['taxi_id'] as String) .toSet(); // Add local favorites that don't exist in Supabase final toAdd = localFavorites.where((id) => !existingIds.contains(id)); if (toAdd.isNotEmpty) { final insertData = toAdd .map((taxiId) => {'user_id': user.id, 'taxi_id': taxiId}) .toList(); await _client.from('favorite_taxis').insert(insertData); } // Clear local favorites after successful sync await clearLocalFavorites(); } catch (e) { // Silent fail for sync operation } } }