"""Orchestrator report generation.

Produces .orchestrator-report.md with timing, costs, per-child summary,
and overall success/failure status.
"""

from __future__ import annotations

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

from cleave.core.file_utils import atomic_write_text
from cleave.orchestrator.state import OrchestratorState

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_report(state: OrchestratorState) -> str:
    """Generate the orchestrator report as markdown."""
    lines: list[str] = []

    # Header
    status_emoji = "COMPLETE" if state.phase == "complete" else "FAILED" if state.phase == "failed" else "IN PROGRESS"
    lines.append(f"# Orchestrator Report — {status_emoji}")
    lines.append("")

    # Summary
    lines.append("## Summary")
    lines.append("")
    lines.append(f"- **Run ID**: `{state.run_id}`")
    lines.append(f"- **Directive**: {state.directive}")
    lines.append(f"- **Repository**: `{state.repo_path}`")
    lines.append(f"- **Base branch**: `{state.base_branch}`")
    lines.append(f"- **Phase**: {state.phase}")
    lines.append(f"- **Depth**: {state.depth}")
    if state.parent_run_id:
        lines.append(f"- **Parent run**: `{state.parent_run_id}`")
    lines.append(f"- **Duration**: {_duration_str(state.started_at, state.completed_at)}")
    lines.append(f"- **Total cost**: ${state.total_cost_usd:.4f}")
    lines.append("")

    # Children summary
    if state.children:
        lines.append("## Children")
        lines.append("")
        lines.append("| # | Label | Status | Duration | Cost | Retries | Exit |")
        lines.append("|---|-------|--------|----------|------|---------|------|")
        for child in state.children:
            duration = _duration_str(child.started_at, child.completed_at)
            cost = f"${child.cost_usd:.4f}" if child.cost_usd is not None else "—"
            exit_code = str(child.exit_code) if child.exit_code is not None else "—"
            lines.append(
                f"| {child.child_id} | {child.label} | {child.status} | "
                f"{duration} | {cost} | {child.retry_count} | {exit_code} |"
            )
        lines.append("")

        # Failures detail
        failed = [c for c in state.children if c.status == "failed"]
        if failed:
            lines.append("## Failures")
            lines.append("")
            for child in failed:
                lines.append(f"### Child {child.child_id}: {child.label}")
                lines.append("")
                if child.error_message:
                    lines.append(f"```\n{child.error_message[:2000]}\n```")
                lines.append("")

        # Needs decomposition
        needs_decomp = [c for c in state.children if c.status == "needs_decomposition"]
        if needs_decomp:
            lines.append("## Needs Further Decomposition")
            lines.append("")
            for child in needs_decomp:
                lines.append(f"- **{child.label}**: Flagged as too complex for single pass")
            lines.append("")

    # Plan
    if state.plan:
        lines.append("## Plan")
        lines.append("")
        rationale = state.plan.get("rationale", "")
        if rationale:
            lines.append(f"Rationale: {rationale}")
            lines.append("")
        children_plan = state.plan.get("children", [])
        for cp in children_plan:
            lines.append(f"- **{cp.get('label', '?')}**: {cp.get('description', '')}")
        lines.append("")

    # Merge results
    if state.merge_report:
        lines.append("## Merge Results")
        lines.append("")
        mr = state.merge_report
        if mr.get("all_succeeded"):
            lines.append("All branches merged successfully.")
        else:
            lines.append("Some branches failed to merge:")
            lines.append("")
            for r in mr.get("results", []):
                status = "merged" if r.get("success") else "**CONFLICT**"
                line = f"- `{r.get('branch', '?')}`: {status}"
                conflicts = r.get("conflict_files", [])
                if conflicts:
                    line += f" — files: {', '.join(conflicts)}"
                lines.append(line)
        lines.append("")

    # Reunification
    if state.reunification:
        lines.append("## Reunification")
        lines.append("")
        reuni_status = state.reunification.get("status", "unknown")
        lines.append(f"- **Status**: {reuni_status}")
        conflicts = state.reunification.get("conflicts", [])
        if conflicts:
            lines.append(f"- **Conflicts**: {len(conflicts)}")
        lines.append("")

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

    return "\n".join(lines)


def write_report(state: OrchestratorState, workspace_path: Path) -> Path:
    """Write the orchestrator report to disk."""
    content = generate_report(state)
    report_path = workspace_path / ".orchestrator-report.md"
    atomic_write_text(report_path, content)
    logger.info("Report written to %s", report_path)
    return report_path
