#!/usr/bin/env python3
"""utils/model_metadata.py 테스트 스위트"""

import sys
from pathlib import Path

import pytest

sys.path.insert(0, str(Path(__file__).parent.parent.parent))

from utils.model_metadata import (
    ModelMetadata,
    get_metadata,
    resolve_model,
)


class TestModelMetadata:
    """ModelMetadata dataclass 테스트"""

    def test_metadata_required_fields(self) -> None:
        """필수 필드 확인"""
        meta = ModelMetadata(
            context_window=200_000,
            max_output=8192,
            supports_vision=True,
            supports_tools=True,
            provider="anthropic",
        )
        assert meta.context_window == 200_000
        assert meta.max_output == 8192
        assert meta.supports_vision is True
        assert meta.supports_tools is True
        assert meta.provider == "anthropic"

    def test_metadata_frozen(self) -> None:
        """frozen dataclass - 수정 불가"""
        meta = ModelMetadata(
            context_window=128_000,
            max_output=4096,
            supports_vision=False,
            supports_tools=True,
            provider="openai",
        )
        with pytest.raises((AttributeError, TypeError)):
            meta.context_window = 256_000  # type: ignore[misc]


class TestGetMetadata:
    """get_metadata() 테스트"""

    def test_claude_sonnet_4_6(self) -> None:
        """Claude Sonnet 4.6 메타데이터"""
        meta = get_metadata("claude-sonnet-4-6")
        assert meta.context_window == 1_000_000
        assert meta.provider == "anthropic"
        assert meta.supports_vision is True
        assert meta.supports_tools is True

    def test_claude_opus_4_6(self) -> None:
        """Claude Opus 4.6 메타데이터"""
        meta = get_metadata("claude-opus-4-6")
        assert meta.context_window == 1_000_000
        assert meta.provider == "anthropic"
        assert meta.supports_vision is True

    def test_claude_haiku_3_5(self) -> None:
        """Claude Haiku 3.5 메타데이터"""
        meta = get_metadata("claude-3-5-haiku-20241022")
        assert meta.context_window == 200_000
        assert meta.provider == "anthropic"

    def test_gpt4o(self) -> None:
        """GPT-4o 메타데이터"""
        meta = get_metadata("gpt-4o")
        assert meta.context_window == 128_000
        assert meta.provider == "openai"
        assert meta.supports_vision is True
        assert meta.supports_tools is True

    def test_gpt4o_mini(self) -> None:
        """GPT-4o-mini 메타데이터"""
        meta = get_metadata("gpt-4o-mini")
        assert meta.provider == "openai"
        assert meta.max_output > 0

    def test_gemini_pro(self) -> None:
        """Gemini 2.5 Pro 메타데이터"""
        meta = get_metadata("gemini-2.5-pro")
        assert meta.provider == "google"
        assert meta.context_window >= 1_000_000
        assert meta.supports_vision is True

    def test_gemini_flash(self) -> None:
        """Gemini 2.5 Flash 메타데이터"""
        meta = get_metadata("gemini-2.5-flash")
        assert meta.provider == "google"

    def test_deepseek_chat(self) -> None:
        """DeepSeek Chat 메타데이터"""
        meta = get_metadata("deepseek-chat")
        assert meta.provider == "deepseek"
        assert meta.context_window == 64_000

    def test_unknown_model_raises(self) -> None:
        """알 수 없는 모델은 KeyError"""
        with pytest.raises(KeyError):
            get_metadata("unknown-model-xyz-999")

    def test_claude_3_opus(self) -> None:
        """Claude 3 Opus (구형) 메타데이터"""
        meta = get_metadata("claude-3-opus-20240229")
        assert meta.context_window == 200_000
        assert meta.provider == "anthropic"

    def test_claude_3_haiku(self) -> None:
        """Claude 3 Haiku (구형) 메타데이터"""
        meta = get_metadata("claude-3-haiku-20240307")
        assert meta.provider == "anthropic"
        assert meta.max_output > 0


class TestResolveModel:
    """resolve_model() 테스트"""

    def test_resolve_claude_opus_alias(self) -> None:
        """claude-opus → 정식 모델 ID"""
        resolved = resolve_model("claude-opus")
        assert resolved == "claude-opus-4-6"

    def test_resolve_claude_sonnet_alias(self) -> None:
        """claude-sonnet → 정식 모델 ID"""
        resolved = resolve_model("claude-sonnet")
        assert resolved == "claude-sonnet-4-6"

    def test_resolve_claude_haiku_alias(self) -> None:
        """claude-haiku → 최신 Haiku"""
        resolved = resolve_model("claude-haiku")
        assert "haiku" in resolved.lower()

    def test_resolve_exact_id_passthrough(self) -> None:
        """정식 ID는 그대로 반환"""
        model_id = "claude-sonnet-4-6"
        resolved = resolve_model(model_id)
        assert resolved == model_id

    def test_resolve_gpt4o_alias(self) -> None:
        """gpt4o 별칭"""
        resolved = resolve_model("gpt4o")
        assert "gpt-4o" in resolved

    def test_resolve_unknown_returns_input(self) -> None:
        """알 수 없는 별칭은 입력 그대로 반환"""
        resolved = resolve_model("totally-unknown-alias-xyz")
        assert resolved == "totally-unknown-alias-xyz"

    def test_resolve_deepseek_alias(self) -> None:
        """deepseek-v3 → deepseek-chat"""
        resolved = resolve_model("deepseek-v3")
        assert resolved == "deepseek-chat"

    def test_resolve_gemini_pro_alias(self) -> None:
        """gemini-pro → 최신 Gemini Pro"""
        resolved = resolve_model("gemini-pro")
        assert "gemini" in resolved.lower()
        assert "pro" in resolved.lower()
