#!/usr/bin/env python3
"""PolishManuscriptApplyTool._run_llm() の実際の実行パステスト

このテストは、モックを最小限にして実際のLLM統合レイヤー全体を通すことを目的とする。
"""

import json
import os
from pathlib import Path
from unittest.mock import patch

import pytest

# Windows環境でのUnicodeエラーを回避
os.environ.setdefault("PYTHONIOENCODING", "utf-8")

from mcp_servers.noveler.tools.polish_manuscript_apply_tool import PolishManuscriptApplyTool


@pytest.mark.unit
@pytest.mark.skip(reason="MCP環境専用テスト - 非MCP環境ではLLM実行がスキップされる仕様")
def test_run_llm_returns_manuscript_content(tmp_path: Path) -> None:
    """_run_llm()が正しくmanuscript内容を返すことを確認

    Note: このテストは MCP 環境でのみ有効です。
    非 MCP 環境では _run_llm() は None を返す仕様です。
    """

    # モックLLMレスポンス（JSON形式）
    mock_manuscript = "# テスト章\n\n改稿後の内容です。\n"
    mock_llm_response = {
        "manuscript": mock_manuscript,
        "improvements": ["内容を改善しました"]
    }

    # MCP環境をモックして、LLM実行が許可されるようにする
    with patch("noveler.infrastructure.factories.path_service_factory.is_mcp_environment", return_value=True), \
         patch(
            "noveler.infrastructure.claude_code_session_integration.ClaudeCodeSessionInterface._call_session_prompt_api",
            return_value={"data": {"content": json.dumps(mock_llm_response, ensure_ascii=False)}}
         ):
        tool = PolishManuscriptApplyTool()

        # プロンプトは何でも良い（実際のLLM呼び出しはモックされている）
        prompt = "テストプロンプト"
        project_root = tmp_path

        # _run_llm()を直接呼び出し
        result = tool._run_llm(project_root, prompt)

    # 検証
    assert result is not None, "_run_llm()がNoneを返しました"
    assert isinstance(result, str), f"_run_llm()の戻り値が文字列ではありません: {type(result)}"
    assert len(result) > 0, "_run_llm()が空文字列を返しました"

    # manuscriptフィールドが正しく抽出されているはず
    assert mock_manuscript == result, f"期待: {mock_manuscript!r}, 実際: {result!r}"


@pytest.mark.unit
@pytest.mark.skip(reason="MCP環境専用テスト - 非MCP環境ではLLM実行がスキップされる仕様")
def test_run_llm_integration_full_stack(tmp_path: Path) -> None:
    """_run_llm()が全統合レイヤーを通して正しく動作することを確認

    このテストは以下のフローを検証:
    - PolishManuscriptApplyTool._run_llm()
    - → UniversalLLMUseCase.execute_with_fallback()
    - → UniversalClaudeCodeService.execute_prompt()
    - → ClaudeCodeIntegrationService.execute_claude_code_prompt()
    - → ClaudeCodeSessionInterface.execute_prompt()
    - → モックLLMレスポンス

    Note: このテストは MCP 環境でのみ有効です。
    非 MCP 環境では _run_llm() は None を返す仕様です。
    """

    mock_manuscript = "改稿後のマニュスクリプト内容"
    mock_llm_response = {
        "manuscript": mock_manuscript,
        "improvements": ["テスト改善"]
    }

    # MCP環境をモックして、LLM実行が許可されるようにする
    with patch("noveler.infrastructure.factories.path_service_factory.is_mcp_environment", return_value=True), \
         patch(
            "noveler.infrastructure.claude_code_session_integration.ClaudeCodeSessionInterface._call_session_prompt_api",
            return_value={"data": {"content": json.dumps(mock_llm_response, ensure_ascii=False)}}
         ):
        tool = PolishManuscriptApplyTool()
        result = tool._run_llm(tmp_path, "test prompt")

    # 統合テストの検証
    assert result == mock_manuscript, \
        f"統合レイヤー通過後の結果が期待と異なる。期待: {mock_manuscript!r}, 実際: {result!r}"
