#!/usr/bin/env python3
"""시나리오 2 통합 테스트: scRNA-seq T세포 탈진 분석 (외부 레퍼런스 비교)

검증 흐름:
  1. platform_data.list  → 폐암 scRNA-seq 데이터 확인
  2. external_data.recommend → HCA 정상 폐 조직 레퍼런스 추천
  3. pipeline.recommend  → Seurat + SingleR + Monocle3 파이프라인
  4. pipeline_canvas.create → CANVAS 이벤트용 시각화 데이터
  5. analysis.execute (각 단계) → CANVAS_UPDATE 데이터
  6. report_canvas.create → 보고서 Canvas (UMAP, Pseudotime, Violin)

Usage:
    python tests/test_scenario2_scrna.py
"""

from __future__ import annotations

import json
import os
import sys

sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))

from oedix.tools.registry import ToolRegistry

DATA_DIR = "/opt/app/data"
TOOLS_DIR = os.path.join(DATA_DIR, "tools")

# ── ANSI helpers ──────────────────────────────────────────────────

GREEN = "\033[32m"
RED = "\033[31m"
YELLOW = "\033[33m"
CYAN = "\033[36m"
BOLD = "\033[1m"
RESET = "\033[0m"


def ok(msg: str):
    print(f"  {GREEN}✓{RESET} {msg}")


def fail(msg: str):
    print(f"  {RED}✗{RESET} {msg}")


def section(title: str):
    print(f"\n{BOLD}{CYAN}{'─' * 50}{RESET}")
    print(f"{BOLD}{CYAN}  {title}{RESET}")
    print(f"{BOLD}{CYAN}{'─' * 50}{RESET}")


# ── Test ──────────────────────────────────────────────────────────

