"""Tests for LLMClient task methods — TDDAB-2."""

import pytest

from neo_cortex.llm import LLMClient


class RecordingClient(LLMClient):
    """Mock that records call() args and returns a fixed response."""

    def __init__(self):
        super().__init__()
        self.last_prompt = None
        self.last_text = None
        self.last_max_tokens = None
        self.last_temperature = None
        self._response = '{"test": true}'

    async def call(self, prompt, text, max_tokens=250, temperature=0.1):
        self.last_prompt = prompt
        self.last_text = text
        self.last_max_tokens = max_tokens
        self.last_temperature = temperature
        return self._response

    async def close(self):
        pass

    @property
    def name(self):
        return "test/mock"


@pytest.mark.asyncio
async def test_distill_uses_correct_params():
    c = RecordingClient()
    await c.distill("some turns")
    assert c.last_max_tokens == 16000
    assert c.last_temperature == 0.2
    assert "KNOWLEDGE DISTILLER" in c.last_prompt


@pytest.mark.asyncio
async def test_classify_uses_correct_params():
    c = RecordingClient()
    await c.classify("some text")
    assert c.last_max_tokens == 500
    assert c.last_temperature == 0.1


@pytest.mark.asyncio
async def test_check_noise_uses_temp_03():
    c = RecordingClient()
    await c.check_noise("question")
    assert c.last_temperature == 0.3
    assert c.last_max_tokens == 60


@pytest.mark.asyncio
async def test_resolve_conflict_assembles_prompt():
    c = RecordingClient()
    await c.resolve_conflict("new text", "My Title", "My Summary", '["fact1"]')
    assert "My Title" in c.last_prompt
    assert "My Summary" in c.last_prompt
    assert "fact1" in c.last_prompt


@pytest.mark.asyncio
async def test_generate_insight_formats_focal_point():
    c = RecordingClient()
    await c.generate_insight("How do I debug?", "evidence here")
    assert "How do I debug?" in c.last_prompt


@pytest.mark.asyncio
async def test_verify_truthfulness_formats_claim():
    c = RecordingClient()
    await c.verify_truthfulness("Claim X is true", "evidence")
    assert "Claim X is true" in c.last_prompt


@pytest.mark.asyncio
async def test_strip_fences_on_json_methods():
    c = RecordingClient()
    c._response = '```json\n{"test": true}\n```'
    result = await c.classify("text")
    assert result == '{"test": true}'


@pytest.mark.asyncio
async def test_no_strip_on_non_json_methods():
    c = RecordingClient()
    c._response = "SUPPORTED because evidence matches"
    result = await c.verify_truthfulness("claim", "evidence")
    assert result == "SUPPORTED because evidence matches"


@pytest.mark.asyncio
async def test_anthropic_uses_calibrated_prompts():
    """AnthropicClient._prompts should have the shorter distill prompt."""
    from neo_cortex.prompts import DEFAULT_PROMPTS
    from neo_cortex.prompts.anthropic import ANTHROPIC_PROMPTS
    prompts = dict(DEFAULT_PROMPTS)
    prompts.update(ANTHROPIC_PROMPTS)
    assert prompts["distill"] != DEFAULT_PROMPTS["distill"]
    assert len(prompts["distill"]) < len(DEFAULT_PROMPTS["distill"])


@pytest.mark.asyncio
async def test_groq_uses_default_prompts():
    """GroqClient has no override — uses default prompts."""
    from neo_cortex.prompts import DEFAULT_PROMPTS
    from neo_cortex.prompts.gemini import GEMINI_PROMPTS
    # Groq has no prompts file — stays with DEFAULT
    prompts = dict(DEFAULT_PROMPTS)
    prompts.update(GEMINI_PROMPTS)  # Gemini also empty
    assert prompts["distill"] == DEFAULT_PROMPTS["distill"]
