"""
Tests für buried/report — das druckerseitige Analytics-Event, das einmal pro
Druckstart feuert (verifiziert live gegen einen echten Kobra X, sowohl für
Anycubic Slicer Next als auch für OrcaSlicer/die Bridge selbst). Liefert
gcode_size/estimate_duration/total_layers, die server/files/metadata für
Dateien außerhalb des eigenen GCodeStore sonst nicht hat (Issue #102).
"""
import pytest


BURIED_PAYLOAD = {
    "type": "buried",
    "action": "PrintStart",
    "code": 200,
    "state": "done",
    "data": {
        "task_name": "Smileys_simple_plate(01)_PLA_0.2_16m39s.gcode",
        "gcode_size": 644437,
        "estimate_duration": 1264,
        "total_layers": 8,
        "storage_total": 6481,
        "storage_used": 898,
        "slicer": "OrcaSlicer",
    },
}


def test_on_buried_populates_cache(client):
    _, bridge = client
    bridge._on_buried(BURIED_PAYLOAD)
    assert bridge._buried_cache == {
        "task_name": "Smileys_simple_plate(01)_PLA_0.2_16m39s.gcode",
        "gcode_size": 644437,
        "estimate_duration": 1264,
        "total_layers": 8,
    }


def test_on_buried_populates_storage_state(client):
    _, bridge = client
    bridge._on_buried(BURIED_PAYLOAD)
    assert bridge._state["storage_total_mb"] == 6481
    assert bridge._state["storage_used_mb"] == 898


def test_on_buried_ignores_payload_without_task_name(client):
    _, bridge = client
    bridge._buried_cache = None
    bridge._on_buried({"type": "buried", "data": {"gcode_size": 123}})
    assert bridge._buried_cache is None


def test_build_file_metadata_uses_buried_fallback_for_unknown_file(client):
    """A file not in the GCodeStore and not the currently-tracked job should
    still get real size/estimated_time/layer_count from the buried cache."""
    _, bridge = client
    bridge._on_buried(BURIED_PAYLOAD)
    meta = bridge._build_file_metadata("Smileys_simple_plate(01)_PLA_0.2_16m39s.gcode")
    assert meta["size"] == 644437
    assert meta["estimated_time"] == 1264
    assert meta["layer_count"] == 8


def test_build_file_metadata_ignores_buried_cache_for_different_file(client):
    """The buried cache must only apply when task_name matches the queried
    filename - otherwise it would leak the last print's data into an
    unrelated query, the exact bug Issue #102 already fixed for live state."""
    _, bridge = client
    bridge._on_buried(BURIED_PAYLOAD)
    meta = bridge._build_file_metadata("some_other_file.gcode")
    assert meta["size"] == 1  # unchanged fallback, not leaked from buried cache
    assert meta["estimated_time"] is None
    assert meta["layer_count"] is None


def test_build_file_metadata_prefers_gcodestore_over_buried(client):
    """GCodeStore data (from the bridge's own upload) must win over the
    buried cache when both are available for the same filename."""
    _, bridge = client
    bridge._on_buried(BURIED_PAYLOAD)
    with bridge._store._lock:
        bridge._store._conn.execute(
            "INSERT INTO gcode_files (id, filename, path, size_bytes, uploaded_at, layer_count, est_print_time_sec) "
            "VALUES (?,?,?,?,?,?,?)",
            ("f1", "Smileys_simple_plate(01)_PLA_0.2_16m39s.gcode", "/tmp/f1", 999999, "2026-01-01T00:00:00Z", 42, 5000),
        )
        bridge._store._conn.commit()
    meta = bridge._build_file_metadata("Smileys_simple_plate(01)_PLA_0.2_16m39s.gcode")
    assert meta["size"] == 999999
    assert meta["estimated_time"] == 5000
    assert meta["layer_count"] == 42


@pytest.mark.asyncio
async def test_api_state_reports_storage_after_buried_report(client):
    c, bridge = client
    bridge._on_buried(BURIED_PAYLOAD)
    resp = await c.get("/api/state")
    assert resp.status == 200
    data = await resp.json()
    assert data["storage_total_mb"] == 6481
    assert data["storage_used_mb"] == 898


@pytest.mark.asyncio
async def test_api_state_storage_defaults_to_zero(client):
    c, _ = client
    resp = await c.get("/api/state")
    data = await resp.json()
    assert data["storage_total_mb"] == 0
    assert data["storage_used_mb"] == 0
