"""AI Brain regression tests with real STM32 projects."""

import json
import time
from pathlib import Path

import pytest

from fwauto.logging_config import init_project_logging
from fwauto.nodes.ai_brain import ai_brain_node
from fwauto.nodes.build import build_node
from fwauto.state import FirmwareState
from tests.integration.error_injector import ErrorInjector, ErrorType

# 定義測試的錯誤類型（先用小規模測試）
ERROR_TYPES_SMALL: list[ErrorType] = [
    "function_name_typo",
    "missing_semicolon",
    "undefined_variable",
]

# 完整測試的錯誤類型
ERROR_TYPES_FULL: list[ErrorType] = [
    "function_name_typo",
    "missing_include",
    "missing_semicolon",
    "undefined_variable",
    "type_mismatch",
    "wrong_parameter_count",
    "bracket_mismatch",
    "comment_syntax_error",
    "duplicate_definition",
    "case_sensitive_error",
]

# 每個錯誤類型重複執行次數（小規模測試用較少次數）
REPETITIONS_SMALL = 2  # 小規模測試
REPETITIONS_FULL = 10  # 完整測試


@pytest.fixture
def create_test_state(isolated_stm32_project):
    """Create FirmwareState for testing."""

    def _create_state(**overrides) -> FirmwareState:
        base_state: FirmwareState = {
            "user_prompt": "Fix compilation errors",
            "project_root": str(isolated_stm32_project),
            "project_initialized": True,
            "build_status": "pending",
            "build_errors": [],
            "build_log": "",
            "flash_status": "pending",
            "flash_errors": [],
            "flash_log": "",
            "iteration": 0,
            "max_retries": 3,
            "execution_mode": None,
            "command": None,
            "command_args": {},
            "mode_metadata": None,
            "command_error": None,
            "log_file_path": None,
            "log_analysis_result": None,
            "firmware_path": None,
            "platform": "stm32_keil",
            "flash_output": "",
            "serial_port": "COM3",
            "baud_rate": 115200,
            "flash_retries": 0,
            "max_flash_retries": 3,
            "last_error": "",
        }
        base_state.update(overrides)
        return base_state

    return _create_state


@pytest.mark.slow
@pytest.mark.parametrize("error_type", ERROR_TYPES_SMALL)
@pytest.mark.parametrize("run_number", range(REPETITIONS_SMALL))
def test_ai_fixes_error_small(
    error_type: ErrorType,
    run_number: int,
    isolated_stm32_project: Path,
    create_test_state,
    tmp_path: Path,
):
    """
    小規模統計測試：AI 修復特定錯誤類型（用於開發和驗證）。

    注意：此測試需要：
    1. Windows 11 + Keil uVision 5 環境
    2. 真實 Claude Code SDK 執行（不 Mock）
    3. 完整 STM32 專案結構

    執行時間：約 30 秒/次（3 錯誤 × 2 次 = 6 次，總計約 3 分鐘）
    """
    # 記錄測試開始時間
    start_time = time.time()

    # 初始化日誌系統（這樣才會建立日誌檔案）
    init_project_logging(isolated_stm32_project)

    # Step 1: 注入錯誤
    injector = ErrorInjector(isolated_stm32_project)
    expected_error = injector.inject_error(error_type)

    try:
        # Step 2: 初始化 State 並執行編譯（驗證錯誤存在）
        state = create_test_state()
        build_result = build_node(state)

        # 驗證編譯確實失敗
        assert build_result["build_status"] == "error", (
            f"Expected build to fail after injecting {error_type}, but it succeeded"
        )

        # 檢查錯誤訊息（較寬鬆的檢查，因為 Keil 錯誤訊息可能不同）
        if expected_error and build_result["build_errors"]:
            error_messages = " ".join(build_result["build_errors"]).lower()
            print(f"Build errors: {error_messages[:200]}...")  # 用於調試

        # Step 3: 執行 AI Brain（真實 SDK 呼叫）
        ai_result = ai_brain_node(build_result)

        # Step 4: 重新編譯驗證修復結果
        final_build = build_node(ai_result)

        # Step 5: 記錄結果
        success = final_build["build_status"] == "success"
        execution_time = time.time() - start_time

        # 保存詳細結果到 JSON
        result_data = {
            "error_type": error_type,
            "run_number": run_number,
            "success": success,
            "execution_time": execution_time,
            "ai_responses": ai_result.get("responses", []),
            "ai_build_log": ai_result.get("build_log", ""),  # 🧠 應該在這裡
            "final_build_errors": final_build.get("build_errors", []),
            "final_build_log": final_build.get("build_log", ""),  # 最終編譯日誌
            "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
        }

        # 寫入結果檔案到專案目錄下的固定位置
        results_dir = Path(__file__).parent.parent.parent / "test_results" / "regression_results"
        results_dir.mkdir(parents=True, exist_ok=True)
        result_file = results_dir / f"{error_type}_run{run_number}.json"
        result_file.write_text(json.dumps(result_data, indent=2, ensure_ascii=False))

        # 輸出測試結果
        status = "✅ SUCCESS" if success else "❌ FAILED"
        print(f"\n{status}: {error_type} (run {run_number + 1}) - {execution_time:.1f}s")

    finally:
        # 恢復原始檔案（無論測試成功或失敗）
        injector.restore()


