"""P4 acceptance test suite.

Tests all P4 milestones: M1 (AI frontend API), M2 (task dispatch),
M3 (batch scheduler + monitor), M4 (reports + visualization data),
M5 (deployment config).

Run: python scripts/test_p4_acceptance.py
"""
import json
import os
import sys
import time
from datetime import datetime

# Add project root to path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

PASS = 0
FAIL = 0
RESULTS = []


def test(name, condition, detail=""):
    global PASS, FAIL
    if condition:
        PASS += 1
        RESULTS.append(("PASS", name, detail))
        print(f"  [PASS] {name}")
    else:
        FAIL += 1
        RESULTS.append(("FAIL", name, detail))
        print(f"  [FAIL] {name} - {detail}")


def test_m1_ai_api():
    """P4-M1: AI API endpoints and frontend integration."""
    print("\n[P4-M1] AI Frontend Integration")
    try:
        from web.backend.app.routers import ai, ai_plan, analysis, adaptive, search
        test("AI router modules importable", True)
    except Exception as e:
        test("AI router modules importable", False, str(e))

    # Check frontend AI API file
    ai_api_path = os.path.join("web", "frontend", "src", "api", "ai.ts")
    test("Frontend AI API file exists", os.path.exists(ai_api_path))

    # Check AI views
    ai_views = ["PlanGenerator.vue", "L0Prescreen.vue", "AdaptiveOptimize.vue",
                "ResultAnalysis.vue", "FidelityCalibration.vue", "ExperienceEnhance.vue"]
    for view in ai_views:
        path = os.path.join("web", "frontend", "src", "views", "ai", view)
        test(f"AI view {view} exists", os.path.exists(path))

    # Check components
    comps = ["ConfidenceBadge.vue", "FeasibilityIndicator.vue"]
    for comp in comps:
        path = os.path.join("web", "frontend", "src", "components", "ai", comp)
        test(f"AI component {comp} exists", os.path.exists(path))


def test_m2_task_dispatch():
    """P4-M2: Task management and dispatch."""
    print("\n[P4-M2] Task Dispatch and Callback")
    try:
        from web.backend.app.models.task import Task
        test("Task model importable", True)
    except Exception as e:
        test("Task model importable", False, str(e))

    try:
        from web.backend.app.services.task_manager import get_task_manager
        tm = get_task_manager()
        test("TaskManager service instantiable", tm is not None)
    except Exception as e:
        test("TaskManager service instantiable", False, str(e))

    # Check task router
    router_path = os.path.join("web", "backend", "app", "routers", "tasks.py")
    test("Tasks router exists", os.path.exists(router_path))

    # Check frontend task manager
    tm_path = os.path.join("web", "frontend", "src", "views", "TaskManager.vue")
    test("Frontend TaskManager exists", os.path.exists(tm_path))

    # Check local executor
    exec_path = os.path.join("scripts", "task_executor.py")
    test("Local task executor exists", os.path.exists(exec_path))


def test_m3_batch_scheduler():
    """P4-M3: Batch scheduler and monitoring."""
    print("\n[P4-M3] Batch Scheduler and Monitoring")
    try:
        from web.backend.app.services.batch_scheduler import BatchScheduler, get_scheduler
        scheduler = get_scheduler()
        test("BatchScheduler instantiable", scheduler is not None)

        # Test add task
        task = scheduler.add_task("test-task-1", "Test Task", priority=5,
                                   parameters=[{"x": 1}, {"x": 2}])
        test("Add task to scheduler", task["task_id"] == "test-task-1")

        # Test statistics
        stats = scheduler.get_statistics()
        test("Scheduler statistics has queued_count", "queued_count" in stats)
        test("Scheduler statistics has overall_progress", "overall_progress" in stats)

        # Cleanup
        scheduler.cancel_task("test-task-1")
    except Exception as e:
        test("BatchScheduler functional", False, str(e))

    # Check monitor router
    monitor_path = os.path.join("web", "backend", "app", "routers", "monitor.py")
    test("Monitor router exists", os.path.exists(monitor_path))

    # Check frontend monitor
    monitor_vue = os.path.join("web", "frontend", "src", "views", "MonitorDashboard.vue")
    test("Frontend MonitorDashboard exists", os.path.exists(monitor_vue))

    # Check robust motorcad
    robust_path = os.path.join("scripts", "robust_motorcad.py")
    test("Robust MotorCAD core exists", os.path.exists(robust_path))


