"""Deterministic orchestration helpers for v0.20."""

from __future__ import annotations

import json
from datetime import datetime, timezone
from pathlib import Path

from scripts.runtime.artifacts import ensure_phase_dirs, load_manifest, write_manifest
from scripts.runtime.methods import ResearchMethodRegistry
from scripts.runtime.tasks import generate_task_cards, generate_task_cards_from_research_brief, write_task_cards


def utc_now_iso() -> str:
    return datetime.now(timezone.utc).replace(microsecond=0).isoformat()


def create_phase2_task_cards(
    project_root: Path,
    *,
    axes: list[str] | None = None,
    dry_run: bool = False,
) -> list[dict[str, object]]:
    framework = project_root / "phase1" / "framework.md"
    if not framework.exists():
        raise FileNotFoundError(f"framework not found: {framework}")
    method_key = None
    if (project_root / "manifest.json").exists():
        method_key = load_manifest(project_root).get("research_method")
    method = ResearchMethodRegistry().get(method_key)
    research_brief_path = project_root / "phase1" / "research_brief.json"
    framework_text = framework.read_text(encoding="utf-8")
    if research_brief_path.exists():
        research_brief = json.loads(research_brief_path.read_text(encoding="utf-8"))
        if not research_brief.get("materials"):
            material_inventory = load_manifest(project_root).get("material_inventory") or []
            materials = []
            for item in material_inventory:
                rel = item.get("ocr_extracted_to") or item.get("extracted_to") or item.get("copied_to")
                if rel:
                    materials.append({"path": rel, "role": "input_material"})
            if materials:
                research_brief["materials"] = materials
        cards = generate_task_cards_from_research_brief(
            project_root.name,
            framework_text,
            research_brief,
            axes=axes,
            method=method,
        )
    else:
        cards = generate_task_cards(project_root.name, framework_text, axes=axes, method=method)
    if not dry_run:
        ensure_phase_dirs(project_root)
        write_task_cards(project_root / "phase2" / "task_cards.json", cards)
        manifest = load_manifest(project_root)
        phase2 = manifest.setdefault("phase2", {})
        phase2.update(
            {
                "status": "in_progress",
                "runtime": "python-core-v0.20",
                "research_method": method.key,
                "task_cards_path": "phase2/task_cards.json",
                "task_cards_total": len(cards),
                "updated_at": utc_now_iso(),
            }
        )
        write_manifest(project_root, manifest)
    return [card.to_dict() for card in cards]


def write_placeholder_packets(
    project_root: Path,
    task_cards: list[dict[str, object]],
    *,
    dry_run: bool = False,
) -> int:
    """Create packet skeletons for manual/API completion.

    This keeps the first v0.20 implementation deterministic and resumable; LLM
    calls can later fill the same schema without changing downstream readers.
    """
    count = 0
    for card in task_cards:
        packet_path = project_root / str(card["output_packet"])
        packet = {
            "task_id": card["task_id"],
            "claims": [],
            "evidence_items": [],
            "counter_evidence": [],
            "source_ids": [],
            "source_quality_notes": [],
            "open_questions": ["待由 Python role worker 调用模型补全。"],
            "raw_quotes_or_notes": [],
        }
        if not dry_run:
            packet_path.parent.mkdir(parents=True, exist_ok=True)
            packet_path.write_text(json.dumps(packet, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
        count += 1
    return count
