"""Tests for compile_prompt_template, extract_prompt_content, normalize_text_content."""

from __future__ import annotations


import pytest

from dr_langfuse.errors.codes import ErrorCode
from dr_langfuse.errors.langfuse_error import LangfuseError
from dr_langfuse.prompts.prompt_payload import (
    compile_prompt_template,
    extract_prompt_content,
    normalize_text_content,
)


def test_compile_success() -> None:
    class _Prompt:
        def compile(self, **variables: object) -> list[dict[str, str]]:
            return [{"role": "user", "content": f"Do {variables.get('task')}."}]

    result = compile_prompt_template(_Prompt(), {"task": "something"})
    assert result == [{"role": "user", "content": "Do something."}]


def test_compile_missing_compile_method() -> None:
    with pytest.raises(LangfuseError) as exc_info:
        compile_prompt_template(object(), {})
    assert exc_info.value.error.code == ErrorCode.MALFORMED_REQUEST
    assert exc_info.value.error.details.get("reason") == "missing_compile_method"


def test_compile_unknown_variables() -> None:
    class _Prompt:
        def compile(self, *, topic: object) -> list[dict[str, str]]:
            return [{"role": "user", "content": f"Summarize {topic}."}]

    with pytest.raises(LangfuseError) as exc_info:
        compile_prompt_template(_Prompt(), {"topic": "incident", "extra": "x"})
    assert exc_info.value.error.code == ErrorCode.MALFORMED_REQUEST
    assert exc_info.value.error.details.get("reason") == "unknown_compile_variables"


def test_compile_type_error() -> None:
    class _Prompt:
        def compile(self, *args: object, **kwargs: object) -> str:
            if kwargs:
                raise TypeError("template compile failed")
            del args
            return "fallback"

    with pytest.raises(LangfuseError) as exc_info:
        compile_prompt_template(_Prompt(), {"topic": "incident"})
    assert exc_info.value.error.code == ErrorCode.MALFORMED_REQUEST
    assert exc_info.value.error.details.get("reason") == "compile_invocation_type_error"


def test_compile_no_kwargs_support() -> None:
    class _Prompt:
        def compile(self) -> list[dict[str, str]]:
            return [{"role": "user", "content": "task"}]

    with pytest.raises(LangfuseError) as exc_info:
        compile_prompt_template(_Prompt(), {"topic": "ignored"})
    assert exc_info.value.error.code == ErrorCode.MALFORMED_REQUEST
    assert exc_info.value.error.details.get("reason") == "unknown_compile_variables"


def test_extract_non_list_raises() -> None:
    with pytest.raises(LangfuseError) as exc_info:
        extract_prompt_content({"role": "user", "content": "task"})
    assert exc_info.value.error.details.get("reason") == "invalid_prompt_shape"


def test_extract_non_dict_message_raises() -> None:
    with pytest.raises(LangfuseError) as exc_info:
        extract_prompt_content(["not a dict"])
    assert exc_info.value.error.details.get("reason") == "invalid_message_shape"


def test_extract_unsupported_role_raises() -> None:
    with pytest.raises(LangfuseError) as exc_info:
        extract_prompt_content([{"role": "assistant", "content": "hi"}])
    assert exc_info.value.error.details.get("reason") == "invalid_message_role"


def test_extract_no_user_message_raises() -> None:
    with pytest.raises(LangfuseError) as exc_info:
        extract_prompt_content([{"role": "system", "content": "system only"}])
    assert exc_info.value.error.details.get("reason") == "invalid_user_message_count"


def test_extract_multiple_user_messages_raises() -> None:
    with pytest.raises(LangfuseError) as exc_info:
        extract_prompt_content(
            [
                {"role": "user", "content": "first"},
                {"role": "user", "content": "   "},
            ]
        )
    assert exc_info.value.error.details.get("reason") == "invalid_user_message_count"


def test_extract_blank_user_content_raises() -> None:
    with pytest.raises(LangfuseError) as exc_info:
        extract_prompt_content([{"role": "user", "content": "   "}])
    assert exc_info.value.error.details.get("reason") == "empty_user_message_content"


def test_extract_system_and_user() -> None:
    system, task = extract_prompt_content(
        [
            {"role": "system", "content": "You are helpful."},
            {"role": "user", "content": "Do the thing."},
        ]
    )
    assert system == "You are helpful."
    assert task == "Do the thing."


def test_extract_user_only() -> None:
    system, task = extract_prompt_content(
        [
            {"role": "user", "content": "Do the thing."},
        ]
    )
    assert system == ""
    assert task == "Do the thing."


def test_normalize_string() -> None:
    assert normalize_text_content("hello") == "hello"


def test_normalize_list() -> None:
    assert normalize_text_content(["a", "b"]) == "a\nb"


def test_normalize_dict_text_key() -> None:
    assert normalize_text_content({"text": "hello"}) == "hello"


def test_normalize_dict_content_key() -> None:
    assert normalize_text_content({"content": "hello"}) == "hello"


def test_normalize_unknown_returns_empty() -> None:
    assert normalize_text_content(42) == ""
