from django_tenants.test.cases import TenantTestCase
from products.services import BouquetNameGenerator
from products.models import BouquetName, ProductTag
from unittest.mock import patch, MagicMock


class BouquetNameGeneratorTestCase(TenantTestCase):
    """
    Тесты для сервиса генерации названий букетов
    """

    def setUp(self):
        """
        Создаем экземпляр сервиса для тестирования
        """
        self.generator = BouquetNameGenerator()

    @patch('products.services.ai.bouquet_names.BouquetNameGenerator.get_glm_service')
    def test_generate_with_mock_glm(self, mock_get_glm_service):
        """
        Тест генерации названий с мок-объектом GLM сервиса
        """
        # Создаем мок-объект сервиса
        mock_service = MagicMock()
        mock_service.generate_text.return_value = (
            True,
            "Текст успешно сгенерирован",
            {
                'generated_text': (
                    "1. Розавая мечта\n"
                    "2. Лиловые настроения\n"
                    "3. Яркий букет для дня рождения\n"
                    "4. Сладкий сюрприз\n"
                    "5. Романтическое вдохновение"
                ),
                'model': 'glm-4',
                'usage': {'prompt_tokens': 100, 'completion_tokens': 50}
            }
        )
        mock_get_glm_service.return_value = mock_service

        # Вызываем метод генерации
        success, msg, data = self.generator.generate(count=5)

        # Проверки
        self.assertTrue(success)
        self.assertIn("Сгенерировано 5 названий для букетов", msg)
        self.assertIsNotNone(data)
        self.assertIn('names', data)
        self.assertEqual(len(data['names']), 5)
        self.assertEqual(data['model'], 'glm-4')
        self.assertIn('usage', data)

        # Проверяем, что названия содержат нужные слова
        expected_names = [
            "Розавая мечта",
            "Лиловые настроения",
            "Яркий букет для дня рождения",
            "Сладкий сюрприз",
            "Романтическое вдохновение"
        ]
        self.assertEqual(data['names'], expected_names)

    @patch('products.services.ai.bouquet_names.BouquetNameGenerator.get_glm_service')
    @patch('products.services.ai.bouquet_names.BouquetNameGenerator.get_openrouter_service')
    def test_no_active_integration(self, mock_get_openrouter, mock_get_glm):
        """
        Тест случая, когда нет активных интеграций
        """
        mock_get_glm.return_value = None
        mock_get_openrouter.return_value = None

        success, msg, data = self.generator.generate(count=10)

        self.assertFalse(success)
        self.assertEqual(msg, "Нет активных AI-интеграций")
        self.assertIsNone(data)

    @patch('products.services.ai.bouquet_names.BouquetNameGenerator.get_glm_service')
    def test_generate_with_characteristics(self, mock_get_glm_service):
        """
        Тест генерации с характеристиками
        """
        # Создаем мок-объект сервиса
        mock_service = MagicMock()
        mock_service.generate_text.return_value = (
            True,
            "Текст успешно сгенерирован",
            {
                'generated_text': (
                    "1. Ромашковое небо\n"
                    "2. Лавандовый спокойствие\n"
                    "3. Свежие ароматы\n"
                    "4. Милая композиция\n"
                    "5. Нежный букет"
                ),
                'model': 'glm-4',
                'usage': {'prompt_tokens': 120, 'completion_tokens': 45}
            }
        )
        mock_get_glm_service.return_value = mock_service

        success, msg, data = self.generator.generate(
            count=5,
            characteristics="ромашки, лаванда, свежие",
            occasion="день матери"
        )

        self.assertTrue(success)
        self.assertIn("Сгенерировано 5 названий для букетов", msg)
        self.assertEqual(len(data['names']), 5)
        # Проверяем, что сервис был вызван с нужными параметрами
        mock_service.generate_text.assert_called_once()

    def test_parse_response_with_markdown(self):
        """
        Тест парсинга ответа с Markdown форматированием
        """
        response_text = """
Here are 3 beautiful bouquet names for you:

1. **Spring Blossom Delight**
2. *Romantic Rose Elegance*
3. "Sunny Daisy Joy"

I hope you love these!
        """

        names = self.generator._parse_response(response_text)
        self.assertEqual(len(names), 3)
        self.assertEqual(names[0], "Spring Blossom Delight")
        self.assertEqual(names[1], "Romantic Rose Elegance")
        self.assertEqual(names[2], "Sunny Daisy Joy")

    def test_parse_response_with_duplicates(self):
        """
        Тест парсинга ответа с дубликатами
        """
        response_text = """
1. Розавая мечта
2. Лиловые настроения
3. Розавая мечта
4. Сладкий сюрприз
5. Лиловые настроения
        """

        names = self.generator._parse_response(response_text)
        self.assertEqual(len(names), 3)
        self.assertIn("Розавая мечта", names)
        self.assertIn("Лиловые настроения", names)
        self.assertIn("Сладкий сюрприз", names)

    def test_parse_response_empty(self):
        """
        Тест парсинга пустого ответа
        """
        response_text = """
        """
        names = self.generator._parse_response(response_text)
        self.assertEqual(len(names), 0)

    def test_parse_response_no_names(self):
        """
        Тест парсинга ответа без названий
        """
        response_text = """
I'm sorry, but I can't help with that right now.
        """
        names = self.generator._parse_response(response_text)
        self.assertEqual(len(names), 0)

    @patch('products.services.ai.bouquet_names.BouquetNameGenerator.get_glm_service')
    def test_generate_and_store(self, mock_get_glm_service):
        """
        Тест генерации и сохранения названий в базе данных
        """
        # Создаем мок-объект сервиса
        mock_service = MagicMock()
        mock_service.generate_text.return_value = (
            True,
            "Текст успешно сгенерирован",
            {
                'generated_text': (
                    "1. Розавая мечта\n"
                    "2. Лиловые настроения\n"
                    "3. Яркий букет для дня рождения"
                ),
                'model': 'glm-4',
                'usage': {'prompt_tokens': 100, 'completion_tokens': 50}
            }
        )
        mock_get_glm_service.return_value = mock_service

        # Очищаем базу перед тестом
        BouquetName.objects.all().delete()

        # Вызываем метод генерации и сохранения
        success, msg, data = self.generator.generate_and_store(count=3)

        self.assertTrue(success)
        self.assertIn("Сгенерировано и сохранено 3 названий для букетов", msg)
        self.assertEqual(BouquetName.objects.count(), 3)

    def test_mark_as_used(self):
        """
        Тест увеличения счетчика использования названия
        """
        # Создаем тестовое название
        bouquet_name = BouquetName.objects.create(
            name="Тестовый букет",
            language="russian",
            is_approved=True
        )

        # Проверяем начальное значение счетчика
        self.assertEqual(bouquet_name.usage_count, 0)

        # Увеличиваем счетчик
        self.generator.mark_as_used("Тестовый букет", "russian")

        # Проверяем обновленное значение
        bouquet_name.refresh_from_db()
        self.assertEqual(bouquet_name.usage_count, 1)

    def test_get_approved_names(self):
        """
        Тест получения одобренных названий
        """
        # Очищаем базу перед тестом
        BouquetName.objects.all().delete()

        # Создаем тестовые данные
        BouquetName.objects.create(
            name="Одобренный букет 1",
            language="russian",
            is_approved=True
        )
        BouquetName.objects.create(
            name="Одобренный букет 2",
            language="russian",
            is_approved=True
        )
        BouquetName.objects.create(
            name="Неодобренный букет",
            language="russian",
            is_approved=False
        )

        # Получаем одобренные названия
        approved_names = self.generator.get_approved_names(language="russian")

        self.assertEqual(len(approved_names), 2)
        self.assertIn("Одобренный букет 1", approved_names)
        self.assertIn("Одобренный букет 2", approved_names)
        self.assertNotIn("Неодобренный букет", approved_names)

    def test_bouquet_name_model(self):
        """
        Тест создания и работы с моделью BouquetName
        """
        # Создаем тестовые теги
        red_tag = ProductTag.objects.create(name="красный", slug="krasny")
        romantic_tag = ProductTag.objects.create(name="романтический", slug="romanticheskiy")

        # Создаем экземпляр модели
        bouquet_name = BouquetName.objects.create(
            name="Романтический букет",
            language="russian",
            is_approved=True
        )

        # Добавляем теги
        bouquet_name.color_tags.add(red_tag)
        bouquet_name.style_tags.add(romantic_tag)

        # Проверяем сохраненные значения
        self.assertEqual(bouquet_name.name, "Романтический букет")
        self.assertEqual(bouquet_name.language, "russian")
        self.assertTrue(bouquet_name.is_approved)
        self.assertEqual(bouquet_name.usage_count, 0)
        self.assertIn(red_tag, bouquet_name.color_tags.all())
        self.assertIn(romantic_tag, bouquet_name.style_tags.all())

        # Обновляем поле
        bouquet_name.usage_count = 5
        bouquet_name.save()

        # Проверяем обновление
        updated_name = BouquetName.objects.get(id=bouquet_name.id)
        self.assertEqual(updated_name.usage_count, 5)
