"""Tests for B17 Audit-Walk-Wiring (Stufe 1)."""

import asyncio
from unittest.mock import patch, MagicMock, AsyncMock

import pytest

from compliance.api.agent_check._b17_wiring import _render, run_b17


_FAKE_WALK = {
    "walk_id": "abc123def456",
    "url": "https://example.com/",
    "started_at": "2026-06-07T10:00:00+00:00",
    "completed_at": "2026-06-07T10:00:30+00:00",
    "engine": "playwright/webkit",
    "viewport": "1280x800",
    "actions": [
        {"timestamp": "2026-06-07T10:00:00+00:00", "action": "goto",
         "url": "https://example.com/", "status": 200},
        {"timestamp": "2026-06-07T10:00:02+00:00", "action": "accept_banner",
         "result": "clicked", "phrase": "alle akzeptieren"},
        {"timestamp": "2026-06-07T10:00:04+00:00",
         "action": "discover_footer_links", "count": 3, "links": []},
        {"timestamp": "2026-06-07T10:00:06+00:00", "action": "navigate",
         "url": "https://example.com/datenschutz",
         "anchor_text": "Datenschutz", "status": 200,
         "title": "Datenschutzerklärung"},
        {"timestamp": "2026-06-07T10:00:12+00:00",
         "action": "expand_accordions", "expanded": 5, "max": 25},
    ],
    "video": {
        "filename": "video.webm",
        "size_bytes": 512000,
        "sha256": "a1b2c3d4e5f67890fedcba0987654321ffffeeeeddddccccbbbbaaaa00001111",
    },
}


class TestRender:
    def test_renders_walk_id_and_link(self):
        html = _render(_FAKE_WALK)
        assert "abc123def456" in html
        assert "video.webm" in html
        assert "walk.json" in html

    def test_includes_sha_prefix(self):
        html = _render(_FAKE_WALK)
        # First 12 chars of sha
        assert "a1b2c3d4e5f6" in html

    def test_action_table_lists_all_actions(self):
        html = _render(_FAKE_WALK)
        # All five actions + header appear as <tr>
        assert html.count("<tr>") >= 5

    def test_nav_count_reflects_navigate_actions(self):
        html = _render(_FAKE_WALK)
        # 1 navigate in the fixture
        assert "1 Compliance-Seiten" in html

    def test_renders_accordion_expansion_count(self):
        html = _render(_FAKE_WALK)
        assert "5 Akkordeon" in html

    def test_accordion_zero_renders_neutral_text(self):
        walk = dict(_FAKE_WALK)
        walk["actions"] = [
            {"timestamp": "...", "action": "expand_accordions",
             "expanded": 0, "max": 25},
        ]
        html = _render(walk)
        assert "Keine Akkordeons gefunden" in html

    def test_dsms_anchor_rendered_when_cid_present(self):
        walk = dict(_FAKE_WALK)
        walk["video"] = dict(walk["video"])
        walk["video"]["dsms"] = {
            "cid": "QmTestCidVideoXX1234567890ABCDEFGHJKLMN",
            "gateway_url": "http://dsms-node:8080/ipfs/QmTestCidVideo",
        }
        walk["walk_json_dsms"] = {
            "cid": "QmTestCidMetaXX1234567890ABCDEFGHJKLMN",
            "gateway_url": "http://dsms-node:8080/ipfs/QmTestCidMeta",
        }
        html = _render(walk)
        assert "DSMS-Anchor" in html
        assert "QmTestCidVideoXX1234" in html
        # Internal gateway-host must be rewritten to public for the mail
        assert "dsms-node:8080" not in html

    def test_no_dsms_block_when_cid_absent(self):
        walk = dict(_FAKE_WALK)
        walk["video"] = dict(walk["video"])
        walk["video"].pop("dsms", None)
        walk.pop("walk_json_dsms", None)
        html = _render(walk)
        assert "DSMS-Anchor" not in html


class TestRunB17:
    def test_no_request_skipped(self):
        state = {}
        asyncio.run(run_b17(state))
        assert "audit_walk" not in state

    def test_no_url_skipped(self):
        state = {"req": MagicMock(documents=[MagicMock(url="")])}
        asyncio.run(run_b17(state))
        assert "audit_walk" not in state

    def test_consent_tester_failure_skipped(self):
        req = MagicMock(documents=[MagicMock(url="https://example.com/dse")])
        state = {"req": req}
        with patch(
            "compliance.api.agent_check._b17_wiring.httpx.AsyncClient"
        ) as mock_client:
            instance = mock_client.return_value.__aenter__.return_value
            instance.post = AsyncMock(side_effect=Exception("nope"))
            asyncio.run(run_b17(state))
        assert "audit_walk" not in state

    def test_success_populates_state(self):
        req = MagicMock(documents=[MagicMock(url="https://example.com/dse")])
        state = {"req": req}
        resp = MagicMock(status_code=200)
        resp.json = MagicMock(return_value=_FAKE_WALK)
        with patch(
            "compliance.api.agent_check._b17_wiring.httpx.AsyncClient"
        ) as mock_client:
            instance = mock_client.return_value.__aenter__.return_value
            instance.post = AsyncMock(return_value=resp)
            asyncio.run(run_b17(state))
        assert state["audit_walk"]["walk_id"] == "abc123def456"
        assert "video.webm" in state["audit_walk_html"]
