"""Escribe un DoD-contrato fijo y su estado en el sidecar goal.json de una sesion Claude."""

import json
import os

_VALID_STATUS = ("pending", "met", "failed")


def set_dod_contract(
    session_id: str,
    contract: str,
    status: str = "pending",
    goals_dir: str | None = None,
) -> dict:
    """Escribe el DoD-contrato y su estado en el goal.json de una sesion Claude.

    Lee el sidecar `<goals_dir>/<session_id>.json` si existe, preservando
    TODOS sus campos (goal, phase, dod, history, prompts, etc.), y actualiza
    solo las claves `dod_contract` y `dod_status`. La escritura es atomica
    (tmp + os.replace) para no corromper el archivo si el proceso muere a mitad.

    Args:
        session_id: ID de la sesion Claude. Da nombre al archivo
            `<session_id>.json` dentro de goals_dir.
        contract: Criterio de aceptacion estable contra el que se evalua la
            terminacion del agente. No puede ser vacio.
        status: Estado del contrato. Uno de "pending", "met" o "failed".
        goals_dir: Directorio de sidecars de goal. Por defecto
            `~/.claude/goals`.

    Returns:
        dict con session_id, path, dod_contract, dod_status y written.

    Raises:
        ValueError: si contract es vacio o status no es valido. No escribe nada.
    """
    if not contract or not contract.strip():
        raise ValueError("contract no puede ser vacio: un DoD-contrato vacio no tiene sentido")
    if status not in _VALID_STATUS:
        raise ValueError(
            f"status invalido: {status!r}. Debe ser uno de {_VALID_STATUS}"
        )

    if goals_dir is None:
        goals_dir = os.path.join(os.path.expanduser("~"), ".claude", "goals")

    os.makedirs(goals_dir, exist_ok=True)
    path = os.path.join(goals_dir, f"{session_id}.json")

    data: dict = {}
    if os.path.exists(path):
        try:
            with open(path, "r", encoding="utf-8") as f:
                loaded = json.load(f)
            if isinstance(loaded, dict):
                data = loaded
        except (json.JSONDecodeError, OSError):
            # Archivo corrupto o ilegible: no se pierde lo nuevo, se parte limpio.
            data = {}

    # Solo se tocan estas dos claves; el resto del dict se preserva intacto.
    data["dod_contract"] = contract
    data["dod_status"] = status

    tmp_path = f"{path}.tmp"
    with open(tmp_path, "w", encoding="utf-8") as f:
        json.dump(data, f, indent=2, ensure_ascii=False)
        f.write("\n")
        f.flush()
        os.fsync(f.fileno())
    os.replace(tmp_path, path)

    return {
        "session_id": session_id,
        "path": path,
        "dod_contract": contract,
        "dod_status": status,
        "written": True,
    }
