import json
import unittest
from config import get_config
from models.recipe_model import RecipeGenerator
from services.search_service import RecipeSearchService
from services.nutrition_service import NutritionService

class TestConfiguration(unittest.TestCase):
    
    def test_config_loading(self):
        config = get_config('development')
        self.assertIsNotNone(config)
        self.assertEqual(config.DEBUG, True)
    
    def test_production_config(self):
        config = get_config('production')
        self.assertEqual(config.DEBUG, False)


class TestRecipeModel(unittest.TestCase):
    
    def setUp(self):
        self.generator = RecipeGenerator()
    
    def test_model_loading(self):
        self.assertTrue(self.generator.is_available())
    
    def test_recipe_generation(self):
        if self.generator.is_available():
            recipe = self.generator.generate_recipe(
                ingredients=["chicken", "garlic"],
                meal_type="dinner",
                num_words=50
            )
            self.assertIsNotNone(recipe)
            self.assertGreater(len(recipe), 10)
    
    def test_batch_generation(self):
        if self.generator.is_available():
            recipes = self.generator.generate_batch(
                ingredients_list=[["chicken"], ["beef"]],
                meal_type="dinner",
                num_words=50
            )
            self.assertEqual(len(recipes), 2)


class TestSearchService(unittest.TestCase):
    
    def setUp(self):
        self.service = RecipeSearchService()
    
    def test_recipes_loaded(self):
        self.assertGreater(len(self.service.recipes), 0)
    
    def test_search_by_ingredients(self):
        results = self.service.search_by_ingredients(["chicken"])
        self.assertGreater(len(results), 0)
    
    def test_search_by_meal_type(self):
        results = self.service.search_by_meal_type("breakfast")
        self.assertGreater(len(results), 0)
    
    def test_search_by_cooking_time(self):
        results = self.service.search_by_cooking_time(30)
        self.assertGreater(len(results), 0)
    
    def test_search_by_difficulty(self):
        results = self.service.search_by_difficulty("easy")
        self.assertGreater(len(results), 0)
    
    def test_advanced_search(self):
        results = self.service.advanced_search(
            meal_type="dinner",
            max_cooking_time=40
        )
        self.assertGreater(len(results), 0)
    
    def test_get_recipe_by_id(self):
        recipe = self.service.get_recipe_by_id(1)
        self.assertIsNotNone(recipe)
        self.assertEqual(recipe["id"], 1)


class TestNutritionService(unittest.TestCase):
    
    def setUp(self):
        self.service = NutritionService()
    
    def test_nutrition_info_exists(self):
        nutrition = self.service.get_nutrition_info("chicken")
        self.assertIsNotNone(nutrition)
        self.assertIn("calories", nutrition)
    
    def test_nutrition_info_scaling(self):
        nutrition_100g = self.service.get_nutrition_info("chicken", 100)
        nutrition_200g = self.service.get_nutrition_info("chicken", 200)
        
        self.assertAlmostEqual(
            nutrition_200g["calories"],
            nutrition_100g["calories"] * 2,
            delta=1
        )
    
    def test_recipe_analysis(self):
        nutrition = self.service.analyze_recipe(
            ingredients=["100g chicken", "50ml olive oil"],
            servings=2
        )
        
        self.assertIn("total_nutrition", nutrition)
        self.assertIn("per_serving", nutrition)
        self.assertEqual(nutrition["servings"], 2)
    
    def test_daily_value_percentages(self):
        nutrition = self.service.analyze_recipe(
            ingredients=["100g chicken"],
            servings=1
        )
        
        percentages = self.service.get_daily_value_percentages(
            nutrition,
            "per_serving"
        )
        
        self.assertIn("calories", percentages)
        self.assertGreater(percentages["calories"], 0)
    
    def test_nutrition_summary(self):
        nutrition = self.service.analyze_recipe(
            ingredients=["100g chicken"],
            servings=1
        )
        
        summary = self.service.get_nutrition_summary(nutrition)
        self.assertIn("Calories", summary)
        self.assertIn("Protein", summary)


class TestIntegration(unittest.TestCase):
    
    def setUp(self):
        self.search_service = RecipeSearchService()
        self.nutrition_service = NutritionService()
        self.recipe_generator = RecipeGenerator()
    
    def test_search_and_nutrition(self):
        # Search for a recipe
        recipes = self.search_service.search_by_meal_type("lunch")
        self.assertGreater(len(recipes), 0)
        
        # Get nutrition for the recipe
        recipe = recipes[0]
        nutrition = self.nutrition_service.analyze_recipe(
            ingredients=recipe["ingredients"]
        )
        
        self.assertIn("total_nutrition", nutrition)
    
    def test_generate_and_analyze(self):
        if self.recipe_generator.is_available():
            # Generate recipe
            recipe_text = self.recipe_generator.generate_recipe(
                ingredients=["chicken", "tomato"],
                num_words=50
            )
            self.assertGreater(len(recipe_text), 10)
            
            # Analyze nutrition for those ingredients
            nutrition = self.nutrition_service.analyze_recipe(
                ingredients=["chicken", "tomato"]
            )
            
            self.assertIn("total_nutrition", nutrition)


def run_tests():

    print("\n" + "="*60)
    print(" AI Recipe Generator - Test Suite")
    print("="*60 + "\n")
    
    loader = unittest.TestLoader()
    suite = unittest.TestSuite()
    suite.addTests(loader.loadTestsFromTestCase(TestConfiguration))
    suite.addTests(loader.loadTestsFromTestCase(TestSearchService))
    suite.addTests(loader.loadTestsFromTestCase(TestNutritionService))
    suite.addTests(loader.loadTestsFromTestCase(TestRecipeModel))
    suite.addTests(loader.loadTestsFromTestCase(TestIntegration))
    runner = unittest.TextTestRunner(verbosity=2)
    result = runner.run(suite)
    
    # Print summary
    print("\n" + "="*60)
    print("Test Summary")
    print("="*60)
    print(f"Tests run: {result.testsRun}")
    print(f"Successes: {result.testsRun - len(result.failures) - len(result.errors)}")
    print(f"Failures: {len(result.failures)}")
    print(f"Errors: {len(result.errors)}")
    print("="*60 + "\n")
    
    return result.wasSuccessful()


if __name__ == '__main__':
    success = run_tests()
    exit(0 if success else 1)
