"""Tests for the HTML evidence report generator."""

from __future__ import annotations

from typing import TYPE_CHECKING

import pytest

from attestmcp.models import (
    AgentIdentity,
    AuditRecord,
    IdentitySource,
    PolicyDecision,
    TrustLevel,
)
from attestmcp.report import generate_report
from attestmcp.store import SQLiteAuditStore

if TYPE_CHECKING:
    from pathlib import Path


def _make_record(
    *,
    method: str = "tools/call",
    tool_name: str | None = "store_memory",
    user: str | None = "alice@acme.com",
    agent_name: str | None = "support-bot",
    source: IdentitySource = IdentitySource.OAUTH_JWT,
    trust_level: TrustLevel = TrustLevel.CLAIMED,
    policy: PolicyDecision = PolicyDecision.ALLOW,
    session_id: str | None = "sess-001",
) -> AuditRecord:
    return AuditRecord(
        session_id=session_id,
        agent_identity=AgentIdentity(
            source=source,
            user=user,
            agent_name=agent_name,
            session_id=session_id,
            trust_level=trust_level,
            verified=trust_level == TrustLevel.VERIFIED,
        ),
        method=method,
        tool_name=tool_name,
        params_hash="abc123",
        policy_decision=policy,
        result_hash="def456",
        duration_ms=5,
    )


@pytest.fixture
def store_with_records(tmp_path: Path) -> SQLiteAuditStore:
    """Store populated with a realistic sequence of operations."""
    store = SQLiteAuditStore(db_path=str(tmp_path / "report_test.db"))

    # Initialize
    store.append(
        _make_record(method="initialize", tool_name=None)
    )
    # List tools
    store.append(
        _make_record(method="tools/list", tool_name=None)
    )
    # Store memories
    for i in range(3):
        store.append(
            _make_record(
                method="tools/call",
                tool_name="store_memory",
                session_id=f"sess-{i % 2 + 1:03d}",
            )
        )
    # Search
    store.append(
        _make_record(
            method="tools/call",
            tool_name="search_memories",
        )
    )
    return store


class TestGenerateReport:
    """HTML report generation from a populated store."""

    def test_returns_html(self, store_with_records: SQLiteAuditStore) -> None:
        html = generate_report(store_with_records)
        assert html.startswith("<!DOCTYPE html>")
        assert "</html>" in html

    def test_contains_attestmcp_branding(
        self, store_with_records: SQLiteAuditStore
    ) -> None:
        html = generate_report(store_with_records)
        assert "AttestMCP" in html
        assert "Compliance Evidence Report" in html

    def test_contains_soc2_controls(
        self, store_with_records: SQLiteAuditStore
    ) -> None:
        html = generate_report(store_with_records)
        assert "CC6.1" in html
        assert "CC6.3" in html
        assert "CC7.2" in html
        assert "CC8.1" in html

    def test_contains_chain_status(
        self, store_with_records: SQLiteAuditStore
    ) -> None:
        html = generate_report(store_with_records)
        assert "INTACT" in html

    def test_contains_total_operations(
        self, store_with_records: SQLiteAuditStore
    ) -> None:
        html = generate_report(store_with_records)
        # 6 records total
        assert ">6<" in html

    def test_contains_timeline_table(
        self, store_with_records: SQLiteAuditStore
    ) -> None:
        html = generate_report(store_with_records)
        assert "tools/call" in html
        assert "store_memory" in html
        assert "search_memories" in html

    def test_contains_identity_info(
        self, store_with_records: SQLiteAuditStore
    ) -> None:
        html = generate_report(store_with_records)
        assert "alice@acme.com" in html

    def test_contains_chain_hash_prefix(
        self, store_with_records: SQLiteAuditStore
    ) -> None:
        html = generate_report(store_with_records)
        # Chain hashes are 64 hex chars, we show first 12
        assert "Chain Hash" in html

    def test_valid_html_structure(
        self, store_with_records: SQLiteAuditStore
    ) -> None:
        html = generate_report(store_with_records)
        assert "<head>" in html
        assert "<body>" in html
        assert "<style>" in html
        assert "<table" in html


class TestGenerateReportEmpty:
    """Report generation with empty store."""

    def test_empty_store_generates_report(self, tmp_path: Path) -> None:
        store = SQLiteAuditStore(db_path=str(tmp_path / "empty.db"))
        html = generate_report(store)
        assert "<!DOCTYPE html>" in html
        assert ">0<" in html  # Total operations

    def test_empty_store_chain_intact(self, tmp_path: Path) -> None:
        store = SQLiteAuditStore(db_path=str(tmp_path / "empty.db"))
        html = generate_report(store)
        assert "INTACT" in html
