from __future__ import annotations

from typing import Any, Dict, Iterator, List, Optional, Union

from abstractcore.core.types import GenerateResponse
from abstractcore.providers.base import BaseProvider


class _ThinkingTagStreamProvider(BaseProvider):
    def get_capabilities(self) -> list[str]:
        return ["streaming"]

    def list_available_models(self, **kwargs) -> list[str]:
        return [self.model]

    def unload_model(self, model_name: str) -> None:
        return None

    def _generate_internal(
        self,
        prompt: str,
        messages: Optional[List[Dict[str, str]]] = None,
        system_prompt: Optional[str] = None,
        tools: Optional[List[Dict[str, Any]]] = None,
        media: Optional[List[Any]] = None,
        stream: bool = False,
        response_model: Optional[Any] = None,
        execute_tools: Optional[bool] = None,
        media_metadata: Optional[List[Dict[str, Any]]] = None,
        **kwargs,
    ) -> Union[GenerateResponse, Iterator[GenerateResponse]]:
        if not stream:
            return GenerateResponse(content="<think>r</think>Final", model=self.model, finish_reason="stop")

        def _gen() -> Iterator[GenerateResponse]:
            yield GenerateResponse(content="<think>r", model=self.model, finish_reason=None)
            yield GenerateResponse(content="</think>Final", model=self.model, finish_reason="stop")

        return _gen()


def test_streaming_extracts_thinking_tags_into_reasoning_metadata() -> None:
    llm = _ThinkingTagStreamProvider(model="unit-test")
    # Force thinking tags to be enabled for this synthetic model.
    llm.model_capabilities = {"thinking_tags": ["<think>", "</think>"]}

    chunks = list(llm.generate(prompt="hi", stream=True))

    visible = "".join(c.content or "" for c in chunks)
    assert visible == "Final"

    assert chunks[-1].reasoning == "r"

