"""Work-order generator (STR-177 Week 3-4).

Converts deliberation TASK outputs into structured markdown files the
founder can copy-paste into an interactive Claude Code session. Bridges
the gap between "strategy decided this" and "founder executes this."

Work orders live at ~/.delimit/work-orders/WO-YYYY-MM-DD-NNN.md and
are surfaced via the daily digest + delimit_digest MCP tool.
"""

from __future__ import annotations

import json
import time
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Dict, List, Optional

WORK_ORDERS_DIR = Path.home() / ".delimit" / "work-orders"


def _ensure_dir():
    WORK_ORDERS_DIR.mkdir(parents=True, exist_ok=True)


def _next_id() -> str:
    _ensure_dir()
    today = datetime.now(timezone.utc).strftime("%Y-%m-%d")
    existing = sorted(WORK_ORDERS_DIR.glob(f"WO-{today}-*.md"))
    n = len(existing) + 1
    return f"WO-{today}-{n:03d}"


def create_work_order(
    title: str,
    goal: str,
    context: str = "",
    steps: Optional[List[str]] = None,
    acceptance_criteria: Optional[List[str]] = None,
    ledger_item_id: str = "",
    deliberation_ref: str = "",
    priority: str = "P1",
    estimated_minutes: int = 0,
    tools_needed: Optional[List[str]] = None,
    worker_type: str = "",
    executable_actions: Optional[List[Dict[str, Any]]] = None,
) -> Dict[str, Any]:
    """Create a work-order markdown file.

    Returns dict with the work-order ID, file path, and a preview.
    """
    _ensure_dir()
    wo_id = _next_id()
    now = datetime.now(timezone.utc).isoformat()

    lines = [
        f"# {wo_id}: {title}",
        "",
        f"**Priority**: {priority}",
        f"**Created**: {now[:19]}Z",
    ]
    if estimated_minutes:
        lines.append(f"**Estimated**: ~{estimated_minutes} min")
    if ledger_item_id:
        lines.append(f"**Ledger**: {ledger_item_id}")
    if deliberation_ref:
        lines.append(f"**Deliberation**: {deliberation_ref}")
    lines.append("")

    lines.extend([
        "## Goal",
        "",
        goal,
        "",
    ])

    if context:
        lines.extend([
            "## Context",
            "",
            context,
            "",
        ])

    if steps:
        lines.extend([
            "## Steps",
            "",
        ])
        for i, step in enumerate(steps, 1):
            if step.startswith("```") or step.startswith("  "):
                lines.append(step)
            else:
                lines.append(f"{i}. {step}")
        lines.append("")

    if tools_needed:
        lines.extend([
            "## Tools needed",
            "",
        ])
        for tool in tools_needed:
            lines.append(f"- `{tool}`")
        lines.append("")

    if acceptance_criteria:
        lines.extend([
            "## Acceptance criteria",
            "",
        ])
        for ac in acceptance_criteria:
            lines.append(f"- [ ] {ac}")
        lines.append("")

    lines.extend([
        "## How to execute",
        "",
        "Copy this work order into a Claude Code session:",
        "",
        "```",
        f"Execute work order {wo_id}: {title}",
        f"Goal: {goal}",
        "```",
        "",
        "Or run specific steps manually from the Steps section above.",
        "",
        "---",
        f"Generated by Delimit work-order system at {now}",
    ])

    content = "\n".join(lines)
    filepath = WORK_ORDERS_DIR / f"{wo_id}.md"
    filepath.write_text(content)

    # Validate executable_actions against the executor whitelist so a worker
    # can't smuggle an unsupported action through. A drafting worker that
    # emits a bad action should fail loud at draft time, not later.
    executable_actions = executable_actions or []
    if executable_actions:
        try:
            from ai.workers.executor import validate_actions
            errors = validate_actions(executable_actions)
            if errors:
                raise ValueError(
                    "executable_actions failed validation: " + "; ".join(errors)
                )
        except ImportError:
            # Executor module not available (e.g. in a stripped bundle); drop
            # the actions rather than shipping unvalidated data.
            executable_actions = []

    # Also write a JSON sidecar for machine consumption
    meta = {
        "id": wo_id,
        "title": title,
        "goal": goal,
        "context": context,
        "steps": steps or [],
        "acceptance_criteria": acceptance_criteria or [],
        "tools_needed": tools_needed or [],
        "estimated_minutes": estimated_minutes or 15,
        "priority": priority,
        "ledger_item_id": ledger_item_id,
        "deliberation_ref": deliberation_ref,
        "worker_type": worker_type,
        "executable_actions": executable_actions,
        "created_at": now,
        "status": "pending",
        "filepath": str(filepath),
        "preview": content[:2000],
    }
    (WORK_ORDERS_DIR / f"{wo_id}.json").write_text(json.dumps(meta, indent=2))

    # Fire-and-forget sync to Supabase so the dashboard approval inbox
    # can surface this work order to Pro users.
    try:
        from ai.supabase_sync import sync_work_order
        sync_work_order(meta)
    except Exception:
        pass

    return {
        "id": wo_id,
        "filepath": str(filepath),
        "preview": content[:500],
    }


def list_work_orders(status: str = "pending", limit: int = 10) -> List[Dict[str, Any]]:
    """List work orders filtered by status."""
    _ensure_dir()
    results = []
    for jf in sorted(WORK_ORDERS_DIR.glob("WO-*.json"), reverse=True):
        try:
            meta = json.loads(jf.read_text())
            if status == "all" or meta.get("status") == status:
                results.append(meta)
                if len(results) >= limit:
                    break
        except Exception:
            continue
    return results


def complete_work_order(wo_id: str, note: str = "") -> Dict[str, Any]:
    """Mark a work order as completed."""
    jf = WORK_ORDERS_DIR / f"{wo_id}.json"
    if not jf.exists():
        return {"error": f"work order {wo_id} not found"}
    meta = json.loads(jf.read_text())
    meta["status"] = "completed"
    meta["completed_at"] = datetime.now(timezone.utc).isoformat()
    if note:
        meta["completion_note"] = note
    jf.write_text(json.dumps(meta, indent=2))
    return meta