def run_scenario2():
    """scRNA-seq 외부 레퍼런스 비교 분석 시나리오 테스트."""
    errors = []

    registry = ToolRegistry(TOOLS_DIR)
    registry.scan()

    section("Step 1: 플랫폼 데이터 조회")
    result = registry.execute("platform_data.list", params={"omics_type": "scrna-seq"})
    data = result.get("data", {})
    datasets = data.get("datasets", []) if isinstance(data, dict) else []
    has_lung = any("lung" in str(d).lower() or "폐" in str(d) for d in datasets)
    if has_lung:
        ok(f"폐암 scRNA-seq 데이터 발견 ({len(datasets)}개 데이터셋)")
    else:
        fail("폐암 scRNA-seq 데이터 미발견")
        errors.append("platform_data: no lung scRNA-seq")

    section("Step 2: 외부 데이터 추천")
    result = registry.execute("external_data.recommend", params={
        "current_data_type": "scrna-seq",
        "disease": "lung cancer",
    })
    data = result.get("data", {})
    recommendations = data.get("recommendations", [])
    has_hca = any("HCA" in str(r) or "Human Cell Atlas" in str(r) for r in recommendations)

    if recommendations:
        ok(f"외부 데이터 추천 {len(recommendations)}건")
        if has_hca:
            ok("HCA 정상 폐 조직 레퍼런스 추천 포함")
        else:
            fail("HCA 레퍼런스 데이터 추천 누락")
            errors.append("external_data: no HCA recommendation")
    else:
        fail("외부 데이터 추천 없음")
        errors.append("external_data: no recommendations")

    section("Step 3: 파이프라인 구성")
    result = registry.execute("pipeline.recommend", params={
        "data_types": "scrna-seq",
    })
    pipeline_data = result.get("data", {})
    pipeline_id = pipeline_data.get("id", "")
    nodes = pipeline_data.get("nodes", [])
    node_tools = [n.get("tool", "") for n in nodes]

    expected_tools = ["Seurat", "SingleR", "Monocle3"]
    all_present = all(t in node_tools for t in expected_tools)

    if pipeline_id:
        ok(f"파이프라인 생성: {pipeline_id}")
    else:
        fail("파이프라인 생성 실패")
        errors.append("pipeline: creation failed")

    if all_present:
        ok(f"도구 조합: {' → '.join(node_tools)}")
    else:
        fail(f"기대 도구 {expected_tools} 중 누락. 실제: {node_tools}")
        errors.append(f"pipeline: missing tools, got {node_tools}")

    section("Step 4: 파이프라인 Canvas 생성")
    result = registry.execute("pipeline_canvas.create", params={
        "pipeline_id": pipeline_id,
    })
    canvas = result.get("canvas", {})
    canvas_id = canvas.get("canvas_id", "")
    canvas_nodes = canvas.get("nodes", [])

    if canvas_id:
        ok(f"Canvas 생성: {canvas_id}")
    else:
        fail("Canvas 생성 실패")
        errors.append("pipeline_canvas: no canvas_id")

    if len(canvas_nodes) == len(nodes):
        ok(f"Canvas 노드 수: {len(canvas_nodes)}")
    else:
        fail(f"Canvas 노드 수 불일치: {len(canvas_nodes)} (expected {len(nodes)})")
        errors.append("pipeline_canvas: node count mismatch")

    section("Step 5: 분석 실행 (각 단계)")
    step_ids = [n.get("id", "") for n in nodes]
    for step_id in step_ids:
        result = registry.execute("analysis.execute", params={
            "pipeline_id": pipeline_id,
            "step_id": step_id,
        })
        step_data = result.get("data", {})
        canvas_update = result.get("canvas_update", {})

        if step_data.get("status") == "completed":
            ok(f"  {step_id}: 실행 완료")
        else:
            fail(f"  {step_id}: 실행 실패")
            errors.append(f"analysis: {step_id} failed")

        if canvas_update.get("canvas_id"):
            ok(f"  {step_id}: CANVAS_UPDATE 데이터 생성")
        else:
            fail(f"  {step_id}: CANVAS_UPDATE 누락")
            errors.append(f"analysis: {step_id} no canvas_update")

    section("Step 6: 결과 보고서 Canvas 생성")
    result = registry.execute("report_canvas.create", params={
        "pipeline_id": pipeline_id,
    })
    report_canvas = result.get("canvas", {})
    report_sections = report_canvas.get("sections", [])

    if report_canvas.get("canvas_type") == "report":
        ok("보고서 Canvas 생성 완료")
    else:
        fail("보고서 Canvas 타입 불일치")
        errors.append("report_canvas: wrong canvas_type")

    # Check key findings
    summary_section = next((s for s in report_sections if s.get("type") == "summary"), None)
    if summary_section:
        findings = summary_section.get("findings", [])
        ok(f"핵심 발견: {len(findings)}개")
        for f in findings:
            print(f"    {YELLOW}•{RESET} {f[:80]}")

        # Check for exhaustion markers
        all_text = " ".join(findings)
        if "PDCD1" in all_text or "HAVCR2" in all_text or "탈진" in all_text or "exhausted" in all_text.lower():
            ok("T세포 탈진 마커 결과 포함 (PDCD1/HAVCR2)")
        else:
            fail("T세포 탈진 마커 결과 누락")
            errors.append("report_canvas: no exhaustion markers in findings")
    else:
        fail("핵심 요약 섹션 누락")
        errors.append("report_canvas: no summary section")

    # Check charts
    charts_section = next((s for s in report_sections if s.get("type") == "charts"), None)
    if charts_section:
        charts = charts_section.get("charts", [])
        chart_types = [c.get("chart_type", "") for c in charts]
        ok(f"차트: {len(charts)}개 — {chart_types}")

        expected_charts = ["umap", "pseudotime", "violin"]
        for ec in expected_charts:
            if ec in chart_types:
                ok(f"  {ec} 차트 포함")
            else:
                fail(f"  {ec} 차트 누락")
                errors.append(f"report_canvas: missing {ec} chart")
    else:
        fail("시각화 섹션 누락")
        errors.append("report_canvas: no charts section")

    # ── Summary ───────────────────────────────────────────────
    section("테스트 결과 요약")
    if not errors:
        print(f"\n  {GREEN}{BOLD}✓ 시나리오 2 전체 통과!{RESET}")
    else:
        print(f"\n  {RED}{BOLD}✗ 시나리오 2 실패 ({len(errors)}건){RESET}")
        for e in errors:
            print(f"    {RED}•{RESET} {e}")

    return len(errors) == 0


if __name__ == "__main__":
    success = run_scenario2()
    sys.exit(0 if success else 1)
