"""Tests for child prompt construction."""

from __future__ import annotations

from pathlib import Path

from cleave.orchestrator.prompt import (
    CHILD_CONTRACT_TEMPLATE,
    build_child_prompt,
    build_planner_prompt,
)


class TestBuildChildPrompt:
    def test_includes_task_content(self, tmp_path: Path) -> None:
        task_file = tmp_path / "1-task.md"
        task_file.write_text("# Task 1\nDo the thing")
        prompt = build_child_prompt(task_file_path=task_file)
        assert "Do the thing" in prompt

    def test_includes_claude_md(self, tmp_path: Path) -> None:
        task_file = tmp_path / "1-task.md"
        task_file.write_text("# Task")
        claude_md = tmp_path / "CLAUDE.md"
        claude_md.write_text("Use rust. Always test.")
        prompt = build_child_prompt(
            task_file_path=task_file, claude_md_path=claude_md
        )
        assert "Use rust" in prompt
        assert "Repository Context" in prompt

    def test_includes_manifest(self, tmp_path: Path) -> None:
        task_file = tmp_path / "1-task.md"
        task_file.write_text("# Task")
        manifest = tmp_path / "manifest.yaml"
        manifest.write_text("directive: Test\nchildren:\n- auth-core")
        prompt = build_child_prompt(
            task_file_path=task_file, manifest_path=manifest
        )
        assert "auth-core" in prompt
        assert "Workspace Manifest" in prompt

    def test_includes_success_criteria(self, tmp_path: Path) -> None:
        task_file = tmp_path / "1-task.md"
        task_file.write_text("# Task")
        prompt = build_child_prompt(
            task_file_path=task_file,
            success_criteria=["tests pass", "clippy clean"],
        )
        assert "tests pass" in prompt
        assert "clippy clean" in prompt

    def test_includes_contract(self, tmp_path: Path) -> None:
        task_file = tmp_path / "1-task.md"
        task_file.write_text("# Task")
        prompt = build_child_prompt(task_file_path=task_file)
        assert "Orchestrator Contract" in prompt
        assert "NEEDS_DECOMPOSITION" in prompt

    def test_missing_task_file(self, tmp_path: Path) -> None:
        task_file = tmp_path / "nonexistent.md"
        prompt = build_child_prompt(task_file_path=task_file)
        assert "not found" in prompt

    def test_skips_nonexistent_optional_files(self, tmp_path: Path) -> None:
        task_file = tmp_path / "1-task.md"
        task_file.write_text("# Task")
        prompt = build_child_prompt(
            task_file_path=task_file,
            claude_md_path=tmp_path / "nope.md",
            manifest_path=tmp_path / "nope.yaml",
        )
        assert "Repository Context" not in prompt
        assert "Workspace Manifest" not in prompt

    def test_includes_siblings(self, tmp_path: Path) -> None:
        task_file = tmp_path / "1-task.md"
        task_file.write_text("# Task")
        siblings = tmp_path / "siblings.yaml"
        siblings.write_text("children:\n- label: auth-core\n  scope: [src/auth/**]")
        prompt = build_child_prompt(
            task_file_path=task_file, siblings_path=siblings
        )
        assert "auth-core" in prompt
        assert "Sibling Coordination" in prompt

    def test_contract_includes_task_file_path(self, tmp_path: Path) -> None:
        task_file = tmp_path / "1-task.md"
        task_file.write_text("# Task")
        prompt = build_child_prompt(
            task_file_path=task_file,
            workspace_path=tmp_path,
        )
        assert str(task_file) in prompt

    def test_contract_includes_timeout_and_budget(self, tmp_path: Path) -> None:
        task_file = tmp_path / "1-task.md"
        task_file.write_text("# Task")
        prompt = build_child_prompt(
            task_file_path=task_file,
            child_timeout_seconds=3600,
            child_budget_usd=10.0,
        )
        assert "3600s" in prompt
        assert "$10.00" in prompt

    def test_contract_environment_constraints(self, tmp_path: Path) -> None:
        task_file = tmp_path / "1-task.md"
        task_file.write_text("# Task")
        prompt = build_child_prompt(task_file_path=task_file)
        assert "No MCP servers" in prompt
        assert "No skills or plugins" in prompt
        assert "No subagents" in prompt

    def test_root_goal_section_present_when_differs(self, tmp_path: Path) -> None:
        task_file = tmp_path / "1-task.md"
        task_file.write_text("# Task\nFix auth subsystem")
        prompt = build_child_prompt(
            task_file_path=task_file,
            root_directive="Overhaul the entire authentication system",
        )
        assert "## Root Goal" in prompt
        assert "Overhaul the entire authentication system" in prompt

    def test_root_goal_section_absent_when_matches(self, tmp_path: Path) -> None:
        task_file = tmp_path / "1-task.md"
        task_file.write_text("# Task\nOverhaul the entire authentication system")
        prompt = build_child_prompt(
            task_file_path=task_file,
            root_directive="Overhaul the entire authentication system",
        )
        assert "## Root Goal" not in prompt

    def test_root_goal_section_absent_when_none(self, tmp_path: Path) -> None:
        task_file = tmp_path / "1-task.md"
        task_file.write_text("# Task\nDo something")
        prompt = build_child_prompt(task_file_path=task_file, root_directive=None)
        assert "## Root Goal" not in prompt


class TestBuildPlannerPrompt:
    def test_includes_directive(self, tmp_path: Path) -> None:
        prompt = build_planner_prompt("Fix auth bug", tmp_path)
        assert "Fix auth bug" in prompt

    def test_includes_success_criteria(self, tmp_path: Path) -> None:
        prompt = build_planner_prompt(
            "Fix bug", tmp_path, success_criteria=["tests pass"]
        )
        assert "tests pass" in prompt

    def test_includes_repo_structure(self, tmp_path: Path) -> None:
        (tmp_path / "src").mkdir()
        (tmp_path / "tests").mkdir()
        (tmp_path / "README.md").touch()
        prompt = build_planner_prompt("Fix bug", tmp_path)
        assert "src" in prompt
        assert "tests" in prompt

    def test_includes_claude_md(self, tmp_path: Path) -> None:
        (tmp_path / "CLAUDE.md").write_text("Use TDD always.")
        prompt = build_planner_prompt("Fix bug", tmp_path)
        assert "Use TDD always" in prompt

    def test_json_schema_in_prompt(self, tmp_path: Path) -> None:
        prompt = build_planner_prompt("Fix bug", tmp_path)
        assert '"children"' in prompt
        assert '"label"' in prompt
        assert '"description"' in prompt
        assert '"scope"' in prompt

    def test_includes_capability_constraints(self, tmp_path: Path) -> None:
        prompt = build_planner_prompt(
            "Fix bug", tmp_path,
            allowed_tools="Bash Edit Read Write",
            child_timeout_seconds=3600,
            child_budget_usd=10.0,
        )
        assert "Bash Edit Read Write" in prompt
        assert "No MCP servers" in prompt
        assert "$10.00" in prompt
        assert "3600s" in prompt

    def test_child_count_guidance(self, tmp_path: Path) -> None:
        prompt = build_planner_prompt("Fix bug", tmp_path)
        assert "2-4 children" in prompt
