from __future__ import annotations

import importlib.util
import json
import sys
from pathlib import Path

SCRIPT = Path(__file__).resolve().parents[1] / "scripts" / "npu-utilization-digest.py"
spec = importlib.util.spec_from_file_location("npu_utilization_digest", SCRIPT)
assert spec and spec.loader
digest = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = digest
spec.loader.exec_module(digest)


def test_positive_sysfs_delta_required_for_proof(tmp_path, monkeypatch):
    busy = tmp_path / "busy"
    busy.write_text("100")

    def fake_health(service, url, timeout, gate="none", mode="health_only"):
        return digest.ServiceRow(service=service, reachable=True, mode=mode, gate=gate), {"ok": True}

    def fake_post(url, payload, timeout):
        busy.write_text("100")
        return 200, {"data": [{"embedding": [0.1, 0.2]}], "embedding_dim": 2, "npu_busy_delta_us": 7}

    monkeypatch.setattr(digest, "health_row", fake_health)
    row = digest.probe_embeddings(1, busy_path=busy, post_json=fake_post)
    assert row.probe_ran is True
    assert row.proof_ok is False
    assert "no_positive_sysfs_delta" in row.warnings


def test_embeddings_row_redacts_vectors(tmp_path):
    row = digest.ServiceRow(
        service="embeddings",
        reachable=True,
        probe_ran=True,
        proof_ok=True,
        calls=1,
        items=1,
        avg_ms=12.3,
        npu_delta_us=5,
        embedding_count=1,
        embedding_dim=3,
        mode="NPU",
    )
    summary = digest.build_summary([row], None, 5, "2026-06-05T14:20:00-07:00")
    text = digest.render_text(summary, [row])
    assert "embedding_count" not in text  # counts are intentionally terse in text
    assert "0.1" not in text
    out = digest.write_jsonl(summary, [row], tmp_path)
    body = out.read_text()
    assert "embedding" in body  # compact metadata key is okay
    assert "[0.1" not in body
    assert "embedding_dim" in body


def test_classifier_dry_run_payload(tmp_path, monkeypatch):
    busy = tmp_path / "busy"
    busy.write_text("10")
    seen = {}

    def fake_health(service, url, timeout, gate="none", mode="health_only"):
        return digest.ServiceRow(service=service, reachable=True, mode=mode, gate=gate), {"ok": True}

    def fake_post(url, payload, timeout):
        seen.update(payload)
        busy.write_text("35")
        return 200, {
            "labels": {"tool_needed": True, "duplicate": False},
            "recommendation": "escalate",
            "confidence": 0.84,
            "authority_flags": {"tool_execution": False, "memory_write": False},
            "allowed_actions": ["log", "recommend"],
            "actual_action": "dry_run",
            "npu_busy_delta_us": 25,
        }

    monkeypatch.setattr(digest, "health_row", fake_health)
    row = digest.probe_classifier(1, busy_path=busy, post_json=fake_post)
    assert seen["options"]["dry_run"] is True
    assert seen["options"]["include_evidence"] is False
    assert row.escalate == 1
    assert row.suppress == 0
    assert row.recommendation == "escalate"
    assert row.confidence == 0.84
    assert row.confidence_bucket == "high"
    assert row.authority_violations == 0
    assert row.proof_ok is True


def test_doc_triage_allowed_root_compact(tmp_path):
    row = digest.ServiceRow(
        service="doc_triage",
        reachable=True,
        probe_ran=True,
        proof_ok=True,
        files=1,
        avg_ms=9,
        npu_delta_us=11,
        allowed_roots_count=1,
        mode="NPU-via-embedding-service",
        gate="closed:private-root",
    )
    summary = digest.build_summary([row], None, 11, "2026-06-05T14:20:00-07:00")
    text = digest.render_text(summary, [row])
    assert "allowed_roots=1" in text
    assert str(tmp_path) not in text


def test_advisory_gateway_health_only(monkeypatch):
    calls = []

    def fake_get(url, timeout):
        return 200, {"ok": True}

    def fake_post(url, payload, timeout):
        calls.append((url, payload))
        return 200, {}

    monkeypatch.setattr(digest, "http_get_json", fake_get)
    monkeypatch.setattr(digest, "http_post_json", fake_post)
    row, _ = digest.health_row("advisory_gateway", digest.ADVISORY_HEALTH_URL, 1, gate="closed:advisory-post")
    assert row.reachable is True
    assert row.probe_ran is False
    assert row.mode == "health_only"
    assert calls == []


def test_genai_loaded_false_skips_default_smoke(monkeypatch):
    def fake_health(service, url, timeout, gate="none", mode="health_only"):
        return digest.ServiceRow(service=service, reachable=True, mode=mode), {"ok": True, "loaded": False}

    monkeypatch.setattr(digest, "health_row", fake_health)
    row = digest.probe_genai(1, include_smoke=False)
    assert row.probe_ran is False
    assert row.loaded is False
    assert row.reason == "skipped_cold_load"
    assert row.fallbacks == 1
    assert "skipped_cold_load" in row.warnings


