"""Tests para mark_claude_parent."""

import json
import os

import pytest

from mark_claude_parent import mark_claude_parent


def _write_session(sessions_dir, pid, session_id):
    """Escribe un sessions/<pid>.json con el sessionId dado."""
    os.makedirs(sessions_dir, exist_ok=True)
    path = os.path.join(sessions_dir, f"{pid}.json")
    with open(path, "w", encoding="utf-8") as fh:
        json.dump({"sessionId": session_id, "cwd": "/tmp/whatever"}, fh)
    return path


def _write_goal(goals_dir, session_id, goal):
    """Escribe un goal/<sessionId>.json con el dict dado."""
    os.makedirs(goals_dir, exist_ok=True)
    path = os.path.join(goals_dir, f"{session_id}.json")
    with open(path, "w", encoding="utf-8") as fh:
        json.dump(goal, fh)
    return path


def _read_goal(goals_dir, session_id):
    path = os.path.join(goals_dir, f"{session_id}.json")
    with open(path, "r", encoding="utf-8") as fh:
        return json.load(fh)


def test_sessions_presente_resuelve_y_escribe_parent_preservando_otros_campos(tmp_path):
    sessions_dir = str(tmp_path / "sessions")
    goals_dir = str(tmp_path / "goals")
    pid = 4242
    sid = "executor-abc-123"
    parent = "orchestrator-xyz-789"

    _write_session(sessions_dir, pid, sid)
    # Goal preexistente con campos que NO deben perderse (incluido role).
    _write_goal(
        goals_dir,
        sid,
        {
            "goal": "implementar fase 3",
            "phase": "trabajando",
            "role": "executor",
            "dod_contract": {"capa1": "mecanica"},
        },
    )

    res = mark_claude_parent(pid, parent, wait_s=2.0,
                             sessions_dir=sessions_dir, goals_dir=goals_dir)

    assert res["ok"] is True
    assert res["pid"] == pid
    assert res["session_id"] == sid
    assert res["parent_orchestrator"] == parent
    assert res["path"] == os.path.join(goals_dir, f"{sid}.json")

    goal = _read_goal(goals_dir, sid)
    assert goal["parent_orchestrator"] == parent
    # Todos los demas campos del goal se preservan intactos.
    assert goal["goal"] == "implementar fase 3"
    assert goal["phase"] == "trabajando"
    assert goal["role"] == "executor"
    assert goal["dod_contract"] == {"capa1": "mecanica"}


def test_parent_vacio_lanza_value_error_sin_escribir(tmp_path):
    sessions_dir = str(tmp_path / "sessions")
    goals_dir = str(tmp_path / "goals")
    pid = 4242
    sid = "executor-abc-123"
    _write_session(sessions_dir, pid, sid)

    with pytest.raises(ValueError):
        mark_claude_parent(pid, "   ", wait_s=2.0,
                           sessions_dir=sessions_dir, goals_dir=goals_dir)

    # No escribio nada: el goals_dir ni siquiera deberia existir.
    assert not os.path.exists(goals_dir)


def test_sessions_ausente_devuelve_timeout_sin_crash(tmp_path):
    sessions_dir = str(tmp_path / "sessions")
    goals_dir = str(tmp_path / "goals")
    pid = 9999  # sin sessions/<pid>.json escrito

    res = mark_claude_parent(pid, "orchestrator-xyz-789", wait_s=0.5,
                             sessions_dir=sessions_dir, goals_dir=goals_dir)

    assert res["ok"] is False
    assert res["pid"] == pid
    assert "timeout" in res["error"]
    assert f"{pid}.json" in res["error"]
    # No se escribio ningun goal.
    assert not os.path.exists(goals_dir)


def test_goal_inexistente_se_crea_con_solo_parent(tmp_path):
    sessions_dir = str(tmp_path / "sessions")
    goals_dir = str(tmp_path / "goals")
    pid = 7
    sid = "fresh-executor-uuid"
    parent = "orchestrator-xyz-789"
    _write_session(sessions_dir, pid, sid)
    # No existe goal previo para esta sesion.

    res = mark_claude_parent(pid, parent, wait_s=2.0,
                             sessions_dir=sessions_dir, goals_dir=goals_dir)

    assert res["ok"] is True
    assert res["session_id"] == sid
    assert res["parent_orchestrator"] == parent

    goal = _read_goal(goals_dir, sid)
    assert goal == {"parent_orchestrator": parent}
