import '../../../core/api/api_client.dart';
import '../../../core/api/api_exception.dart';
import '../../../core/api/api_paths.dart';
import '../domain/inventory_compare_item.dart';
import '../domain/meal_plan_entry.dart';
import '../domain/shopping_item.dart';

class MealPlanRepository {
  final ApiClient _api;

  const MealPlanRepository(this._api);

  Future<List<MealPlanEntry>> fetchEntries(String from, String to, {String? token}) async {
    try {
      final dynamic data = await _api.getJson(MealPlanApiPaths.listByRange(from, to), token: token);
      if (data is! List) {
        throw const ApiException(
          type: ApiErrorType.unknown,
          message: 'Ogiltigt svar från servern.',
        );
      }
      return data
          .map((item) => MealPlanEntry.fromJson(item as Map<String, dynamic>))
          .toList();
    } on ApiException {
      rethrow;
    } catch (_) {
      throw const ApiException(
        type: ApiErrorType.network,
        message: 'Kunde inte hämta matsedeln.',
      );
    }
  }

  Future<List<ShoppingItem>> fetchShoppingList(String from, String to, {String? token}) async {
    try {
      final dynamic data = await _api.getJson(MealPlanApiPaths.shoppingList(from, to), token: token);
      if (data is! List) {
        throw const ApiException(
          type: ApiErrorType.unknown,
          message: 'Ogiltigt svar från servern.',
        );
      }
      return data
          .map((item) => ShoppingItem.fromJson(item as Map<String, dynamic>))
          .toList();
    } on ApiException {
      rethrow;
    } catch (_) {
      throw const ApiException(
        type: ApiErrorType.network,
        message: 'Kunde inte hämta inköpslistan.',
      );
    }
  }

  Future<List<InventoryCompareItem>> fetchInventoryCompare(String from, String to, {String? token}) async {
    try {
      final dynamic data = await _api.getJson(MealPlanApiPaths.inventoryCompare(from, to), token: token);
      if (data is! List) {
        throw const ApiException(
          type: ApiErrorType.unknown,
          message: 'Ogiltigt svar från servern.',
        );
      }
      return data
          .map((item) => InventoryCompareItem.fromJson(item as Map<String, dynamic>))
          .toList();
    } on ApiException {
      rethrow;
    } catch (_) {
      throw const ApiException(
        type: ApiErrorType.network,
        message: 'Kunde inte hämta lagerjämförelsen.',
      );
    }
  }

  Future<MealPlanEntry> upsert({
    required String date,
    required int recipeId,
    int? servings,
    String? token,
  }) async {
    try {
      final data = await _api.postJson(
        MealPlanApiPaths.list,
        body: {
          'date': date,
          'recipeId': recipeId,
          'servings': servings,
        },
        token: token,
      );
      if (data is! Map<String, dynamic>) {
        throw const ApiException(
          type: ApiErrorType.unknown,
          message: 'Ogiltigt svar från servern.',
        );
      }
      return MealPlanEntry.fromJson(data);
    } on ApiException {
      rethrow;
    } catch (_) {
      throw const ApiException(
        type: ApiErrorType.network,
        message: 'Kunde inte spara matsedeln.',
      );
    }
  }

  Future<void> deleteByDate(String date, {String? token}) async {
    try {
      await _api.deleteJson(MealPlanApiPaths.removeByDate(date), token: token);
    } on ApiException {
      rethrow;
    } catch (_) {
      throw const ApiException(
        type: ApiErrorType.network,
        message: 'Kunde inte ta bort dagens planering.',
      );
    }
  }
}