"""Integration tests for domain term dictionary pipeline."""

from unittest.mock import MagicMock, patch
from uuid import uuid4

import pytest

from src.db.models import DomainTermDictionary
from src.extraction_v2.domain_term_extractor import DomainTermExtractor


class TestDomainDictionaryPipeline:
    """Integration tests for end-to-end domain dictionary flow."""

    @patch("src.knowledge.domain_dictionary_service.DomainDictionaryService")
    @patch("src.extraction_v2.translation_service.TranslationService")
    @patch("sqlalchemy.create_engine")
    @patch("sqlalchemy.orm.Session")
    def test_persist_new_terms_integration(
        self,
        mock_session_class,
        mock_engine,
        mock_translator_class,
        mock_service_class
    ):
        """Should integrate extractor, translator, and service to persist terms."""
        # Mock session and service
        mock_session = MagicMock()
        mock_session_class.return_value.__enter__.return_value = mock_session

        mock_service = MagicMock()
        mock_service.get_existing_terms_set.return_value = set()  # No existing terms
        mock_service_class.return_value = mock_service

        # Mock translator
        mock_translator = MagicMock()
        mock_translator.translate_term.return_value = (
            {"ja": "売上", "en": "revenue", "vi": "doanh thu"},
            True  # Success
        )
        mock_translator_class.return_value = mock_translator

        # Create extractor and persist terms
        extractor = DomainTermExtractor()
        count = extractor.persist_new_terms(
            terms=["revenue", "ebitda"],
            domain_category="finance",
            document_id=uuid4(),
            tenant_id=uuid4(),
            node_id=uuid4(),
        )

        # Verify translations were requested
        assert mock_translator.translate_term.call_count == 2

        # Verify terms were added in batch
        mock_service.add_terms_batch.assert_called_once()
        assert count == 2

    @patch("src.knowledge.domain_dictionary_service.DomainDictionaryService")
    @patch("src.extraction_v2.translation_service.TranslationService")
    @patch("sqlalchemy.create_engine")
    @patch("sqlalchemy.orm.Session")
    def test_persist_new_terms_skips_duplicates(
        self,
        mock_session_class,
        mock_engine,
        mock_translator_class,
        mock_service_class
    ):
        """Should skip terms that already exist in dictionary."""
        # Mock session and service with existing terms
        mock_session = MagicMock()
        mock_session_class.return_value.__enter__.return_value = mock_session

        mock_service = MagicMock()
        mock_service.get_existing_terms_set.return_value = {"revenue", "ebitda"}  # Existing terms
        mock_service_class.return_value = mock_service

        # Mock translator (should not be called)
        mock_translator = MagicMock()
        mock_translator_class.return_value = mock_translator

        # Create extractor and persist terms
        extractor = DomainTermExtractor()
        count = extractor.persist_new_terms(
            terms=["revenue", "ebitda"],
            domain_category="finance",
            tenant_id=uuid4(),
            node_id=uuid4(),
        )

        # Verify no translations were requested (all duplicates)
        assert mock_translator.translate_term.call_count == 0

        # Verify no terms were added
        mock_service.add_terms_batch.assert_not_called()
        assert count == 0

    @patch("src.knowledge.domain_dictionary_service.DomainDictionaryService")
    @patch("src.extraction_v2.translation_service.TranslationService")
    @patch("sqlalchemy.create_engine")
    @patch("sqlalchemy.orm.Session")
    def test_persist_new_terms_handles_translation_failure(
        self,
        mock_session_class,
        mock_engine,
        mock_translator_class,
        mock_service_class
    ):
        """Should mark translation_failed=True when translation fails."""
        # Mock session and service
        mock_session = MagicMock()
        mock_session_class.return_value.__enter__.return_value = mock_session

        mock_service = MagicMock()
        mock_service.get_existing_terms_set.return_value = set()
        mock_service_class.return_value = mock_service

        # Mock translator to return failure
        mock_translator = MagicMock()
        mock_translator.translate_term.return_value = (
            {"ja": None, "en": None, "vi": None},
            False  # Failure
        )
        mock_translator_class.return_value = mock_translator

        # Create extractor and persist terms
        extractor = DomainTermExtractor()
        count = extractor.persist_new_terms(
            terms=["revenue"],
            domain_category="finance",
            tenant_id=uuid4(),
            node_id=uuid4(),
        )

        # Verify term was still added with translation_failed=True
        mock_service.add_terms_batch.assert_called_once()
        added_entries = mock_service.add_terms_batch.call_args[0][0]
        assert len(added_entries) == 1
        assert added_entries[0].translation_failed is True
        assert count == 1

    def test_detect_language_japanese(self):
        """Should detect Japanese language from Hiragana/Katakana."""
        extractor = DomainTermExtractor()
        assert extractor.detect_language("売上") == "ja"
        assert extractor.detect_language("カタカナ") == "ja"

    def test_detect_language_vietnamese(self):
        """Should detect Vietnamese language from diacritics."""
        extractor = DomainTermExtractor()
        assert extractor.detect_language("năng suất") == "vi"
        assert extractor.detect_language("công ty") == "vi"

    def test_detect_language_english(self):
        """Should default to English for ASCII text."""
        extractor = DomainTermExtractor()
        assert extractor.detect_language("revenue") == "en"
        assert extractor.detect_language("ebitda") == "en"
