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<List<String>> 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<String> 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<String> getShifts() {
    return ['Day', 'Evening', 'Night'];
  }

  /// Search taxis with optional corregimiento, shift, and text filters
  Future<List<TaxiModel>> 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<TaxiModel>((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<List<String>> 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<String>((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<bool> 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<bool> isFavorite(String taxiId) async {
    final favorites = await getFavoriteTaxiIds();
    return favorites.contains(taxiId);
  }

  /// Handle Supabase favorite toggle
  Future<bool> _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<bool> _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<List<String>> _getLocalFavorites() async {
    try {
      final prefs = await SharedPreferences.getInstance();
      return prefs.getStringList(_favoritesKey) ?? [];
    } catch (e) {
      return [];
    }
  }

  /// Clear all local favorites (for testing/reset)
  Future<void> 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<void> 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<String>((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
    }
  }
}