from pathlib import Path
from unittest.mock import MagicMock, patch

import pytest

from transduck.config import TransduckConfig
from transduck.backend import detect_language


def _make_config(**overrides):
    defaults = dict(
        project_name="test", project_context="test",
        source_lang="EN", target_langs=["DE"],
        storage_path=Path("/tmp/test.db"),
        provider="openai", api_key_env="OPENAI_API_KEY", token_env="",
        backend_model="gpt-4.1-mini", backend_timeout=10, backend_max_retries=2,
        read_only=False, shared_url="",
    )
    defaults.update(overrides)
    return TransduckConfig(**defaults)


@patch("transduck.providers.openai_provider.openai")
def test_detect_language_returns_code(mock_openai_module):
    mock_client = MagicMock()
    mock_openai_module.OpenAI.return_value = mock_client
    mock_client.chat.completions.create.return_value = MagicMock(
        choices=[MagicMock(message=MagicMock(content="ES"))]
    )
    cfg = _make_config()
    with patch.dict("os.environ", {"OPENAI_API_KEY": "test-key"}):
        result = detect_language("Hola mundo", cfg)
    assert result == "ES"


@patch("transduck.providers.openai_provider.openai")
def test_detect_language_strips_and_uppercases(mock_openai_module):
    mock_client = MagicMock()
    mock_openai_module.OpenAI.return_value = mock_client
    mock_client.chat.completions.create.return_value = MagicMock(
        choices=[MagicMock(message=MagicMock(content="  de \n"))]
    )
    cfg = _make_config()
    with patch.dict("os.environ", {"OPENAI_API_KEY": "test-key"}):
        result = detect_language("Hallo Welt", cfg)
    assert result == "DE"


@patch("transduck.providers.openai_provider.openai")
def test_detect_language_sends_correct_prompt(mock_openai_module):
    mock_client = MagicMock()
    mock_openai_module.OpenAI.return_value = mock_client
    mock_client.chat.completions.create.return_value = MagicMock(
        choices=[MagicMock(message=MagicMock(content="FR"))]
    )
    cfg = _make_config()
    with patch.dict("os.environ", {"OPENAI_API_KEY": "test-key"}):
        detect_language("Bonjour le monde", cfg)
    call_args = mock_client.chat.completions.create.call_args
    messages = call_args[1]["messages"] if "messages" in call_args[1] else call_args[0][0]
    assert any("ISO 639-1" in m["content"] for m in messages)
    assert any("Bonjour le monde" in m["content"] for m in messages)


def test_detect_language_raises_without_api_key():
    cfg = _make_config()
    with patch.dict("os.environ", {}, clear=True):
        with pytest.raises(RuntimeError, match="Missing API key"):
            detect_language("Hello", cfg)


@patch("transduck.providers.openai_provider.openai")
def test_detect_language_raises_on_api_error(mock_openai_module):
    mock_client = MagicMock()
    mock_openai_module.OpenAI.return_value = mock_client
    mock_client.chat.completions.create.side_effect = Exception("API error")
    cfg = _make_config()
    with patch.dict("os.environ", {"OPENAI_API_KEY": "test-key"}):
        with pytest.raises(Exception, match="API error"):
            detect_language("Hello", cfg)


def test_top_level_detect_language_export():
    """detect_language is importable from transduck top-level."""
    import transduck
    assert hasattr(transduck, "detect_language")
    assert callable(transduck.detect_language)


def test_top_level_detect_language_requires_init():
    """detect_language raises if transduck not initialized."""
    import transduck
    # Reset state
    old_config = transduck._state.config
    transduck._state.config = None
    try:
        with pytest.raises(RuntimeError, match="not initialized"):
            transduck.detect_language("Hello")
    finally:
        transduck._state.config = old_config
