"""Architect report generation.

Produces checkpoint reports (after each phase) and final summary reports.
"""

from __future__ import annotations

import logging
from datetime import UTC, datetime
from pathlib import Path

from cleave.architect.config import ArchitectConfig
from cleave.architect.dag import DAGStore

logger = logging.getLogger(__name__)


def _duration_str(start_iso: str | None, end_iso: str | None) -> str:
    """Human-readable duration between two ISO timestamps."""
    if not start_iso:
        return "unknown"
    try:
        start = datetime.fromisoformat(start_iso)
        end = datetime.fromisoformat(end_iso) if end_iso else datetime.now(UTC)
        delta = end - start
        total = int(delta.total_seconds())
        hours, remainder = divmod(total, 3600)
        minutes, seconds = divmod(remainder, 60)
        if hours > 0:
            return f"{hours}h {minutes}m {seconds}s"
        if minutes > 0:
            return f"{minutes}m {seconds}s"
        return f"{seconds}s"
    except (ValueError, TypeError):
        return "unknown"


def generate_checkpoint_report(dag: DAGStore, config: ArchitectConfig) -> str:
    """Generate a checkpoint report (after planning or mid-execution)."""
    lines: list[str] = []
    lines.append("# Architect Checkpoint Report")
    lines.append("")

    # Summary
    phases = dag.list_phases()
    completed = [p for p in phases if p.status == "completed"]
    failed = [p for p in phases if p.status == "failed"]
    pending = [p for p in phases if p.status == "pending"]
    running = [p for p in phases if p.status == "running"]
    paused = [p for p in phases if p.status == "paused"]

    lines.append("## Progress")
    lines.append("")
    lines.append(f"- **Directive**: {config.directive}")
    lines.append(f"- **Repository**: `{config.repo_path}`")
    lines.append(f"- **Total phases**: {len(phases)}")
    lines.append(f"- **Completed**: {len(completed)}")
    lines.append(f"- **Failed**: {len(failed)}")
    lines.append(f"- **Pending**: {len(pending)}")
    if running:
        lines.append(f"- **Running**: {len(running)}")
    if paused:
        lines.append(f"- **Paused**: {len(paused)}")
    lines.append(f"- **Total cost**: ${dag.total_cost():.4f}")
    lines.append(f"- **Budget remaining**: ${config.max_budget_usd - dag.total_cost():.4f}")
    lines.append("")

    # Phases table
    if phases:
        lines.append("## Phases")
        lines.append("")
        lines.append("| # | ID | Label | Status | Duration | Cost |")
        lines.append("|---|-----|-------|--------|----------|------|")
        for i, phase in enumerate(phases):
            duration = _duration_str(phase.started_at, phase.completed_at)
            cost = f"${phase.cost_usd:.4f}" if phase.cost_usd else "-"
            lines.append(
                f"| {i + 1} | `{phase.id}` | {phase.label} | {phase.status} | "
                f"{duration} | {cost} |"
            )
        lines.append("")

    # Wave structure
    waves = dag.compute_waves()
    if waves:
        lines.append("## Execution Order (Waves)")
        lines.append("")
        for i, wave in enumerate(waves):
            lines.append(f"- **Wave {i}**: {', '.join(f'`{pid}`' for pid in wave)}")
        lines.append("")

    # Gate decisions (checkpoints)
    checkpoints = dag.get_checkpoints()
    if checkpoints:
        lines.append("## Gate Decisions")
        lines.append("")
        for cp in checkpoints:
            phase_str = f" (phase: `{cp.phase_id}`)" if cp.phase_id else ""
            lines.append(f"- **{cp.gate_type}** → {cp.decision}{phase_str}: {cp.reason}")
        lines.append("")

    # Failures detail
    if failed:
        lines.append("## Failures")
        lines.append("")
        for phase in failed:
            lines.append(f"### {phase.id}: {phase.label}")
            lines.append("")
            if phase.error_message:
                lines.append(f"```\n{phase.error_message[:2000]}\n```")
            lines.append("")

    # Footer
    lines.append("---")
    lines.append(f"Generated at {datetime.now(UTC).isoformat()} by cleave architect")
    lines.append("")

    return "\n".join(lines)


def generate_plan_review(dag: DAGStore, config: ArchitectConfig) -> str:
    """Generate a human-readable plan review for --confirm gate."""
    lines: list[str] = []
    lines.append("# Architect Plan Review")
    lines.append("")
    lines.append(f"**Directive**: {config.directive}")
    lines.append("")

    rationale = dag.get_metadata("rationale")
    if rationale:
        lines.append(f"**Rationale**: {rationale}")
        lines.append("")

    phases = dag.list_phases()
    waves = dag.compute_waves()

    if waves:
        lines.append("## Execution Order")
        lines.append("")
        for i, wave in enumerate(waves):
            lines.append(f"### Wave {i}")
            lines.append("")
            for pid in wave:
                phase = dag.get_phase(pid)
                if phase:
                    deps = dag.get_dependencies(pid)
                    lines.append(f"**{phase.label}** (`{phase.id}`)")
                    lines.append("")
                    lines.append(phase.description)
                    if deps:
                        lines.append("")
                        lines.append(f"*Depends on*: {', '.join(f'`{d}`' for d in deps)}")
                    lines.append("")
    else:
        for phase in phases:
            lines.append(f"## {phase.label} (`{phase.id}`)")
            lines.append("")
            lines.append(phase.description)
            lines.append("")

    lines.append("---")
    db_path = dag.db_path
    lines.append(f"To proceed: `cleave architect --resume {db_path}`")
    lines.append("")

    return "\n".join(lines)


def write_report(dag: DAGStore, config: ArchitectConfig, output_dir: Path) -> Path:
    """Write the architect report to disk."""
    content = generate_checkpoint_report(dag, config)
    report_path = output_dir / ".architect-report.md"
    report_path.write_text(content, encoding="utf-8")
    logger.info("Report written to %s", report_path)
    return report_path


def write_plan_review(dag: DAGStore, config: ArchitectConfig, output_dir: Path) -> Path:
    """Write the plan review for --confirm gate."""
    content = generate_plan_review(dag, config)
    review_path = output_dir / "architect-plan-review.md"
    review_path.write_text(content, encoding="utf-8")
    logger.info("Plan review written to %s", review_path)
    return review_path
