"""Test suite for AI Agent Model Customization and Persona System Prompt Grounding."""

import pytest
from fastapi.testclient import TestClient

from app.agents.personas import (
    build_persona_system_prompt,
    get_persona,
    list_persona_codes,
)
from app.core.settings import get_settings
from app.main import create_app
from app.modules.auth.application.auth_service import AuthService
from app.modules.agents.application.llm_client import LLMClient


@pytest.fixture
def client() -> TestClient:
    app = create_app()
    return TestClient(app)


@pytest.fixture
def superadmin_token() -> str:
    auth_service = AuthService()
    session = auth_service.create_dev_user_session(
        email="superadmin@dscons.vn",
        name="Superadmin Test",
        role="superadmin",
    )
    return session["access_token"]


@pytest.fixture
def viewer_token() -> str:
    auth_service = AuthService()
    session = auth_service.create_dev_user_session(
        email="viewer@dscons.vn",
        name="Viewer Test",
        role="viewer",
    )
    return session["access_token"]


class TestAgentPersonaSystemPrompts:
    """Kiểm thử tính toàn vẹn và ngữ cảnh phong phú của System Prompt cho từng AI Persona."""

    def test_all_9_personas_registered(self):
        codes = list_persona_codes()
        assert len(codes) >= 9
        expected = {
            "minh",
            "lan",
            "hung",
            "thao",
            "nam",
            "quynh",
            "phuc",
            "tung",
            "thuy",
        }
        assert expected.issubset(set(codes))

    def test_persona_system_prompt_grounding(self):
        for code in list_persona_codes():
            persona = get_persona(code)
            prompt = build_persona_system_prompt(code, task_type="audit_inspection")

            # Phải có định danh, vai trò, xưng hô
            assert persona["display_name"].upper() in prompt
            assert str(persona["age"]) in prompt
            assert persona["role_title"] in prompt
            assert "Luật Xây dựng 2025" in prompt
            assert "Nghị định 123/2020/NĐ-CP" in prompt
            assert "Độ chính xác số học" in prompt
            assert len(persona.get("duties", [])) > 0
            for duty in persona.get("duties", []):
                assert duty in prompt

    def test_custom_superadmin_instruction_injection(self):
        custom_note = "Ưu tiên rà soát kỹ các hóa đơn vật tư trên 500 triệu VNĐ trong đợt thanh toán này."
        prompt = build_persona_system_prompt("quynh", custom_instruction=custom_note)
        assert custom_note in prompt
        assert "[CHỈ ĐẠO ĐẶC BIỆT TỪ BAN GIÁM ĐỐC / SUPERADMIN]" in prompt


class TestSuperadminAgentModelManagement:
    """Kiểm thử API quản trị và tùy biến Model cho Superadmin."""

    def test_list_agent_models_superadmin_authorized(
        self, client: TestClient, superadmin_token: str
    ):
        response = client.get(
            "/v1/admin/agent-models",
            headers={"Authorization": f"Bearer {superadmin_token}"},
        )
        assert response.status_code == 200
        data = response.json()
        assert "agents" in data
        assert len(data["agents"]) >= 9
        assert data["default_model"] in ("gemini-3.8-flash", "stealth/ox-alpha")

        # Verify stealth/ox-alpha preset exists
        presets = data["agents"][0]["available_presets"]
        preset_ids = [p["id"] for p in presets]
        assert "stealth/ox-alpha" in preset_ids
        assert "nvidia/nemotron-3-nano-30b-a3b:free" in preset_ids

    def test_list_agent_models_viewer_forbidden(
        self, client: TestClient, viewer_token: str
    ):
        response = client.get(
            "/v1/admin/agent-models",
            headers={"Authorization": f"Bearer {viewer_token}"},
        )
        assert response.status_code == 403

    def test_update_agent_model_persistence(
        self, client: TestClient, superadmin_token: str
    ):
        # Update Thủy to use stealth/ox-alpha with custom temp and max tokens
        payload = {
            "model_name": "stealth/ox-alpha",
            "provider": "openrouter",
            "temperature": 0.15,
            "max_tokens": 3000,
            "system_prompt_custom": "Tập trung cao độ vào báo cáo điều hành giao ban sáng.",
        }
        res = client.put(
            "/v1/admin/agent-models/thuy",
            json=payload,
            headers={"Authorization": f"Bearer {superadmin_token}"},
        )
        assert res.status_code == 200
        updated = res.json()
        assert updated["agent_code"] == "thuy"
        assert updated["model_name"] == "stealth/ox-alpha"
        assert updated["provider"] == "openrouter"
        assert updated["temperature"] == 0.15
        assert updated["max_tokens"] == 3000
        assert (
            updated["system_prompt_custom"]
            == "Tập trung cao độ vào báo cáo điều hành giao ban sáng."
        )

        # Verify LLMClient resolves the updated model
        settings = get_settings()
        llm_client = LLMClient(settings)
        provider_info = llm_client.get_provider_for_agent("thuy")
        assert provider_info["model"] == "stealth/ox-alpha"
        assert provider_info["provider"] == "openrouter"
        assert provider_info["temperature"] == 0.15
        assert provider_info["max_tokens"] == 3000
