"""把一次 Run 的可重放事件打成最小证据包。"""
from __future__ import annotations

import json
from pathlib import Path

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from ..config import get_settings
from ..models import EvidenceBundle, Run, RunEvent, iso_z


async def build_evidence_bundle(session: AsyncSession, run: Run) -> EvidenceBundle:
    events = (
        await session.scalars(
            select(RunEvent).where(RunEvent.run_id == run.id).order_by(RunEvent.seq)
        )
    ).all()
    root = get_settings().object_store_path / "runs" / run.id
    root.mkdir(parents=True, exist_ok=True)
    timeline_path = root / "events.ndjson"
    timeline = "\n".join(
        json.dumps(
            {
                "seq": event.seq,
                "ts": iso_z(event.ts),
                "source": event.source,
                "kind": event.kind,
                "severity": event.severity,
                "message": event.message,
                "payload": event.payload,
            },
            ensure_ascii=False,
            sort_keys=True,
        )
        for event in events
    )
    timeline_path.write_text(timeline + ("\n" if timeline else ""), encoding="utf-8")
    manifest = {
        "schema_version": 1,
        "run_id": run.id,
        "workflow": {
            "key": run.workflow_key,
            "version": run.workflow_version,
            "spec_hash": run.spec_hash,
        },
        "environment_fingerprint": run.env_fingerprint,
        "checkpoint": run.checkpoint,
        "event_count": len(events),
        "files": [{"path": "events.ndjson", "bytes": timeline_path.stat().st_size}],
    }
    manifest_path = root / "manifest.json"
    manifest_path.write_text(
        json.dumps(manifest, ensure_ascii=False, indent=2, sort_keys=True),
        encoding="utf-8",
    )
    size = manifest_path.stat().st_size + timeline_path.stat().st_size
    bundle = EvidenceBundle(
        run_id=run.id,
        uri=str(root),
        manifest=manifest,
        size_bytes=size,
        completeness=1.0,
        missing_fields=[],
    )
    session.add(bundle)
    await session.flush()
    return bundle
