"""Tests for multi-provider LLM summarization."""
from __future__ import annotations

import pytest
from unittest.mock import AsyncMock, MagicMock, patch

from mcp_youtube_intelligence.config import Config
from mcp_youtube_intelligence.core.summarizer import (
    resolve_provider,
    llm_summary,
    summarize,
    extractive_summary,
)


def _make_config(**overrides) -> Config:
    return Config(**overrides)


class TestResolveProvider:
    def test_explicit_openai(self):
        cfg = _make_config(llm_provider="openai", openai_api_key="sk-test")
        assert resolve_provider(cfg) == "openai"

    def test_explicit_anthropic(self):
        cfg = _make_config(llm_provider="anthropic", anthropic_api_key="sk-ant-test")
        assert resolve_provider(cfg) == "anthropic"

    def test_explicit_google(self):
        cfg = _make_config(llm_provider="google", google_api_key="goog-test")
        assert resolve_provider(cfg) == "google"

    def test_auto_prefers_anthropic(self):
        cfg = _make_config(
            llm_provider="auto",
            anthropic_api_key="sk-ant",
            openai_api_key="sk-oai",
            google_api_key="goog",
        )
        assert resolve_provider(cfg) == "anthropic"

    def test_auto_falls_to_openai(self):
        cfg = _make_config(llm_provider="auto", openai_api_key="sk-oai", google_api_key="goog")
        assert resolve_provider(cfg) == "openai"

    def test_auto_falls_to_google(self):
        cfg = _make_config(llm_provider="auto", google_api_key="goog")
        assert resolve_provider(cfg) == "google"

    @patch("mcp_youtube_intelligence.core.summarizer._check_ollama_available", return_value=False)
    def test_auto_no_keys(self, mock_check):
        cfg = _make_config(llm_provider="auto")
        assert resolve_provider(cfg) is None

    def test_invalid_provider(self):
        cfg = _make_config(llm_provider="invalid")
        assert resolve_provider(cfg) is None


@pytest.mark.asyncio
class TestLlmSummary:
    async def test_openai_summary(self):
        cfg = _make_config(llm_provider="openai", openai_api_key="sk-test")
        mock_response = MagicMock()
        mock_response.choices = [MagicMock(message=MagicMock(content="OpenAI summary"))]

        with patch("mcp_youtube_intelligence.core.summarizer._openai_summary", new_callable=AsyncMock) as mock:
            mock.return_value = "OpenAI summary"
            result = await llm_summary("test text", cfg)
            assert result == "OpenAI summary"

    async def test_anthropic_summary(self):
        cfg = _make_config(llm_provider="anthropic", anthropic_api_key="sk-ant")
        with patch("mcp_youtube_intelligence.core.summarizer._anthropic_summary", new_callable=AsyncMock) as mock:
            mock.return_value = "Anthropic summary"
            result = await llm_summary("test text", cfg)
            assert result == "Anthropic summary"

    async def test_google_summary(self):
        cfg = _make_config(llm_provider="google", google_api_key="goog")
        with patch("mcp_youtube_intelligence.core.summarizer._google_summary", new_callable=AsyncMock) as mock:
            mock.return_value = "Google summary"
            result = await llm_summary("test text", cfg)
            assert result == "Google summary"

    async def test_provider_override(self):
        cfg = _make_config(llm_provider="openai", openai_api_key="sk", anthropic_api_key="sk-ant")
        with patch("mcp_youtube_intelligence.core.summarizer._anthropic_summary", new_callable=AsyncMock) as mock:
            mock.return_value = "Anthropic override"
            result = await llm_summary("test text", cfg, provider_override="anthropic")
            assert result == "Anthropic override"

    async def test_no_provider_returns_none(self):
        cfg = _make_config(llm_provider="auto")
        result = await llm_summary("test text", cfg)
        assert result is None

    async def test_failure_falls_back_to_none(self):
        cfg = _make_config(llm_provider="openai", openai_api_key="sk-test")
        with patch("mcp_youtube_intelligence.core.summarizer._openai_summary", new_callable=AsyncMock) as mock:
            mock.side_effect = Exception("API error")
            result = await llm_summary("test text", cfg)
            assert result is None

    async def test_import_error_returns_none(self):
        cfg = _make_config(llm_provider="anthropic", anthropic_api_key="sk-ant")
        with patch("mcp_youtube_intelligence.core.summarizer._anthropic_summary", new_callable=AsyncMock) as mock:
            mock.side_effect = ImportError("no anthropic")
            result = await llm_summary("test text", cfg)
            assert result is None


@pytest.mark.asyncio
class TestSummarize:
    async def test_falls_back_to_extractive(self):
        cfg = _make_config(llm_provider="auto")
        result = await summarize("This is a long enough text for testing purposes. " * 10, config=cfg)
        assert result  # extractive fallback should produce something

    async def test_legacy_api_key_path(self):
        with patch("mcp_youtube_intelligence.core.summarizer._openai_summary", new_callable=AsyncMock) as mock:
            mock.return_value = "legacy result"
            result = await summarize("text", api_key="sk-test", model="gpt-4o-mini")
            assert result == "legacy result"


class TestExtractiveSummary:
    def test_empty(self):
        assert extractive_summary("") == ""

    def test_short_text(self):
        result = extractive_summary("Short text that is not very long at all")
        assert result  # returns something


class TestConfigFromEnv:
    def test_llm_provider_env(self):
        import os
        with patch.dict(os.environ, {"MYI_LLM_PROVIDER": "anthropic", "ANTHROPIC_API_KEY": "sk-ant"}):
            cfg = Config.from_env()
            assert cfg.llm_provider == "anthropic"
            assert cfg.anthropic_api_key == "sk-ant"