def test_m4_visualization_reports():
    """P4-M4: Advanced visualization and reports."""
    print("\n[P4-M4] Visualization and Reports")
    try:
        from web.backend.app.services.report_generator import ReportGenerator, get_report_generator
        rg = get_report_generator()
        test("ReportGenerator instantiable", rg is not None)

        # Test JSON report generation (fallback mode)
        task_data = {"task_id": "test-report", "task_name": "Test",
                      "status": "completed", "plan_data": {"x": 1},
                      "result_metrics": {"efficiency": 90}}
        report_path = rg.generate_report(task_data)
        test("Report generated (JSON fallback)", os.path.exists(report_path))
        if os.path.exists(report_path):
            os.remove(report_path)
    except Exception as e:
        test("ReportGenerator functional", False, str(e))

    # Check reports router
    reports_path = os.path.join("web", "backend", "app", "routers", "reports.py")
    test("Reports router exists", os.path.exists(reports_path))

    # Check frontend visualization
    viz_path = os.path.join("web", "frontend", "src", "views", "AdvancedVisualization.vue")
    test("Frontend AdvancedVisualization exists", os.path.exists(viz_path))


def test_m5_deployment():
    """P4-M5: Deployment configuration."""
    print("\n[P4-M5] Deployment and Packaging")
    files = {
        "Dockerfile": os.path.join("Dockerfile"),
        "docker-compose.yml": os.path.join("docker-compose.yml"),
        "nginx.conf": os.path.join("nginx.conf"),
        "deploy.ps1": os.path.join("deploy.ps1"),
    }
    for name, path in files.items():
        test(f"Deployment file {name} exists", os.path.exists(path))

    # Check deploy.ps1 is ASCII only
    deploy_path = files["deploy.ps1"]
    if os.path.exists(deploy_path):
        with open(deploy_path, "r", encoding="utf-8") as f:
            content = f.read()
        non_ascii = [c for c in content if ord(c) > 127]
        test("deploy.ps1 is ASCII-only", len(non_ascii) == 0,
             f"{len(non_ascii)} non-ASCII chars" if non_ascii else "")


def test_router_registration():
    """Verify all routers are registered in main.py."""
    print("\n[Integration] Router Registration")
    main_path = os.path.join("web", "backend", "app", "main.py")
    if os.path.exists(main_path):
        with open(main_path, "r", encoding="utf-8") as f:
            content = f.read()
        expected_routers = ["tasks", "monitor", "reports"]
        for router in expected_routers:
            test(f"Router '{router}' imported in main.py", f"import {router}" in content or f", {router}" in content)
            test(f"Router '{router}' included in main.py", f"include_router({router}.router)" in content)
    else:
        test("main.py exists", False)


def main():
    print("=" * 60)
    print("PCB AFM Simulation System - P4 Acceptance Test")
    print(f"Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print("=" * 60)

    os.chdir(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

    test_m1_ai_api()
    test_m2_task_dispatch()
    test_m3_batch_scheduler()
    test_m4_visualization_reports()
    test_m5_deployment()
    test_router_registration()

    print("\n" + "=" * 60)
    print(f"RESULTS: {PASS} passed, {FAIL} failed, {PASS + FAIL} total")
    print("=" * 60)

    if FAIL > 0:
        print("\nFailed tests:")
        for status, name, detail in RESULTS:
            if status == "FAIL":
                print(f"  - {name}: {detail}")
        sys.exit(1)
    else:
        print("\nAll tests passed!")
        sys.exit(0)


if __name__ == "__main__":
    main()
