# -*- coding: utf-8 -*-
"""tests.regression.test_autoset_cwd_canonical_lookup — task-2636.

Spec: memory/specs/system_callback_collector_canonical_root_spec_260523.md §8.

Reproduces the task-2635+1 incident: ANU collector spawn cwd lives under
``/home/jay/.cokacdir/workspace/autoset`` while the canonical artifact tree
is at ``/home/jay/workspace``. The collector MUST find the artifact via
canonical_root, never via getcwd().

Live subprocess calls are forbidden (monkeypatch os.getcwd).
"""
from __future__ import annotations

import json
import os

from utils.canonical_root_resolver import (
    CLASS_FOUND,
    CLASS_NOT_FOUND,
    detect_context_mismatch,
    find_artifact,
    resolve_canonical_root,
    resolve_path,
)


def test_autoset_cwd_does_not_break_canonical_lookup(tmp_path, monkeypatch):
    """The fresh-cwd false-negative incident — locked down by static gate."""
    # Stand up a canonical workspace with the artifact actually present.
    canonical = tmp_path / "workspace"
    artifact = canonical / "memory" / "reports" / "task-2636-result.json"
    artifact.parent.mkdir(parents=True)
    artifact.write_text(json.dumps({"ok": True}))

    # Pretend cwd is an autoset workspace that has no such file.
    fake_cwd = tmp_path / ".cokacdir" / "workspace" / "autoset"
    fake_cwd.mkdir(parents=True)
    monkeypatch.setattr(os, "getcwd", lambda: str(fake_cwd))

    envelope = {
        "task_id": "task-2636-tm",
        "canonical_root": str(canonical),
        "result_path": "memory/reports/task-2636-result.json",
    }

    # The resolver must surface the canonical artifact even though cwd lives
    # somewhere else (task-2635+1 incident reproduction).
    result = find_artifact(envelope, "result_path")
    assert result["found"] is True
    assert result["classification"] == CLASS_FOUND
    assert result["resolved_path"] == str(artifact)

    # The MISMATCH event must be logged because getcwd() != canonical_root.
    out = detect_context_mismatch(envelope, log_root=str(tmp_path / "log_root"))
    assert out["mismatch"] is True
    assert out["canonical_root"] == str(canonical)
    log_path = tmp_path / "log_root" / "memory" / "events" / "callback_collector_context_mismatch.jsonl"
    assert log_path.exists()
    events = [
        json.loads(line)
        for line in log_path.read_text(encoding="utf-8").splitlines()
        if line.strip()
    ]
    assert len(events) == 1
    assert events[0]["cwd"] == str(fake_cwd)
    assert events[0]["canonical_root_resolved"] == str(canonical)


def test_canonical_root_when_envelope_missing_uses_default(tmp_path, monkeypatch):
    monkeypatch.setattr(os, "getcwd", lambda: str(tmp_path / "elsewhere"))
    env = {"task_id": "x", "result_path": "memory/x.json"}
    assert resolve_canonical_root(env) == "/home/jay/workspace"
    # path resolution still uses canonical default, not cwd:
    resolved = resolve_path(env, "result_path")
    assert resolved == "/home/jay/workspace/memory/x.json"


def test_static_guard_no_cwd_in_primary_lookup_path(tmp_path, monkeypatch):
    """The COLLECTOR_LOOKUP_ORDER must never consult cwd as a primary root.

    We prove this by giving the canonical_root no artifact AND chdir-ing to a
    directory that DOES contain the artifact. The lookup must report NOT_FOUND
    instead of silently picking up the cwd-relative file.
    """
    canonical = tmp_path / "canonical"
    canonical.mkdir()
    elsewhere = tmp_path / "elsewhere"
    elsewhere.mkdir()
    artifact = elsewhere / "result.json"
    artifact.write_text("{}")
    monkeypatch.setattr(os, "getcwd", lambda: str(elsewhere))

    env = {
        "task_id": "x",
        "canonical_root": str(canonical),
        "result_path": "result.json",
    }
    out = find_artifact(env, "result_path")
    assert out["found"] is False, "lookup must NOT use cwd as a primary root"
    assert out["classification"] == CLASS_NOT_FOUND
    # the attempted path is canonical-relative — not cwd-relative
    assert str(canonical / "result.json") in out["lookup_attempts"]
    assert str(elsewhere / "result.json") not in out["lookup_attempts"]


def test_no_subprocess_calls_during_lookup(monkeypatch, tmp_path):
    """Defensive: lookup must not invoke subprocess (spec §10)."""
    import subprocess

    def _explode(*a, **kw):
        raise AssertionError("subprocess.* must not be called during lookup")

    monkeypatch.setattr(subprocess, "run", _explode)
    monkeypatch.setattr(subprocess, "Popen", _explode)
    monkeypatch.setattr(subprocess, "check_output", _explode)

    artifact = tmp_path / "memory" / "x.json"
    artifact.parent.mkdir(parents=True)
    artifact.write_text("{}")
    env = {"canonical_root": str(tmp_path), "result_path": "memory/x.json"}
    out = find_artifact(env, "result_path")
    assert out["found"] is True
