"""Test SessionManager audit log functionality."""

import json

import pytest

from nanobot.session.manager import Session, SessionManager


@pytest.fixture
def session_manager(tmp_path):
    return SessionManager(workspace=tmp_path)


@pytest.fixture
def session():
    s = Session(key="telegram:12345")
    s.add_message("user", "Hello")
    s.add_message("assistant", "Hi there!")
    return s


def test_save_creates_audit_file(session_manager, session):
    """SessionManager.save() should create a monthly audit log file."""
    session_manager.save(session)

    audit_files = list(session_manager.sessions_dir.glob("*.audit.*.jsonl"))
    assert len(audit_files) == 1
    assert "telegram_12345.audit." in audit_files[0].name


def test_audit_file_contains_save_marker(session_manager, session):
    """Audit log should start with a save_marker line containing metadata."""
    session_manager.save(session)

    audit_files = list(session_manager.sessions_dir.glob("*.audit.*.jsonl"))
    lines = audit_files[0].read_text().strip().split("\n")

    marker = json.loads(lines[0])
    assert marker["_type"] == "save_marker"
    assert marker["message_count"] == 2
    assert "timestamp" in marker


def test_audit_file_contains_all_messages(session_manager, session):
    """Audit log should contain all session messages after the save marker."""
    session_manager.save(session)

    audit_files = list(session_manager.sessions_dir.glob("*.audit.*.jsonl"))
    lines = audit_files[0].read_text().strip().split("\n")

    # Line 0 = save_marker, lines 1-2 = messages
    assert len(lines) == 3
    msg1 = json.loads(lines[1])
    msg2 = json.loads(lines[2])
    assert msg1["role"] == "user"
    assert msg1["content"] == "Hello"
    assert msg2["role"] == "assistant"
    assert msg2["content"] == "Hi there!"


def test_audit_file_is_append_only(session_manager, session):
    """Multiple saves should append to the same audit file, not overwrite."""
    session_manager.save(session)

    # Add another message and save again
    session.add_message("user", "How are you?")
    session_manager.save(session)

    audit_files = list(session_manager.sessions_dir.glob("*.audit.*.jsonl"))
    assert len(audit_files) == 1  # Same file

    lines = audit_files[0].read_text().strip().split("\n")

    # First save: 1 marker + 2 messages = 3 lines
    # Second save: 1 marker + 3 messages = 4 lines
    # Total: 7 lines
    assert len(lines) == 7

    # Both save markers present
    markers = [json.loads(l) for l in lines if json.loads(l).get("_type") == "save_marker"]
    assert len(markers) == 2
    assert markers[0]["message_count"] == 2
    assert markers[1]["message_count"] == 3


def test_audit_preserves_message_fields(session_manager):
    """Audit log should preserve all message fields including reasoning_content."""
    session = Session(key="test:preserve")
    session.add_raw_message({
        "role": "assistant",
        "content": "thinking response",
        "reasoning_content": [{"type": "thinking", "thinking": "deep thoughts"}],
        "timestamp": "2026-03-22T12:00:00",
    })

    session_manager.save(session)

    audit_files = list(session_manager.sessions_dir.glob("*.audit.*.jsonl"))
    lines = audit_files[0].read_text().strip().split("\n")

    msg = json.loads(lines[1])
    assert msg["reasoning_content"] == [{"type": "thinking", "thinking": "deep thoughts"}]


def test_audit_failure_does_not_break_save(session_manager, session, tmp_path):
    """If audit logging fails, the main session save should still succeed.

    _append_audit has its own try/except, so internal failures are caught.
    We simulate a realistic failure by making the sessions dir read-only
    for audit file creation.
    """
    # First save works (creates both session file and audit file)
    session_manager.save(session)

    path = session_manager._get_session_path(session.key)
    assert path.exists()

    # Remove audit files and make a blocking file at the audit path
    # so the next audit open("a") fails
    for af in session_manager.sessions_dir.glob("*.audit.*.jsonl"):
        af.unlink()

    # Create a directory where the audit file should be — open() will fail
    from datetime import datetime
    now = datetime.now()
    bad_path = session_manager.sessions_dir / f"telegram_12345.audit.{now:%Y-%m}.jsonl"
    bad_path.mkdir()

    # Second save should succeed despite audit failure
    session.add_message("user", "another message")
    session_manager.save(session)

    # Session file should still be written correctly
    with open(path) as f:
        first_line = json.loads(f.readline())
        assert first_line["_type"] == "metadata"