def test_disabled_proof_smokes_count_as_fallbacks(monkeypatch):
    def fake_health(service, url, timeout, gate="none", mode="health_only"):
        return digest.ServiceRow(service=service, reachable=True, mode=mode, gate=gate), {"ok": True, "loaded": True}

    monkeypatch.setattr(digest, "health_row", fake_health)
    rows = [
        digest.probe_whisper(1, include_smoke=False),
        digest.probe_genai(1, include_smoke=False),
        digest.probe_doc_triage(1, include_smoke=False),
    ]
    summary = digest.build_summary(rows, None, 0, "2026-06-05T14:20:00-07:00")
    assert summary["fallbacks"] == 3
    assert summary["warnings"] == {"skipped": 2, "smoke_disabled": 1}


def test_jsonl_shape(tmp_path):
    rows = [digest.ServiceRow(service="embeddings", reachable=True, probe_ran=True, proof_ok=True, calls=1, npu_delta_us=1)]
    summary = digest.build_summary(rows, None, 1, "2026-06-05T14:20:00-07:00")
    path = digest.write_jsonl(summary, rows, tmp_path)
    lines = [json.loads(line) for line in path.read_text().splitlines()]
    assert lines[0]["type"] == "summary"
    assert lines[0]["request_counts_by_service"] == {"embeddings": 1}
    assert lines[0]["npu_busy_delta_us_by_service"] == {"embeddings": 1}
    assert lines[1]["type"] == "service"
    assert lines[1]["service"] == "embeddings"


def test_summary_observability_rollups_and_text():
    rows = [
        digest.ServiceRow(service="classifier", reachable=True, calls=1, npu_delta_us=25, fallbacks=0, escalate=1, suppress=0, recommendation="escalate", confidence=0.84, confidence_bucket="high", authority_violations=0),
        digest.ServiceRow(service="doc_triage", reachable=True, calls=1, npu_delta_us=7, fallbacks=1, warnings=["no_positive_sysfs_delta"]),
        digest.ServiceRow(service="advisory_gateway", reachable=True, gate="closed:advisory-post", authority_violations=1, warnings=["authority_violation"]),
    ]
    summary = digest.build_summary(rows, None, 32, "2026-06-05T14:20:00-07:00")
    assert summary["request_counts_by_service"] == {"classifier": 1, "doc_triage": 1}
    assert summary["npu_busy_delta_us_by_service"] == {"classifier": 25, "doc_triage": 7}
    assert summary["fallbacks_by_service"] == {"doc_triage": 1}
    assert summary["confidence_distribution"] == {"high": 1}
    assert summary["recommendation_counts"] == {"escalate": 1}
    assert summary["authority_violations"] == 1
    text = digest.render_text(summary, rows)
    assert "authority_violations=1" in text
    assert "recommendations: escalate=1" in text
    assert "confidence: high=1" in text


def test_authority_violation_detection():
    assert digest.count_authority_violations({
        "authority_flags": {"tool_execution": True, "memory_write": False},
        "allowed_actions": ["log", "service_restart"],
        "actual_action": "outbound_send",
    }) == 3


def test_v1_authority_violation_detection():
    safe_payload = {
        "authority_flags": {
            "can_route_atlas": False,
            "can_write_memory": False,
            "can_execute_tools": False,
            "can_restart_services": False,
            "can_send_outbound": False,
            "can_scan_private_roots": False,
            "can_mutate_vector_store": False,
            "can_post_advisory_event": False,
            "can_change_gateway_config": False,
            "requires_human_approval": True,
            "advisory_only": True,
        },
        "allowed_actions": ["record_metric", "compare_with_expected_label", "include_in_digest", "recommend_human_review"],
        "actual_action": {"kind": "dry_run_reported", "performed": False, "performed_by": "harness", "side_effects": []},
    }
    assert digest.count_authority_violations(safe_payload) == 0
    unsafe = dict(safe_payload)
    unsafe["authority_flags"] = dict(safe_payload["authority_flags"], can_execute_tools=True)
    assert digest.count_authority_violations(unsafe) == 1


def test_recommendation_only_and_zero_confidence_rollups():
    payload = {"labels": {"no_op": {"confidence": 0.0, "score": 0.9}}, "recommendation": "suppress"}
    assert digest.extract_confidence(payload) == 0.0
    row = digest.ServiceRow(service="classifier", reachable=True, recommendation="suppress", confidence=0.0, confidence_bucket="low")
    summary = digest.build_summary([row], None, None, "2026-06-05T14:20:00-07:00")
    assert summary["recommendation_counts"] == {"suppress": 1}
    assert summary["confidence_distribution"] == {"low": 1}


def test_exit_codes(monkeypatch):
    rows = [digest.ServiceRow(service="embeddings", reachable=True, probe_ran=True, proof_ok=False, warnings=["no_positive_sysfs_delta"])]
    summary = digest.build_summary(rows, None, 0, "2026-06-05T14:20:00-07:00")
    monkeypatch.setattr(digest, "run", lambda args: (summary, rows))
    assert digest.main(["--no-write"]) == 0
    assert digest.main(["--no-write", "--strict-proof"]) == 2
