"""Phase 6 파이프라인 YAML + 유스케이스 테스트.

검증 대상:
1. marketing-dev-pipeline.yaml 유효성
2. content-pipeline.yaml 유효성
3. 파이프라인 YAML 구조 (pipeline_validator 통과)
4. 템플릿 파일 존재 확인
5. auto_orch.py cmd_validate 통합 검증
6. dry-run 모드 시뮬레이션 (cmd_run with dry_run=True)

작성자: 벨레스 (dev6-team tester)
날짜: 2026-03-24
"""

import os
import sys
from typing import Any, Callable

import pytest
import yaml

# ---------------------------------------------------------------------------
# sys.path 세팅
# ---------------------------------------------------------------------------
WORKSPACE_ROOT = "/home/jay/workspace"
if WORKSPACE_ROOT not in sys.path:
    sys.path.insert(0, WORKSPACE_ROOT)

# ---------------------------------------------------------------------------
# 기존 함수 import (이미 구현된 것들)
# ---------------------------------------------------------------------------
from orchestrator.auto_orch import cmd_validate, load_pipeline  # noqa: E402
from orchestrator.pipeline_validator import validate_pipeline  # noqa: E402

# ---------------------------------------------------------------------------
# Phase 6 신규 함수 import (dry_run 파라미터 — RED 단계이므로 미구현 예상)
# ---------------------------------------------------------------------------
try:
    from orchestrator.auto_orch import cmd_run as _cmd_run_impl  # noqa: E402

    _cmd_run: Callable[..., Any] = _cmd_run_impl
except ImportError:
    _cmd_run = None  # type: ignore[assignment]

# ---------------------------------------------------------------------------
# 경로 상수
# ---------------------------------------------------------------------------
PIPELINES_DIR = os.path.join(WORKSPACE_ROOT, "pipelines")
TEMPLATES_DIR = os.path.join(WORKSPACE_ROOT, "pipelines/templates")


# ===========================================================================
# TestPipelineYAMLValidity — T6-1: YAML 문법 유효성 테스트
# ===========================================================================


class TestPipelineYAMLValidity:
    """T6-1: YAML 문법 유효성 테스트."""

    def test_marketing_pipeline_yaml_loads(self) -> None:
        """marketing-dev-pipeline.yaml이 유효한 YAML인지 확인."""
        path = os.path.join(PIPELINES_DIR, "marketing-dev-pipeline.yaml")
        assert os.path.exists(path), f"파일 없음: {path}"
        with open(path, encoding="utf-8") as f:
            data = yaml.safe_load(f)
        assert isinstance(data, dict)

    def test_content_pipeline_yaml_loads(self) -> None:
        """content-pipeline.yaml이 유효한 YAML인지 확인."""
        path = os.path.join(PIPELINES_DIR, "content-pipeline.yaml")
        assert os.path.exists(path), f"파일 없음: {path}"
        with open(path, encoding="utf-8") as f:
            data = yaml.safe_load(f)
        assert isinstance(data, dict)


# ===========================================================================
# TestPipelineValidation — P6-2: pipeline_validator 전건 통과 테스트
# ===========================================================================


