"""
Unit tests for extractor.py — mock fallback and LangExtract wrapper logic.
"""

import asyncio
import time

import pytest

from src.extractor import extract, _mock_extract
from src.models import ExtractResponse


@pytest.mark.asyncio
async def test_mock_extract_detects_meeting():
    """Mock extractor identifies meeting-related keywords."""
    result = await extract(
        text="We had a meeting to discuss the project timeline",
        model_id="gemini-2.5-flash-mock",
    )
    assert isinstance(result, ExtractResponse)
    assert any(e.extraction_class == "topic" for e in result.extractions)
    assert result.metadata.char_count == len("We had a meeting to discuss the project timeline")


@pytest.mark.asyncio
async def test_mock_extract_detects_action_item():
    """Mock extractor identifies action-related keywords."""
    result = await extract(
        text="There is a todo to finish the report by Friday",
        model_id="gemini-2.5-flash-mock",
    )
    assert isinstance(result, ExtractResponse)
    classes = [e.extraction_class for e in result.extractions]
    assert "action_item" in classes


@pytest.mark.asyncio
async def test_mock_extract_detects_decision():
    """Mock extractor identifies decision-related keywords."""
    result = await extract(
        text="We decided to postpone the launch until Q2",
        model_id="gemini-2.5-flash-mock",
    )
    assert isinstance(result, ExtractResponse)
    classes = [e.extraction_class for e in result.extractions]
    assert "decision" in classes


@pytest.mark.asyncio
async def test_mock_extract_returns_empty_for_no_keywords():
    """Mock extractor returns empty extractions for unrecognized text."""
    result = await extract(
        text="The quick brown fox jumps over the lazy dog",
        model_id="gemini-2.5-flash-mock",
    )
    assert isinstance(result, ExtractResponse)
    assert result.extractions == []


@pytest.mark.asyncio
async def test_mock_extract_metadata():
    """Mock extractor metadata contains model_id and char_count."""
    text = "Hello world"
    result = await extract(text=text, model_id="test-model-mock")
    assert result.metadata.model_id.endswith("-mock")
    assert result.metadata.char_count == len(text)
    assert result.metadata.duration_ms >= 0


@pytest.mark.asyncio
async def test_extract_with_task_prompt():
    """Extract accepts optional task_prompt parameter."""
    result = await extract(
        text="Ship feature by Friday",
        task_prompt="Extract deadlines and action items.",
        model_id="gemini-2.5-flash-mock",
    )
    assert isinstance(result, ExtractResponse)


@pytest.mark.asyncio
async def test_extract_with_examples():
    """Extract accepts optional examples parameter."""
    result = await extract(
        text="Call the dentist tomorrow",
        examples=[
            {
                "text": "Buy groceries",
                "extractions": [
                    {"extraction_class": "action", "extraction_text": "Buy groceries"},
                ],
            },
        ],
        model_id="gemini-2.5-flash-mock",
    )
    assert isinstance(result, ExtractResponse)


def test_mock_extract_sync():
    """_mock_extract works as a sync helper."""
    start = time.monotonic()
    result = _mock_extract("We had a standup call today", "test-model", start)
    assert isinstance(result, ExtractResponse)
    assert any(e.extraction_class == "topic" for e in result.extractions)


@pytest.mark.asyncio
async def test_extract_multiple_keywords():
    """Mock extractor detects multiple keyword categories in one text."""
    result = await extract(
        text="We decided in the meeting that this is a todo for the team",
        model_id="gemini-2.5-flash-mock",
    )
    classes = [e.extraction_class for e in result.extractions]
    assert "topic" in classes
    assert "decision" in classes
    assert "action_item" in classes
