"""ievo orchestrate — run the coder agent in a loop."""

from __future__ import annotations

import re
import subprocess
import time
from pathlib import Path

import typer

from ievo.core.agent import AgentPackage
from ievo.core.config import AGENTS_DIR, SPEC_DIR, require_project
from ievo.core.project import ProjectManifest
from ievo.utils.console import error, info, step, success, warn


def orchestrate(
    max_iterations: int = typer.Option(
        10,
        "--max",
        "-n",
        help="Max requirements to process in one run.",
    ),
    pause: int = typer.Option(
        5,
        "--pause",
        "-p",
        help="Seconds to pause between iterations.",
    ),
    stop_on_block: bool = typer.Option(
        True,
        "--stop-on-block/--continue-on-block",
        help="Stop if agent files a question.",
    ),
    agent: str = typer.Option(
        "coder",
        "--agent",
        "-a",
        help="Agent to run (default: coder).",
    ),
    model: str | None = typer.Option(
        None,
        "--model",
        help="Override model (opus/sonnet/haiku).",
    ),
) -> None:
    """[DEPRECATED] Run the coder agent in a loop, one requirement per iteration.

    This is the automated pipeline: scan ready REQs, run agent,
    check for questions, repeat. Stops when no ready requirements
    remain or agent files a question.
    """
    from ievo.utils.deprecation import deprecated_command

    deprecated_command("ievo orchestrate", alternative="the autonomous pipeline (internal)")
    root = require_project()
    manifest = ProjectManifest.load(root)

    if not manifest.has_agent(agent):
        error(f"Agent [bold]{agent}[/bold] not installed. Run: ievo add {agent}")
        raise typer.Exit(1)

    spec_index = root / SPEC_DIR / "SPEC_INDEX.md"
    if not spec_index.exists():
        error("spec/SPEC_INDEX.md not found.")
        raise typer.Exit(1)

    # Determine model
    agent_dir = root / AGENTS_DIR / agent
    try:
        pkg = AgentPackage.load(agent_dir)
    except FileNotFoundError:
        error(f"agent.yaml not found in {agent_dir}")
        raise typer.Exit(1) from None

    agent_model = model or pkg.model.primary

    # Pre-flight
    ready_count = _count_ready(spec_index)
    info(f"Starting orchestrator: max {max_iterations} iterations, agent={agent}")
    step(f"Ready requirements: {ready_count}")

    if ready_count == 0:
        warn("No ready requirements. Nothing to do.")
        raise typer.Exit(0)

    # Create logs directory
    logs_dir = root / "logs"
    logs_dir.mkdir(exist_ok=True)

    # Main loop
    for i in range(1, max_iterations + 1):
        ready_count = _count_ready(spec_index)
        if ready_count == 0:
            info("No more ready requirements. Stopping.")
            break

        info(f"[bold]Iteration {i}/{max_iterations}[/bold] — {ready_count} ready")

        # Build and run claude command
        cmd = _build_orchestrator_command(root, agent_dir, pkg, agent_model)
        try:
            result = subprocess.run(cmd, cwd=str(root), check=False)
        except FileNotFoundError:
            error("Claude CLI not found. Install: https://docs.claude.com/en/docs/claude-code")
            raise typer.Exit(1) from None

        if result.returncode != 0:
            error(f"Agent exited with error code {result.returncode}")
            break

        # Check for new questions
        questions_count = _count_open_questions(root)
        if questions_count > 0 and stop_on_block:
            warn(f"Agent filed {questions_count} question(s). Review needed.")
            _list_questions(root)
            break

        # Pause between iterations
        if i < max_iterations and _count_ready(spec_index) > 0:
            step(f"Pausing {pause}s...")
            time.sleep(pause)

    # Summary
    _print_summary(spec_index, root)


def _count_ready(spec_index: Path) -> int:
    """Count requirements with status: ready."""
    try:
        content = spec_index.read_text()
        return len(re.findall(r"\|\s*ready\s*\|", content))
    except FileNotFoundError:
        return 0


def _count_open_questions(root: Path) -> int:
    """Count open question files."""
    questions_dir = root / SPEC_DIR / "questions"
    if not questions_dir.exists():
        return 0
    count = 0
    for qf in questions_dir.glob("Q-*.md"):
        if "Status: open" in qf.read_text():
            count += 1
    return count


def _list_questions(root: Path) -> None:
    """Print open question files."""
    questions_dir = root / SPEC_DIR / "questions"
    if not questions_dir.exists():
        return
    for qf in sorted(questions_dir.glob("Q-*.md")):
        if "Status: open" in qf.read_text():
            step(str(qf.relative_to(root)))


def _build_orchestrator_command(
    root: Path,
    agent_dir: Path,
    pkg: AgentPackage,
    model: str,
) -> list[str]:
    """Build claude CLI command for orchestrator mode."""
    cmd = ["claude"]

    model_map = {"opus": "opus", "sonnet": "sonnet", "haiku": "haiku"}
    if model in model_map:
        cmd.extend(["--model", model_map[model]])

    prompt = (
        f"Read agents/{pkg.name}/ROLE.md. You are the {pkg.name.replace('-', ' ').title()} agent.\n"
        "Read .ievo/iEVO.md for the requirement selection algorithm (Priority scoring section).\n"
        "Read spec/SPEC_INDEX.md.\n"
        "Follow the orchestration loop exactly — Steps 1 through 6.\n"
        "If anything is unclear — write questions and STOP.\n"
        "Do NOT proceed past ambiguity.\n"
        "Do NOT implement more than ONE requirement.\n"
        "After completing (or blocking), output your Iteration Report and stop."
    )
    cmd.extend(["-p", prompt])

    return cmd


def _print_summary(spec_index: Path, root: Path) -> None:
    """Print orchestrator summary."""
    try:
        content = spec_index.read_text()
    except FileNotFoundError:
        return

    implemented = len(re.findall(r"\|\s*implemented\s*\|", content))
    blocked = len(re.findall(r"\|\s*blocked\s*\|", content))
    ready = len(re.findall(r"\|\s*ready\s*\|", content))
    questions = _count_open_questions(root)

    info("[bold]Orchestrator summary:[/bold]")
    step(f"Implemented: {implemented}")
    step(f"Blocked: {blocked}")
    step(f"Ready (remaining): {ready}")
    step(f"Open questions: {questions}")
    success("Done.")