class TestPipelineValidation:
    """P6-2: pipeline_validator 전건 통과 테스트."""

    def test_marketing_pipeline_validates(self) -> None:
        """marketing-dev-pipeline.yaml이 pipeline_validator 검증 통과."""
        path = os.path.join(PIPELINES_DIR, "marketing-dev-pipeline.yaml")
        pipeline = load_pipeline(path)
        errors = validate_pipeline(pipeline)
        assert errors == [], f"검증 에러: {errors}"

    def test_content_pipeline_validates(self) -> None:
        """content-pipeline.yaml이 pipeline_validator 검증 통과."""
        path = os.path.join(PIPELINES_DIR, "content-pipeline.yaml")
        pipeline = load_pipeline(path)
        errors = validate_pipeline(pipeline)
        assert errors == [], f"검증 에러: {errors}"

    def test_marketing_pipeline_schema_version(self) -> None:
        """schema_version이 "1.0"인지 확인."""
        path = os.path.join(PIPELINES_DIR, "marketing-dev-pipeline.yaml")
        pipeline = load_pipeline(path)
        assert pipeline["schema_version"] == "1.0"

    def test_marketing_pipeline_has_gates(self) -> None:
        """gates가 비어있지 않은 리스트인지 확인."""
        path = os.path.join(PIPELINES_DIR, "marketing-dev-pipeline.yaml")
        pipeline = load_pipeline(path)
        assert isinstance(pipeline["gates"], list)
        assert len(pipeline["gates"]) > 0

    def test_marketing_pipeline_token_budget_positive(self) -> None:
        """token_budget이 양수인지 확인."""
        path = os.path.join(PIPELINES_DIR, "marketing-dev-pipeline.yaml")
        pipeline = load_pipeline(path)
        assert pipeline["token_budget"] > 0

    def test_marketing_pipeline_blast_radius_valid(self) -> None:
        """blast_radius가 유효값인지 확인."""
        path = os.path.join(PIPELINES_DIR, "marketing-dev-pipeline.yaml")
        pipeline = load_pipeline(path)
        assert pipeline.get("blast_radius") in {"step", "team", "org"}

    def test_marketing_pipeline_3_steps(self) -> None:
        """marketing 파이프라인이 3스텝인지 확인."""
        path = os.path.join(PIPELINES_DIR, "marketing-dev-pipeline.yaml")
        pipeline = load_pipeline(path)
        assert len(pipeline["steps"]) == 3

    def test_marketing_pipeline_step_order(self) -> None:
        """ga4_design → dev_implement → qc_verify 순서 확인."""
        path = os.path.join(PIPELINES_DIR, "marketing-dev-pipeline.yaml")
        pipeline = load_pipeline(path)
        step_ids = [s["id"] for s in pipeline["steps"]]
        assert step_ids == ["ga4_design", "dev_implement", "qc_verify"]

    def test_marketing_pipeline_dependencies(self) -> None:
        """의존성 체인 확인: design → implement → verify."""
        path = os.path.join(PIPELINES_DIR, "marketing-dev-pipeline.yaml")
        pipeline = load_pipeline(path)
        steps = pipeline["steps"]
        assert steps[0].get("depends_on", []) == []
        assert "ga4_design" in steps[1].get("depends_on", [])
        assert "dev_implement" in steps[2].get("depends_on", [])

    def test_content_pipeline_3_steps(self) -> None:
        """content 파이프라인이 3스텝인지 확인."""
        path = os.path.join(PIPELINES_DIR, "content-pipeline.yaml")
        pipeline = load_pipeline(path)
        assert len(pipeline["steps"]) == 3

    def test_all_target_teams_in_allowed(self) -> None:
        """모든 step의 target_team이 allowed_teams에 포함되는지 확인."""
        for filename in ["marketing-dev-pipeline.yaml", "content-pipeline.yaml"]:
            path = os.path.join(PIPELINES_DIR, filename)
            pipeline = load_pipeline(path)
            allowed = set(pipeline["allowed_teams"])
            for step in pipeline["steps"]:
                assert step["target_team"] in allowed, (
                    f"{filename}: step '{step['id']}' target_team " f"'{step['target_team']}' not in allowed_teams"
                )


# ===========================================================================
# TestTemplateFiles — T6-2: 템플릿 파일 존재 확인
# ===========================================================================


