"""Tests for receipt submission and retrieval."""

from __future__ import annotations

import pytest

from ads_foundation.merkle import build_merkle, generate_proof, root_hash
from ads_foundation.prooftrail import ProofTrailMonitor, _receipt_to_submission


def _make_submission(index: int = 0) -> dict:
    """Create a valid receipt submission using the real SDK."""
    monitor = ProofTrailMonitor()

    @monitor.track_tool_call
    def dummy(x):
        return x * 2

    with monitor.session(agent_id="test_agent") as session:
        for _ in range(index + 1):
            dummy(42)
        receipt = session.get_latest_receipt()

    return _receipt_to_submission(receipt)


class TestSubmitReceipt:
    def test_submit_valid(self, client, auth_headers):
        payload = _make_submission(0)
        resp = client.post("/receipts", json=payload, headers=auth_headers)
        assert resp.status_code == 201
        data = resp.json()
        assert data["verified"] is True
        assert data["index"] == 0

    def test_submit_duplicate(self, client, auth_headers):
        payload = _make_submission(0)
        resp1 = client.post("/receipts", json=payload, headers=auth_headers)
        assert resp1.status_code == 201

        resp2 = client.post("/receipts", json=payload, headers=auth_headers)
        assert resp2.status_code == 409

    def test_submit_bad_proof(self, client, auth_headers):
        payload = _make_submission(0)
        # Tamper with the record hash
        payload["record_hash"] = "aa" * 32
        resp = client.post("/receipts", json=payload, headers=auth_headers)
        assert resp.status_code == 422
        assert "verification failed" in resp.json()["detail"]


class TestListReceipts:
    def test_list_empty(self, client, auth_headers):
        resp = client.get("/receipts", headers=auth_headers)
        assert resp.status_code == 200
        data = resp.json()
        assert data["receipts"] == []
        assert data["total"] == 0

    def test_list_after_submit(self, client, auth_headers):
        payload = _make_submission(0)
        client.post("/receipts", json=payload, headers=auth_headers)

        resp = client.get("/receipts", headers=auth_headers)
        data = resp.json()
        assert data["total"] == 1
        assert data["receipts"][0]["index"] == 0
        assert data["receipts"][0]["tool_name"] == "dummy"

    def test_filter_by_agent(self, client, auth_headers):
        payload = _make_submission(0)
        client.post("/receipts", json=payload, headers=auth_headers)

        resp = client.get(
            "/receipts", params={"agent_id": "wrong"}, headers=auth_headers
        )
        assert resp.json()["total"] == 0

        resp = client.get(
            "/receipts", params={"agent_id": "test_agent"}, headers=auth_headers
        )
        assert resp.json()["total"] == 1


class TestGetReceipt:
    def test_get_by_index(self, client, auth_headers):
        payload = _make_submission(0)
        client.post("/receipts", json=payload, headers=auth_headers)

        resp = client.get("/receipts/0", headers=auth_headers)
        assert resp.status_code == 200
        assert resp.json()["index"] == 0

    def test_get_not_found(self, client, auth_headers):
        resp = client.get("/receipts/999", headers=auth_headers)
        assert resp.status_code == 404


class TestOrgIsolation:
    def test_receipts_scoped_to_api_key(self, client, auth_headers, admin_headers):
        # Submit a receipt with the test key
        payload = _make_submission(0)
        client.post("/receipts", json=payload, headers=auth_headers)

        # Create a second API key
        resp = client.post(
            "/admin/api-keys",
            json={"org_name": "Other Org"},
            headers=admin_headers,
        )
        other_key = resp.json()["api_key"]

        # The other org should see no receipts
        resp = client.get("/receipts", headers={"X-API-Key": other_key})
        assert resp.json()["total"] == 0
