"""
Language-specific processing functions for English and German.
"""
import spacy
from typing import List, Tuple, Optional
import pandas as pd


def extract_svo_en(doc) -> Tuple[Optional[str], Optional[str], Optional[str]]:
    """
    Extract Subject-Verb-Object from English sentence using spacy.

    Args:
        doc: Spacy Doc object

    Returns:
        Tuple of (subject, verb, object) or (None, None, None)
    """
    subject = None
    verb = None
    obj = None

    for token in doc:
        # Find subject (nsubj)
        if token.dep_ == "nsubj":
            subject = token.text

        # Find main verb (ROOT)
        if token.pos_ == "VERB" and token.dep_ == "ROOT":
            verb = token.text

        # Find object (dobj)
        if token.dep_ == "dobj":
            obj = token.text

    return subject, verb, obj


def extract_svo_de(doc) -> Tuple[Optional[str], Optional[str], Optional[str]]:
    """
    Extract Subject-Verb-Object from German sentence using spacy.

    Uses Tiger annotation scheme for German dependency parsing.

    Args:
        doc: Spacy Doc object

    Returns:
        Tuple of (subject, verb, object) or (None, None, None)
    """
    subject = None
    verb = None
    obj = None

    for token in doc:
        # Find subject (sb - Tiger annotation)
        if token.dep_ in ["sb", "nsubj"]:
            subject = token.text

        # Find main verb (ROOT)
        if token.pos_ == "VERB" and token.dep_ == "ROOT":
            verb = token.text

        # Find object (oa - accusative object in Tiger)
        if token.dep_ in ["oa", "dobj"]:
            obj = token.text

    return subject, verb, obj


def extract_nouns_en(text: str, nlp) -> List[str]:
    """
    Extract nouns from English text.

    Args:
        text: Input text
        nlp: Spacy English model

    Returns:
        List of lemmatized nouns
    """
    doc = nlp(text)
    nouns = [token.lemma_ for token in doc if token.pos_ == "NOUN"]
    return nouns


def extract_nouns_de(text: str, nlp) -> List[str]:
    """
    Extract nouns from German text.

    Args:
        text: Input text
        nlp: Spacy German model

    Returns:
        List of lemmatized nouns
    """
    doc = nlp(text)
    nouns = [token.lemma_ for token in doc if token.pos_ == "NOUN"]
    return nouns


def de_to_concepts(
    df: pd.DataFrame,
    text_column: str = "text",
    nlp=None
) -> List[List[str]]:
    """
    Convert German dataframe to concept lists.

    Args:
        df: DataFrame with German text
        text_column: Name of column containing text
        nlp: Spacy German model (optional, will load if None)

    Returns:
        List of concept lists (one per row)
    """
    if nlp is None:
        nlp = spacy.load("de_core_news_lg")

    concept_lists = []

    for text in df[text_column]:
        if pd.isna(text):
            concept_lists.append([])
            continue

        # Split into sentences
        sentences = [s.strip() for s in text.split('.') if s.strip()]

        # Extract nouns from each sentence
        sentence_concepts = []
        for sentence in sentences:
            nouns = extract_nouns_de(sentence, nlp)
            if nouns:
                sentence_concepts.append(nouns)

        concept_lists.append(sentence_concepts)

    return concept_lists


def detect_language(text: str) -> str:
    """
    Simple language detection for English vs German.

    Args:
        text: Input text

    Returns:
        Language code ('en' or 'de')
    """
    # Simple heuristic: count common English and German words
    english_words = {'the', 'a', 'an', 'and', 'or', 'but', 'is', 'are', 'was', 'were'}
    german_words = {'der', 'die', 'das', 'und', 'oder', 'aber', 'ist', 'sind', 'war', 'waren'}

    words = set(text.lower().split())

    english_count = len(words & english_words)
    german_count = len(words & german_words)

    return 'de' if german_count > english_count else 'en'


def load_language_model(language: str, size: str = "lg"):
    """
    Load appropriate spacy model for language.

    Args:
        language: Language code ('en' or 'de')
        size: Model size ('sm', 'md', 'lg')

    Returns:
        Loaded spacy model
    """
    if language == "en":
        model_name = f"en_core_web_{size}"
    elif language == "de":
        model_name = f"de_core_news_{size}"
    else:
        raise ValueError(f"Unsupported language: {language}")

    try:
        return spacy.load(model_name)
    except OSError:
        print(f"Model {model_name} not found. Downloading...")
        spacy.cli.download(model_name)
        return spacy.load(model_name)


class BilingualProcessor:
    """
    Process text in both English and German.
    """

    def __init__(self, model_size: str = "lg"):
        """
        Initialize with both language models.

        Args:
            model_size: Spacy model size
        """
        self.model_size = model_size
        self.en_nlp = None
        self.de_nlp = None

    def _load_en(self):
        """Lazy load English model."""
        if self.en_nlp is None:
            self.en_nlp = load_language_model("en", self.model_size)
        return self.en_nlp

    def _load_de(self):
        """Lazy load German model."""
        if self.de_nlp is None:
            self.de_nlp = load_language_model("de", self.model_size)
        return self.de_nlp

    def extract_nouns(self, text: str, language: Optional[str] = None) -> List[str]:
        """
        Extract nouns from text, auto-detecting language if not specified.

        Args:
            text: Input text
            language: Language code or None for auto-detection

        Returns:
            List of lemmatized nouns
        """
        if language is None:
            language = detect_language(text)

        if language == "en":
            nlp = self._load_en()
            return extract_nouns_en(text, nlp)
        else:
            nlp = self._load_de()
            return extract_nouns_de(text, nlp)

    def extract_svo(
        self,
        text: str,
        language: Optional[str] = None
    ) -> Tuple[Optional[str], Optional[str], Optional[str]]:
        """
        Extract Subject-Verb-Object, auto-detecting language if not specified.

        Args:
            text: Input text
            language: Language code or None for auto-detection

        Returns:
            Tuple of (subject, verb, object)
        """
        if language is None:
            language = detect_language(text)

        if language == "en":
            nlp = self._load_en()
            doc = nlp(text)
            return extract_svo_en(doc)
        else:
            nlp = self._load_de()
            doc = nlp(text)
            return extract_svo_de(doc)