@pytest.mark.slow
@pytest.mark.parametrize("error_type", ERROR_TYPES_FULL)
@pytest.mark.parametrize("run_number", range(REPETITIONS_FULL))
def test_ai_fixes_error_full(
    error_type: ErrorType,
    run_number: int,
    isolated_stm32_project: Path,
    create_test_state,
    tmp_path: Path,
):
    """
    完整統計測試：AI 修復特定錯誤類型（重複執行以量化成功率）。

    注意：此測試需要：
    1. Windows 11 + Keil uVision 5 環境
    2. 真實 Claude Code SDK 執行（不 Mock）
    3. 完整 STM32 專案結構

    執行時間：約 30 秒/次（10 錯誤 × 10 次 = 100 次，總計約 50 分鐘）
    """
    # 與小規模測試相同的邏輯，但使用完整的錯誤類型和重複次數
    test_ai_fixes_error_small(error_type, run_number, isolated_stm32_project, create_test_state, tmp_path)


@pytest.mark.slow
def test_overall_success_rate():
    """
    驗證整體成功率 >= 70%（基準線）。

    此測試應在所有統計測試完成後執行。
    """
    results_dir = Path(__file__).parent.parent.parent / "test_results" / "regression_results"

    # 如果沒有結果檔案，跳過測試
    if not results_dir.exists():
        pytest.skip("No regression test results found")

    # 載入所有結果
    results = []
    for result_file in results_dir.glob("*.json"):
        results.append(json.loads(result_file.read_text()))

    if not results:
        pytest.skip("No regression test results found")

    # 計算整體成功率
    total_tests = len(results)
    successful_tests = sum(1 for r in results if r["success"])
    success_rate = successful_tests / total_tests if total_tests > 0 else 0

    # 計算每個錯誤類型的成功率
    error_type_stats = {}
    for result in results:
        error_type = result["error_type"]
        if error_type not in error_type_stats:
            error_type_stats[error_type] = {"total": 0, "success": 0}
        error_type_stats[error_type]["total"] += 1
        if result["success"]:
            error_type_stats[error_type]["success"] += 1

    # 生成報告
    print("\n" + "=" * 60)
    print("AI Brain Regression Test Report")
    print("=" * 60)
    print(f"Total Tests: {total_tests}")
    print(f"Successful: {successful_tests}")
    print(f"Failed: {total_tests - successful_tests}")
    print(f"Overall Success Rate: {success_rate:.1%}")
    print("\nPer Error Type:")
    print("-" * 60)
    for error_type, stats in sorted(error_type_stats.items()):
        rate = stats["success"] / stats["total"] if stats["total"] > 0 else 0
        print(f"  {error_type:30s} {stats['success']:2d}/{stats['total']:2d} ({rate:.1%})")
    print("=" * 60)

    # 斷言：整體成功率 >= 70%
    assert success_rate >= 0.70, (
        f"Overall success rate {success_rate:.1%} is below 70% baseline. "
        f"This indicates the AI Brain needs prompt improvements."
    )
