enum RecipeIngredientAvailabilityStatus {
  exactMatch,
  coveredByPantry,
  substitutable,
  missing,
}

class RecipeIngredientAnalysis {
  final int ingredientId;
  final String rawName;
  final double quantity;
  final String unit;
  final String? note;
  final RecipeIngredientAvailabilityStatus status;
  final int? matchedProductId;
  final String? matchedProductName;
  final String? source;
  final double availableQuantity;
  final double missingQuantity;

  const RecipeIngredientAnalysis({
    required this.ingredientId,
    required this.rawName,
    required this.quantity,
    required this.unit,
    this.note,
    required this.status,
    this.matchedProductId,
    this.matchedProductName,
    this.source,
    required this.availableQuantity,
    required this.missingQuantity,
  });

  factory RecipeIngredientAnalysis.fromJson(Map<String, dynamic> json) {
    final rawStatus = json['status'] as String? ?? 'missing';
    final status = switch (rawStatus) {
      'exact_match' => RecipeIngredientAvailabilityStatus.exactMatch,
      'covered_by_pantry' => RecipeIngredientAvailabilityStatus.coveredByPantry,
      'substitutable' => RecipeIngredientAvailabilityStatus.substitutable,
      _ => RecipeIngredientAvailabilityStatus.missing,
    };

    return RecipeIngredientAnalysis(
      ingredientId: (json['ingredientId'] as num?)?.toInt() ?? 0,
      rawName: (json['rawName'] as String? ?? '').trim(),
      quantity: (json['quantity'] as num? ?? 0).toDouble(),
      unit: json['unit'] as String? ?? '',
      note: json['note'] as String?,
      status: status,
      matchedProductId: (json['matchedProductId'] as num?)?.toInt(),
      matchedProductName: json['matchedProductName'] as String?,
      source: json['source'] as String?,
      availableQuantity: (json['availableQuantity'] as num? ?? 0).toDouble(),
      missingQuantity: (json['missingQuantity'] as num? ?? 0).toDouble(),
    );
  }
}

class RecipeAnalysisSummary {
  final int exactCount;
  final int pantryCount;
  final int substituteCount;
  final int missingCount;

  const RecipeAnalysisSummary({
    required this.exactCount,
    required this.pantryCount,
    required this.substituteCount,
    required this.missingCount,
  });

  factory RecipeAnalysisSummary.fromJson(Map<String, dynamic> json) {
    return RecipeAnalysisSummary(
      exactCount: (json['exactCount'] as num?)?.toInt() ?? 0,
      pantryCount: (json['pantryCount'] as num?)?.toInt() ?? 0,
      substituteCount: (json['substituteCount'] as num?)?.toInt() ?? 0,
      missingCount: (json['missingCount'] as num?)?.toInt() ?? 0,
    );
  }
}

class RecipeShoppingCandidate {
  final int ingredientId;
  final String rawName;
  final double quantity;
  final String unit;
  final double missingQuantity;

  const RecipeShoppingCandidate({
    required this.ingredientId,
    required this.rawName,
    required this.quantity,
    required this.unit,
    required this.missingQuantity,
  });

  factory RecipeShoppingCandidate.fromJson(Map<String, dynamic> json) {
    return RecipeShoppingCandidate(
      ingredientId: (json['ingredientId'] as num?)?.toInt() ?? 0,
      rawName: (json['rawName'] as String? ?? '').trim(),
      quantity: (json['quantity'] as num? ?? 0).toDouble(),
      unit: json['unit'] as String? ?? '',
      missingQuantity: (json['missingQuantity'] as num? ?? 0).toDouble(),
    );
  }
}

class RecipeAnalysis {
  final int recipeId;
  final List<RecipeIngredientAnalysis> ingredients;
  final RecipeAnalysisSummary summary;
  final List<RecipeShoppingCandidate> shoppingListCandidates;

  const RecipeAnalysis({
    required this.recipeId,
    required this.ingredients,
    required this.summary,
    required this.shoppingListCandidates,
  });

  factory RecipeAnalysis.fromJson(Map<String, dynamic> json) {
    final rawIngredients = json['ingredients'] as List<dynamic>? ?? const [];
    final rawShopping = json['shoppingListCandidates'] as List<dynamic>? ?? const [];

    return RecipeAnalysis(
      recipeId: (json['recipeId'] as num?)?.toInt() ?? 0,
      ingredients: rawIngredients
          .map((e) => RecipeIngredientAnalysis.fromJson(e as Map<String, dynamic>))
          .toList(),
      summary: RecipeAnalysisSummary.fromJson(
        json['summary'] as Map<String, dynamic>? ?? const {},
      ),
      shoppingListCandidates: rawShopping
          .map((e) => RecipeShoppingCandidate.fromJson(e as Map<String, dynamic>))
          .toList(),
    );
  }
}