class TestTemplateFiles:
    """T6-2: 템플릿 파일 존재 확인."""

    def test_templates_dir_exists(self) -> None:
        """templates 디렉토리 존재 확인."""
        assert os.path.isdir(TEMPLATES_DIR), f"디렉토리 없음: {TEMPLATES_DIR}"

    def test_ga4_design_template_exists(self) -> None:
        """ga4-design.md 존재 확인."""
        path = os.path.join(TEMPLATES_DIR, "ga4-design.md")
        assert os.path.exists(path), f"파일 없음: {path}"
        assert os.path.getsize(path) > 0, "파일이 비어있음"

    def test_dev_implement_template_exists(self) -> None:
        """dev-implement.md 존재 확인."""
        path = os.path.join(TEMPLATES_DIR, "dev-implement.md")
        assert os.path.exists(path), f"파일 없음: {path}"
        assert os.path.getsize(path) > 0, "파일이 비어있음"

    def test_qc_verify_template_exists(self) -> None:
        """qc-verify.md 존재 확인."""
        path = os.path.join(TEMPLATES_DIR, "qc-verify.md")
        assert os.path.exists(path), f"파일 없음: {path}"
        assert os.path.getsize(path) > 0, "파일이 비어있음"

    def test_template_files_referenced_in_pipelines(self) -> None:
        """파이프라인의 task_file_template 경로가 실제 파일로 존재하는지 확인."""
        for filename in ["marketing-dev-pipeline.yaml", "content-pipeline.yaml"]:
            path = os.path.join(PIPELINES_DIR, filename)
            pipeline = load_pipeline(path)
            for step in pipeline["steps"]:
                tpl = step.get("task_file_template", "")
                full_path = os.path.join(WORKSPACE_ROOT, tpl)
                assert os.path.exists(full_path), (
                    f"{filename}: step '{step['id']}' task_file_template " f"'{tpl}' not found at {full_path}"
                )


# ===========================================================================
# TestDryRun — T6-3/P6-4: dry-run 모드 시뮬레이션 테스트
# ===========================================================================


class TestDryRun:
    """T6-3/P6-4: dry-run 모드 시뮬레이션 테스트."""

    def test_cmd_run_dry_run_marketing(self, capsys: pytest.CaptureFixture[str]) -> None:
        """marketing-dev-pipeline dry-run이 에러 없이 완료되는지 확인."""
        if _cmd_run is None:
            pytest.fail("cmd_run이 orchestrator.auto_orch에서 import되지 않음")

        _cmd_run("marketing-dev-pipeline", dry_run=True)  # type: ignore[call-arg]
        captured = capsys.readouterr()
        assert "DRY-RUN" in captured.out
        assert "marketing-dev-pipeline" in captured.out
        assert "ga4_design" in captured.out
        assert "dev_implement" in captured.out
        assert "qc_verify" in captured.out

    def test_cmd_run_dry_run_content(self, capsys: pytest.CaptureFixture[str]) -> None:
        """content-pipeline dry-run이 에러 없이 완료되는지 확인."""
        if _cmd_run is None:
            pytest.fail("cmd_run이 orchestrator.auto_orch에서 import되지 않음")

        _cmd_run("content-pipeline", dry_run=True)  # type: ignore[call-arg]
        captured = capsys.readouterr()
        assert "DRY-RUN" in captured.out
        assert "content-pipeline" in captured.out

    def test_cmd_run_dry_run_invalid_pipeline(self, capsys: pytest.CaptureFixture[str]) -> None:
        """존재하지 않는 파이프라인 dry-run 시 에러 메시지 출력."""
        if _cmd_run is None:
            pytest.fail("cmd_run이 orchestrator.auto_orch에서 import되지 않음")

        _cmd_run("nonexistent-pipeline", dry_run=True)  # type: ignore[call-arg]
        captured = capsys.readouterr()
        assert "ERROR" in captured.out


# ===========================================================================
# TestCmdValidate — P6-3: auto_orch.py --validate 통합 테스트
# ===========================================================================


class TestCmdValidate:
    """P6-3: auto_orch.py --validate 통합 테스트."""

    def test_validate_marketing_pipeline(self, capsys: pytest.CaptureFixture[str]) -> None:
        """--validate로 marketing 파이프라인 검증 성공."""
        path = os.path.join(PIPELINES_DIR, "marketing-dev-pipeline.yaml")
        cmd_validate(path)
        captured = capsys.readouterr()
        assert "Valid" in captured.out

    def test_validate_content_pipeline(self, capsys: pytest.CaptureFixture[str]) -> None:
        """--validate로 content 파이프라인 검증 성공."""
        path = os.path.join(PIPELINES_DIR, "content-pipeline.yaml")
        cmd_validate(path)
        captured = capsys.readouterr()
        assert "Valid" in captured.out
