"""Integration seam proofs for state and compatibility boundaries.

Spec source: contract-alignment-integration.fix-seam-proof-blockers (B2/B3).
These tests avoid mocks and use real filesystem/process boundaries.
"""

from __future__ import annotations

import json
from pathlib import Path

from returns.result import Failure, Success

from anima.core.schemas import AgentNotFoundError, AgentState, JobSpec
from anima.shell.state import (
    create_agent_state,
    read_state,
    update_agent_state,
    write_state,
)


def test_state_missing_file_returns_not_found(tmp_state_dir: Path) -> None:
    """Missing state file returns typed not-found failure."""
    _ = tmp_state_dir
    result = read_state("inst_missing_state")
    assert isinstance(result, Failure)
    assert isinstance(result.failure(), AgentNotFoundError)


def test_spec_digest_explicit_null_overwrite_persists(tmp_state_dir: Path) -> None:
    """Explicit null update clears transitional spec_digest field."""
    job = JobSpec(persona_ref="persona@test", instance_id="inst_spec_digest_clear")
    created = create_agent_state(
        "inst_spec_digest_clear",
        "persona",
        job,
        spec_id="persona@test",
        spec_digest="sha256:legacy",
    )
    assert isinstance(created, Success)

    updated = update_agent_state("inst_spec_digest_clear", {"spec_digest": None})
    assert isinstance(updated, Success)
    assert updated.unwrap().spec_digest is None

    read_back = read_state("inst_spec_digest_clear")
    assert isinstance(read_back, Success)
    assert read_back.unwrap().spec_digest is None


def test_partial_state_write_is_detected_then_recoverable(tmp_state_dir: Path) -> None:
    """Partial rewrite is detected and valid rewrite recovers state file."""
    job = JobSpec(persona_ref="persona@test", instance_id="inst_partial_rewrite")
    created = create_agent_state("inst_partial_rewrite", "persona", job)
    assert isinstance(created, Success)
    state = created.unwrap()

    state_file = tmp_state_dir / "agents" / "inst_partial_rewrite" / "state.json"
    state_file.write_text('{"instance_id": "inst_partial_rewrite", "state":')

    broken = read_state("inst_partial_rewrite")
    assert isinstance(broken, Failure)

    repaired_state = state.model_copy(update={"state": AgentState.running})
    write_result = write_state("inst_partial_rewrite", repaired_state, "repair", {})
    assert isinstance(write_result, Success)

    repaired = read_state("inst_partial_rewrite")
    assert isinstance(repaired, Success)
    assert repaired.unwrap().state == AgentState.running


def test_state_fixture_rewrite_precedence_uses_latest_snapshot(
    tmp_state_dir: Path,
) -> None:
    """When old/new snapshots coexist by rewrite, latest on-disk state wins."""
    job = JobSpec(persona_ref="persona@test", instance_id="inst_rewrite_precedence")
    created = create_agent_state("inst_rewrite_precedence", "persona", job)
    assert isinstance(created, Success)

    state_file = tmp_state_dir / "agents" / "inst_rewrite_precedence" / "state.json"
    old_snapshot = json.loads(state_file.read_text())
    old_snapshot["state"] = "pending"
    state_file.write_text(json.dumps(old_snapshot))

    update_result = update_agent_state(
        "inst_rewrite_precedence", {"state": "running", "spec_digest": "sha256:new"}
    )
    assert isinstance(update_result, Success)

    latest = read_state("inst_rewrite_precedence")
    assert isinstance(latest, Success)
    assert latest.unwrap().state == AgentState.running
    assert latest.unwrap().spec_digest == "sha256:new"
