"""Interface review agent 통합 테스트."""

from pathlib import Path
from unittest.mock import MagicMock, patch

import pytest

from gar.core.context import ReviewContext, ReviewMode
from gar.core.orchestrator import ReviewOrchestrator
from gar.llm.client import AgentStepResult, LocalOpenAIAgentBackend
from gar.reviewers.interface.agent import InterfaceReviewAgent


class MockAgentBackend:
    """테스트용 Mock Agent Backend."""
    
    def __init__(self):
        self.call_count = 0
        self.tool_calls_history: list[list] = []
    
    def run_step(
        self,
        *,
        messages: list[dict[str, str]],
        tools: list[dict],
        model: str,
        temperature: float,
        max_tokens: int,
    ) -> AgentStepResult:
        """Mock 에이전트 스텝 실행."""
        self.call_count += 1
        
        # 첫 번째 호출: tool_calls 반환 (read_file 호출 시뮬레이션)
        if self.call_count == 1:
            tool_calls = [
                {
                    "id": "call_1",
                    "type": "function",
                    "function": {
                        "name": "read_file",
                        "arguments": '{"path": "test.py", "start_line": 1, "end_line": 10}',
                    },
                }
            ]
            self.tool_calls_history.append(tool_calls)
            return AgentStepResult(
                messages=messages + [{"role": "assistant", "content": ""}],
                tool_calls=tool_calls,
                is_final=False,
            )
        
        # 두 번째 호출: report_finding 호출
        if self.call_count == 2:
            tool_calls = [
                {
                    "id": "call_2",
                    "type": "function",
                    "function": {
                        "name": "report_finding",
                        "arguments": '{"file": "test.py", "line": 5, "category": "api_contract", "severity": "medium", "message": "타입힌트와 실제 반환값이 일치하지 않습니다.", "suggestion": "Optional[dict] 또는 dict | None을 사용하세요."}',
                    },
                }
            ]
            self.tool_calls_history.append(tool_calls)
            return AgentStepResult(
                messages=messages + [{"role": "assistant", "content": ""}],
                tool_calls=tool_calls,
                is_final=False,
            )
        
        # 세 번째 호출: 최종 응답
        return AgentStepResult(
            messages=messages + [{"role": "assistant", "content": "리뷰를 완료했습니다."}],
            tool_calls=[],
            is_final=True,
        )


def test_interface_agent_with_mock():
    """Mock 백엔드를 사용한 인터페이스 에이전트 테스트."""
    fixtures_dir = Path(__file__).parent.parent.parent / "fixtures"
    test_file = fixtures_dir / "sample_code_with_issues.py"
    
    if not test_file.exists():
        pytest.skip("테스트 fixture 파일이 없습니다.")
    
    # Mock 백엔드 생성
    mock_backend = MockAgentBackend()
    
    # Orchestrator로 컨텍스트 생성
    orchestrator = ReviewOrchestrator()
    ctx = orchestrator.build_context(
        mode=ReviewMode.INTERFACE,
        files=[test_file],
        model="test-model",
        temperature=0.2,
        max_output_tokens=1024,
        max_retries=3,
        language="Korean",
        quiet=True,
    )
    
    # Mock 백엔드로 에이전트 생성
    agent = InterfaceReviewAgent(mock_backend)
    
    # 에이전트 실행
    findings = agent.run(ctx)
    
    # 결과 검증
    assert isinstance(findings, list)
    # Mock이 report_finding을 호출했는지 확인
    assert mock_backend.call_count >= 2


def test_interface_agent_tool_calls():
    """에이전트의 툴 호출이 제대로 작동하는지 테스트."""
    fixtures_dir = Path(__file__).parent.parent.parent / "fixtures"
    test_file = fixtures_dir / "sample_code_with_issues.py"
    
    if not test_file.exists():
        pytest.skip("테스트 fixture 파일이 없습니다.")
    
    import os
    orchestrator = ReviewOrchestrator()
    ctx = orchestrator.build_context(
        mode=ReviewMode.INTERFACE,
        files=[test_file],
        model="test-model",
        temperature=float(os.getenv("GAR_TEMPERATURE", "0.2")),
        max_output_tokens=int(os.getenv("GAR_MAX_OUTPUT_TOKENS", "2048")),
        max_retries=int(os.getenv("GAR_MAX_RETRIES", "3")),
        language=os.getenv("GAR_LANGUAGE", "Korean"),
        quiet=True,
    )
    
    agent = InterfaceReviewAgent()
    
    # 툴 스키마 확인
    tools = agent._build_tools_schema()
    assert len(tools) > 0
    
    tool_names = [t["function"]["name"] for t in tools]
    assert "read_file" in tool_names
    assert "report_finding" in tool_names
    assert "get_interface_summary" in tool_names


def test_read_file_tool():
    """read_file 툴이 제대로 작동하는지 테스트."""
    fixtures_dir = Path(__file__).parent.parent.parent / "fixtures"
    test_file = fixtures_dir / "sample_code_with_issues.py"
    
    if not test_file.exists():
        pytest.skip("테스트 fixture 파일이 없습니다.")
    
    import os
    orchestrator = ReviewOrchestrator()
    ctx = orchestrator.build_context(
        mode=ReviewMode.INTERFACE,
        files=[test_file],
        model="test-model",
        temperature=float(os.getenv("GAR_TEMPERATURE", "0.2")),
        max_output_tokens=int(os.getenv("GAR_MAX_OUTPUT_TOKENS", "2048")),
        max_retries=int(os.getenv("GAR_MAX_RETRIES", "3")),
        language=os.getenv("GAR_LANGUAGE", "Korean"),
        quiet=True,
    )
    
    agent = InterfaceReviewAgent()
    
    # read_file 툴 테스트
    result = agent._tool_read_file(ctx, {"path": str(test_file), "start_line": 1, "end_line": 20})
    
    assert "path" in result
    assert "content" in result
    assert "start_line" in result
    assert "end_line" in result
    assert len(result["content"]) > 0


def test_report_finding_tool():
    """report_finding 툴이 제대로 작동하는지 테스트."""
    fixtures_dir = Path(__file__).parent.parent.parent / "fixtures"
    test_file = fixtures_dir / "sample_code_with_issues.py"
    
    if not test_file.exists():
        pytest.skip("테스트 fixture 파일이 없습니다.")
    
    import os
    orchestrator = ReviewOrchestrator()
    ctx = orchestrator.build_context(
        mode=ReviewMode.INTERFACE,
        files=[test_file],
        model="test-model",
        temperature=float(os.getenv("GAR_TEMPERATURE", "0.2")),
        max_output_tokens=int(os.getenv("GAR_MAX_OUTPUT_TOKENS", "2048")),
        max_retries=int(os.getenv("GAR_MAX_RETRIES", "3")),
        language=os.getenv("GAR_LANGUAGE", "Korean"),
        quiet=True,
    )
    
    agent = InterfaceReviewAgent()
    
    initial_count = len(ctx.state.findings)
    
    # report_finding 툴 테스트
    result = agent._tool_report_finding(
        ctx,
        {
            "file": str(test_file),
            "line": 10,
            "category": "api_contract",
            "severity": "medium",
            "message": "테스트 메시지",
            "suggestion": "테스트 제안",
        },
    )
    
    assert result["status"] == "ok"
    assert len(ctx.state.findings) == initial_count + 1
    
    finding = ctx.state.findings[-1]
    assert finding.category == "api_contract"
    assert finding.severity == "medium"
    assert finding.message == "테스트 메시지"
