"""Tests for graphify.ingest.save_query_result"""
from __future__ import annotations
import re
from pathlib import Path
import pytest
from graphify.ingest import save_query_result


def test_file_created(tmp_path):
    out = save_query_result("what is attention?", "Attention is...", tmp_path / "memory")
    assert out.exists()


def test_filename_format(tmp_path):
    mem = tmp_path / "memory"
    out = save_query_result("what connects A to B?", "They share...", mem)
    assert out.name.startswith("query_")
    assert out.suffix == ".md"


def test_frontmatter_question(tmp_path):
    mem = tmp_path / "memory"
    question = "what is attention?"
    out = save_query_result(question, "Attention is softmax.", mem)
    content = out.read_text()
    assert "question:" in content
    assert "attention" in content.lower()


def test_frontmatter_type(tmp_path):
    mem = tmp_path / "memory"
    out = save_query_result("q", "a", mem, query_type="path_query")
    content = out.read_text()
    assert 'type: "path_query"' in content


def test_source_nodes_included(tmp_path):
    mem = tmp_path / "memory"
    nodes = ["AttentionLayer", "SoftmaxFunc"]
    out = save_query_result("q", "a", mem, source_nodes=nodes)
    content = out.read_text()
    assert "AttentionLayer" in content
    assert "SoftmaxFunc" in content


def test_source_nodes_capped_at_10(tmp_path):
    mem = tmp_path / "memory"
    nodes = [f"Node{i}" for i in range(20)]
    out = save_query_result("q", "a", mem, source_nodes=nodes)
    content = out.read_text()
    # Only first 10 should appear in frontmatter source_nodes line
    fm_line = [l for l in content.splitlines() if l.startswith("source_nodes:")][0]
    assert fm_line.count('"Node') == 10


def test_memory_dir_created(tmp_path):
    mem = tmp_path / "deep" / "memory"
    assert not mem.exists()
    save_query_result("q", "a", mem)
    assert mem.exists()


def test_answer_in_body(tmp_path):
    mem = tmp_path / "memory"
    answer = "The answer is forty-two."
    out = save_query_result("what is the answer?", answer, mem)
    content = out.read_text()
    assert answer in content

def test_outcome_in_frontmatter_and_body(tmp_path):
    """An outcome signal is written to both frontmatter (for `reflect`) and an
    ## Outcome body section (so it round-trips into the graph on re-extraction)."""
    out = save_query_result("q", "a", tmp_path / "memory", outcome="useful")
    content = out.read_text()
    assert 'outcome: "useful"' in content
    assert "## Outcome" in content
    assert "- Signal: useful" in content


def test_correction_in_frontmatter_and_body(tmp_path):
    out = save_query_result(
        "what hashes passwords?", "MD5", tmp_path / "memory",
        outcome="corrected", correction="It's bcrypt, see PasswordHasher",
    )
    content = out.read_text()
    assert 'correction: "It\'s bcrypt, see PasswordHasher"' in content
    assert "- Correction: It's bcrypt, see PasswordHasher" in content


def test_no_outcome_means_no_outcome_section(tmp_path):
    """Backward compatible: a result without an outcome looks exactly as before."""
    out = save_query_result("q", "a", tmp_path / "memory")
    content = out.read_text()
    assert "outcome:" not in content
    assert "## Outcome" not in content


def test_invalid_outcome_rejected(tmp_path):
    with pytest.raises(ValueError):
        save_query_result("q", "a", tmp_path / "memory", outcome="great")
