import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../api/types.dart';
import '../api/client.dart';
import '../api/openapi_config.dart';
import '../services/auth_service.dart';
import '../models/user_profile.dart';
import '../models/delivery_route.dart';
import '../models/delivery.dart';

final authServiceProvider = Provider<AuthService>((ref) {
  return AuthService();
});

final apiClientProvider = Provider<CqrsApiClient>((ref) {
  return CqrsApiClient(config: ApiClientConfig.production);
});

final isAuthenticatedProvider = FutureProvider<bool>((ref) async {
  final authService = ref.watch(authServiceProvider);
  return await authService.isAuthenticated();
});

final userProfileProvider = FutureProvider<UserProfile?>((ref) async {
  final authService = ref.watch(authServiceProvider);
  final token = await authService.getToken();
  if (token == null) return null;
  return authService.decodeToken(token);
});

final authTokenProvider = FutureProvider<String?>((ref) async {
  final authService = ref.watch(authServiceProvider);
  return await authService.getToken();
});

final deliveryRoutesProvider = FutureProvider<List<DeliveryRoute>>((ref) async {
  final token = await ref.read(authTokenProvider.future);

  if (token == null) {
    throw Exception('User not authenticated');
  }

  // Create a new client with auth token
  final authClient = CqrsApiClient(
    config: ApiClientConfig(
      baseUrl: ApiClientConfig.production.baseUrl,
      defaultHeaders: {'Authorization': 'Bearer $token'},
    ),
  );

  final result = await authClient.executeQuery<List<DeliveryRoute>>(
    endpoint: 'simpleDeliveryRouteQueryItems',
    query: _EmptyQuery(),
    fromJson: (json) {
      // API returns data wrapped in object with "data" field
      if (json is Map<String, dynamic>) {
        final data = json['data'];
        if (data is List<dynamic>) {
          return data.map((r) => DeliveryRoute.fromJson(r as Map<String, dynamic>)).toList();
        }
      }
      return [];
    },
  );

  return result.whenSuccess((routes) => routes) ?? [];
});

final deliveriesProvider = FutureProvider.family<List<Delivery>, int>((ref, routeFragmentId) async {
  final token = await ref.read(authTokenProvider.future);

  if (token == null) {
    throw Exception('User not authenticated');
  }

  final authClient = CqrsApiClient(
    config: ApiClientConfig(
      baseUrl: ApiClientConfig.production.baseUrl,
      defaultHeaders: {'Authorization': 'Bearer $token'},
    ),
  );

  final result = await authClient.executeQuery<List<Delivery>>(
    endpoint: 'simpleDeliveriesQueryItems',
    query: _DeliveriesQuery(routeFragmentId: routeFragmentId),
    fromJson: (json) {
      // API returns data wrapped in object with "data" field
      if (json is Map<String, dynamic>) {
        final data = json['data'];
        if (data is List<dynamic>) {
          return data.map((d) => Delivery.fromJson(d as Map<String, dynamic>)).toList();
        }
      }
      return [];
    },
  );

  return result.whenSuccess((deliveries) => deliveries) ?? [];
});

/// Provider to get all deliveries from all routes
final allDeliveriesProvider = FutureProvider<List<Delivery>>((ref) async {
  final routes = await ref.read(deliveryRoutesProvider.future);

  if (routes.isEmpty) {
    return [];
  }

  // Fetch deliveries for all routes
  final deliveriesFutures = routes.map((route) {
    return ref.watch(deliveriesProvider(route.id)).when(
      data: (deliveries) => deliveries,
      loading: () => <Delivery>[],
      error: (_, __) => <Delivery>[],
    );
  });

  // Combine all deliveries
  final allDeliveries = <Delivery>[];
  for (final deliveries in deliveriesFutures) {
    allDeliveries.addAll(deliveries);
  }

  return allDeliveries;
});

// Language notifier for state management
class LanguageNotifier extends Notifier<String> {
  @override
  String build() => 'fr';

  void setLanguage(String lang) => state = lang;
}

final languageProvider = NotifierProvider<LanguageNotifier, String>(() {
  return LanguageNotifier();
});

// Theme mode notifier for manual theme switching
class ThemeModeNotifier extends Notifier<ThemeMode> {
  @override
  ThemeMode build() => ThemeMode.dark;

  void setThemeMode(ThemeMode mode) => state = mode;
}

final themeModeProvider = NotifierProvider<ThemeModeNotifier, ThemeMode>(() {
  return ThemeModeNotifier();
});

class _EmptyQuery implements Serializable {
  @override
  Map<String, Object?> toJson() => {};
}

class _DeliveriesQuery implements Serializable {
  final int routeFragmentId;

  _DeliveriesQuery({required this.routeFragmentId});

  @override
  Map<String, Object?> toJson() => {
    'params': {
      'routeFragmentId': routeFragmentId,
    },
  };
}
