"""Tests for architect report generation."""

from __future__ import annotations

from pathlib import Path

import pytest

from cleave.architect.config import ArchitectConfig
from cleave.architect.dag import DAGStore, Phase
from cleave.architect.report import (
    generate_checkpoint_report,
    generate_plan_review,
    write_plan_review,
    write_report,
)


def _make_config(tmp_path: Path, **kwargs) -> ArchitectConfig:
    (tmp_path / ".git").mkdir(exist_ok=True)
    defaults = {"directive": "Build auth system", "repo_path": tmp_path}
    defaults.update(kwargs)
    return ArchitectConfig(**defaults)


def _populated_dag(tmp_path: Path) -> DAGStore:
    store = DAGStore(tmp_path / "test.db")
    store.open()
    store.add_phase(Phase(
        id="p1", label="Define types", description="Create type definitions",
        status="completed", cost_usd=5.0,
        started_at="2024-01-01T00:00:00", completed_at="2024-01-01T00:30:00",
    ))
    store.add_phase(Phase(
        id="p2", label="Implement", description="Build the implementation",
        status="pending", wave=1,
    ))
    store.add_dependency("p2", "p1")
    store.add_checkpoint(
        gate_type="structural", decision="continue",
        reason="Phase 'p1' completed successfully", phase_id="p1",
    )
    store.log_event("plan", "Started planning")
    store.set_metadata("rationale", "Types first, then implementation")
    return store


class TestGenerateCheckpointReport:
    def test_includes_directive(self, tmp_path: Path) -> None:
        config = _make_config(tmp_path)
        dag = _populated_dag(tmp_path)
        report = generate_checkpoint_report(dag, config)
        assert "Build auth system" in report
        dag.close()

    def test_includes_phase_table(self, tmp_path: Path) -> None:
        config = _make_config(tmp_path)
        dag = _populated_dag(tmp_path)
        report = generate_checkpoint_report(dag, config)
        assert "Define types" in report
        assert "Implement" in report
        assert "completed" in report
        assert "pending" in report
        dag.close()

    def test_includes_cost(self, tmp_path: Path) -> None:
        config = _make_config(tmp_path)
        dag = _populated_dag(tmp_path)
        report = generate_checkpoint_report(dag, config)
        assert "$5.0000" in report
        dag.close()

    def test_includes_wave_structure(self, tmp_path: Path) -> None:
        config = _make_config(tmp_path)
        dag = _populated_dag(tmp_path)
        report = generate_checkpoint_report(dag, config)
        assert "Wave" in report
        dag.close()

    def test_includes_gate_decisions(self, tmp_path: Path) -> None:
        config = _make_config(tmp_path)
        dag = _populated_dag(tmp_path)
        report = generate_checkpoint_report(dag, config)
        assert "structural" in report
        assert "continue" in report
        dag.close()

    def test_includes_failures(self, tmp_path: Path) -> None:
        config = _make_config(tmp_path)
        dag = DAGStore(tmp_path / "test2.db")
        dag.open()
        dag.add_phase(Phase(
            id="p1", label="Broken", status="failed",
            error_message="Something went wrong",
        ))
        report = generate_checkpoint_report(dag, config)
        assert "Failures" in report
        assert "Something went wrong" in report
        dag.close()

    def test_empty_dag(self, tmp_path: Path) -> None:
        config = _make_config(tmp_path)
        dag = DAGStore(tmp_path / "empty.db")
        dag.open()
        report = generate_checkpoint_report(dag, config)
        assert "Architect Checkpoint Report" in report
        dag.close()


class TestGeneratePlanReview:
    def test_includes_rationale(self, tmp_path: Path) -> None:
        config = _make_config(tmp_path)
        dag = _populated_dag(tmp_path)
        review = generate_plan_review(dag, config)
        assert "Types first" in review
        dag.close()

    def test_includes_phase_descriptions(self, tmp_path: Path) -> None:
        config = _make_config(tmp_path)
        dag = _populated_dag(tmp_path)
        review = generate_plan_review(dag, config)
        assert "Create type definitions" in review
        assert "Build the implementation" in review
        dag.close()

    def test_includes_dependencies(self, tmp_path: Path) -> None:
        config = _make_config(tmp_path)
        dag = _populated_dag(tmp_path)
        review = generate_plan_review(dag, config)
        assert "p1" in review  # dependency reference
        dag.close()

    def test_includes_resume_command(self, tmp_path: Path) -> None:
        config = _make_config(tmp_path)
        dag = _populated_dag(tmp_path)
        review = generate_plan_review(dag, config)
        assert "cleave architect --resume" in review
        dag.close()


class TestWriteReport:
    def test_writes_file(self, tmp_path: Path) -> None:
        config = _make_config(tmp_path)
        dag = _populated_dag(tmp_path)
        output_dir = tmp_path / "output"
        output_dir.mkdir()
        report_path = write_report(dag, config, output_dir)
        assert report_path.exists()
        assert report_path.name == ".architect-report.md"
        content = report_path.read_text()
        assert "Build auth system" in content
        dag.close()


class TestWritePlanReview:
    def test_writes_file(self, tmp_path: Path) -> None:
        config = _make_config(tmp_path)
        dag = _populated_dag(tmp_path)
        output_dir = tmp_path / "output"
        output_dir.mkdir()
        review_path = write_plan_review(dag, config, output_dir)
        assert review_path.exists()
        assert review_path.name == "architect-plan-review.md"
        dag.close()
