"""L10: an opt-in, user-optional local transcript of what a bridge run
actually did — files, commands, diffs. Written from the event stream
(L8's widened BridgeEvent.tool), never from an agent's own self-report.

Substance never leaves the user's machine: this writes to a HOST-scoped
path under the user's own home directory, distinct from `~/.atashi/bridge.json`
(the pairing token) and never inside `workspace_dir` — workspace_dir is part
of the resume key `work_sessions` gates every resume on
(backend/services/work_sessions.py), so a transcript living inside it would
corrupt the bridge's own jail/resume behaviour.

execution_id (migration 134) does not yet reach the bridge process over the
wire — it stops at the backend's cli_bridge directive layer. This writer
carries it through when a caller has it, but does not fabricate the wiring
that would populate it; that is a separate, unbuilt backend/ws-protocol
change.
"""

from __future__ import annotations

import json
import os
from pathlib import Path
from typing import Optional

from .events import BridgeEvent


class TranscriptWriter:
    def __init__(
        self,
        *,
        enabled: bool,
        engine: str,
        agent_id: str,
        home_dir: Optional[Path] = None,
    ) -> None:
        self.enabled = enabled
        self.engine = engine
        self.agent_id = agent_id
        self._home_dir = home_dir or Path.home()
        self.engine_session_id: Optional[str] = None
        self.execution_id: Optional[str] = None

    def _path(self) -> Path:
        return self._home_dir / ".atashi" / "transcripts" / self.engine / f"{self.agent_id}.jsonl"

    def record(self, event: BridgeEvent) -> None:
        if not self.enabled:
            return
        if event.type == "session":
            self.engine_session_id = event.payload.get("engine_session_id")
            return
        if event.type != "tool":
            return
        # A bare BridgeEvent.tool(name) — every pre-L8 call site, and any
        # site L10 hasn't wired yet — carries no substance to record. Never
        # write a line whose args/result are fabricated nulls.
        if "args" not in event.payload and "result" not in event.payload:
            return

        row = {
            "engine_session_id": self.engine_session_id,
            "execution_id": self.execution_id,
            **event.to_dict(),
        }

        path = self._path()
        path.parent.mkdir(parents=True, exist_ok=True)
        path.parent.chmod(0o700)
        # Owner-only from creation (O_CREAT with 0o600, no world-readable
        # window), same convention as bridge.json's pairing token
        # (config.py) — this is the most sensitive thing the bridge sees.
        fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_APPEND, 0o600)
        try:
            os.write(fd, (json.dumps(row) + "\n").encode())
        finally:
            os.close(fd)
        path.chmod(0o600)
