#!/usr/bin/env python3
"""
Story 8.05 — Test Suite
========================
Royal Dashboard HTML Frontend (Single File)

File under test: api/templates/royal_dashboard.html

BB Tests (3):
  BB1: HTML file contains "Royal Chamber" title
  BB2: HTML contains setInterval with 5000ms
  BB3: HTML contains fetch calls to /status, /calls/recent, /workers/active

WB Tests (3):
  WB1: No external CDN dependencies (no src="http" or src="https")
  WB2: Uses setInterval (not setTimeout chain for refresh loop)
  WB3: Dark theme present (background: #0a0a0a)

Additional coverage tests (3):
  COV1: Single file — no <link rel="stylesheet"> pointing to external resources
  COV2: AIVA status badge has all three state classes (aiva-available, aiva-oncall, aiva-processing)
  COV3: HTML is valid enough to contain all five required sections
        (active-calls, swarm-workers, queue-depth, calls-container, workers-container)

No network calls are made. All tests read the HTML file from disk.
"""
from __future__ import annotations

import sys
from pathlib import Path

import pytest

# ---------------------------------------------------------------------------
# Path setup
# ---------------------------------------------------------------------------

sys.path.insert(0, "/mnt/e/genesis-system")

_HTML_PATH = Path("/mnt/e/genesis-system/api/templates/royal_dashboard.html")


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------


def _html() -> str:
    """Return the full HTML content as a string. Fails fast if file not found."""
    assert _HTML_PATH.exists(), (
        f"royal_dashboard.html not found at {_HTML_PATH}. "
        "Create api/templates/royal_dashboard.html before running tests."
    )
    return _HTML_PATH.read_text(encoding="utf-8")


# ---------------------------------------------------------------------------
# BB1 — HTML file contains "Royal Chamber" title
# ---------------------------------------------------------------------------


class TestBB1_Title:
    """BB1: The HTML file must contain 'Royal Chamber' in the title tag."""

    def test_file_exists(self):
        """BB1: The HTML file must exist at the expected path."""
        assert _HTML_PATH.exists(), f"File not found: {_HTML_PATH}"

    def test_title_tag_contains_royal_chamber(self):
        """BB1: <title> tag must contain 'Royal Chamber'."""
        content = _html()
        assert "Royal Chamber" in content, (
            "Expected 'Royal Chamber' in HTML title, not found."
        )

    def test_h1_contains_royal_chamber(self):
        """BB1: Page heading <h1> must also display 'Royal Chamber'."""
        content = _html()
        assert "<h1>" in content and "Royal Chamber" in content, (
            "Expected <h1> element containing 'Royal Chamber'."
        )

    def test_genesis_system_reference(self):
        """BB1: Page subtitle must reference 'AIVA Command Centre'."""
        content = _html()
        assert "AIVA Command Centre" in content, (
            "Expected 'AIVA Command Centre' subtitle in HTML."
        )


# ---------------------------------------------------------------------------
# BB2 — HTML contains setInterval with 5000ms
# ---------------------------------------------------------------------------


class TestBB2_AutoRefresh:
    """BB2: Auto-refresh must be implemented via setInterval(refresh, 5000)."""

    def test_set_interval_present(self):
        """BB2: setInterval must be present in the HTML script block."""
        content = _html()
        assert "setInterval" in content, (
            "Expected 'setInterval' in HTML for auto-refresh."
        )

    def test_set_interval_uses_5000ms(self):
        """BB2: setInterval must be called with 5000 (5 seconds)."""
        content = _html()
        assert "5000" in content, (
            "Expected '5000' (5-second interval) in setInterval call."
        )

    def test_set_interval_with_refresh_function(self):
        """BB2: setInterval must reference a refresh function."""
        content = _html()
        # Both the function definition and the interval call must be present
        assert "setInterval" in content, "setInterval not found"
        assert "5000" in content, "5000ms interval value not found"
        # setInterval(refresh, 5000) — the combination means refresh is the callback
        assert "refresh" in content, "refresh function reference not found"


# ---------------------------------------------------------------------------
# BB3 — HTML contains fetch calls to all three endpoints
# ---------------------------------------------------------------------------


class TestBB3_FetchEndpoints:
    """BB3: The JS must fetch from /status, /calls/recent, and /workers/active."""

    def test_fetch_status_endpoint(self):
        """BB3: HTML must fetch from /status."""
        content = _html()
        assert "'/status'" in content or '"/status"' in content or "+ '/status'" in content or '+ "/status"' in content, (
            "Expected fetch call to '/status' endpoint in HTML."
        )

    def test_fetch_calls_recent_endpoint(self):
        """BB3: HTML must fetch from /calls/recent."""
        content = _html()
        assert "/calls/recent" in content, (
            "Expected fetch call to '/calls/recent' endpoint in HTML."
        )

    def test_fetch_workers_active_endpoint(self):
        """BB3: HTML must fetch from /workers/active."""
        content = _html()
        assert "/workers/active" in content, (
            "Expected fetch call to '/workers/active' endpoint in HTML."
        )

    def test_all_three_endpoints_present(self):
        """BB3: All three fetch endpoints must be present in the same HTML file."""
        content = _html()
        missing = []
        if "/status" not in content:
            missing.append("/status")
        if "/calls/recent" not in content:
            missing.append("/calls/recent")
        if "/workers/active" not in content:
            missing.append("/workers/active")
        assert not missing, f"Missing fetch endpoints: {missing}"


# ---------------------------------------------------------------------------
# WB1 — No external CDN dependencies
# ---------------------------------------------------------------------------


class TestWB1_NoCDNDependencies:
    """WB1: HTML must be self-contained — no external src= or href= references."""

    def test_no_external_script_src(self):
        """WB1: No <script src='http...'> or <script src='https...'> tags."""
        content = _html().lower()
        import re

        external_scripts = re.findall(r'<script[^>]+src=["\']https?://', content)
        assert not external_scripts, (
            f"Found external script CDN dependencies: {external_scripts}. "
            "Dashboard must be self-contained (no external JS)."
        )

    def test_no_external_css_link(self):
        """WB1: No <link rel='stylesheet' href='http...'> pointing to CDN."""
        content = _html().lower()
        import re

        external_css = re.findall(r'<link[^>]+href=["\']https?://', content)
        assert not external_css, (
            f"Found external CSS CDN dependencies: {external_css}. "
            "Dashboard must be self-contained (no external CSS)."
        )

    def test_no_external_img_src(self):
        """WB1: No <img src='http...'> referencing external resources."""
        content = _html().lower()
        import re

        external_imgs = re.findall(r'<img[^>]+src=["\']https?://', content)
        assert not external_imgs, (
            f"Found external image dependencies: {external_imgs}."
        )

    def test_uses_inline_styles_not_external(self):
        """WB1: Styles must be inline (in <style> tags), not from a CDN."""
        content = _html()
        assert "<style>" in content, "Expected inline <style> block in HTML."


# ---------------------------------------------------------------------------
# WB2 — Uses setInterval (not setTimeout chain)
# ---------------------------------------------------------------------------


class TestWB2_SetIntervalNotSetTimeout:
    """WB2: Refresh must use setInterval, not a recursive setTimeout chain."""

    def test_set_interval_is_present(self):
        """WB2: setInterval must be present."""
        content = _html()
        assert "setInterval" in content, (
            "Expected setInterval for auto-refresh — not found."
        )

    def test_refresh_not_implemented_as_settimeout_loop(self):
        """WB2: Recursive setTimeout pattern (setTimeout inside refresh function) should not be used."""
        content = _html()
        # Acceptable: a single setTimeout for one-time delays is fine,
        # but the PRIMARY refresh mechanism must be setInterval
        assert "setInterval" in content, (
            "setInterval is required as the primary refresh mechanism."
        )

    def test_set_interval_called_once_at_top_level(self):
        """WB2: setInterval must appear in the script (confirming it's registered)."""
        content = _html()
        count = content.count("setInterval")
        assert count >= 1, (
            f"Expected at least 1 setInterval call, found {count}."
        )


# ---------------------------------------------------------------------------
# WB3 — Dark theme present
# ---------------------------------------------------------------------------


class TestWB3_DarkTheme:
    """WB3: Dark theme must use background: #0a0a0a (or equivalent very dark color)."""

    def test_dark_background_color_present(self):
        """WB3: CSS must contain background: #0a0a0a."""
        content = _html()
        assert "#0a0a0a" in content, (
            "Expected dark background color '#0a0a0a' in CSS."
        )

    def test_gold_accent_color_present(self):
        """WB3: Gold accent color #D4AF37 must be present in CSS."""
        content = _html()
        assert "#D4AF37" in content or "#d4af37" in content, (
            "Expected gold accent color '#D4AF37' in CSS."
        )

    def test_dark_card_background_present(self):
        """WB3: Status cards must have a dark background color (#1a1a1a)."""
        content = _html()
        assert "#1a1a1a" in content, (
            "Expected dark card background '#1a1a1a' in CSS."
        )

    def test_light_text_color_present(self):
        """WB3: Text must be light-colored for contrast on dark background."""
        content = _html()
        # Accept #e0e0e0 or similar light colors
        assert "#e0e0e0" in content or "#ffffff" in content or "#f0f0f0" in content, (
            "Expected light text color (#e0e0e0 or similar) in CSS for readability."
        )


# ---------------------------------------------------------------------------
# COV1 — No external stylesheet links
# ---------------------------------------------------------------------------


class TestCOV1_NoExternalStylesheet:
    """COV1: Dashboard must not link to any external stylesheet resources."""

    def test_no_link_rel_stylesheet_to_external(self):
        """COV1: <link rel='stylesheet'> must not point to an external URL."""
        content = _html()
        import re

        # Find all <link rel="stylesheet"> tags
        links = re.findall(r'<link[^>]*rel=["\']stylesheet["\'][^>]*>', content, re.IGNORECASE)
        for link in links:
            assert "http://" not in link and "https://" not in link, (
                f"External stylesheet link found: {link}. All styles must be inline."
            )

    def test_style_block_present(self):
        """COV1: A <style> block must exist containing the dashboard styles."""
        content = _html()
        assert "<style>" in content and "</style>" in content, (
            "Expected <style>...</style> block in HTML head."
        )


# ---------------------------------------------------------------------------
# COV2 — AIVA status badge has all three state classes
# ---------------------------------------------------------------------------


class TestCOV2_AivaBadgeStates:
    """COV2: All three AIVA status badge CSS classes must be defined and used."""

    def test_aiva_available_class_present(self):
        """COV2: CSS class 'aiva-available' must be defined."""
        content = _html()
        assert "aiva-available" in content, (
            "Expected CSS class 'aiva-available' for AIVA available state."
        )

    def test_aiva_oncall_class_present(self):
        """COV2: CSS class 'aiva-oncall' must be defined."""
        content = _html()
        assert "aiva-oncall" in content, (
            "Expected CSS class 'aiva-oncall' for AIVA on-call state."
        )

    def test_aiva_processing_class_present(self):
        """COV2: CSS class 'aiva-processing' must be defined."""
        content = _html()
        assert "aiva-processing" in content, (
            "Expected CSS class 'aiva-processing' for AIVA processing state."
        )

    def test_badge_element_present(self):
        """COV2: An element with id='aiva-badge' must exist in the DOM."""
        content = _html()
        assert 'id="aiva-badge"' in content or "id='aiva-badge'" in content, (
            "Expected element with id='aiva-badge' in HTML."
        )

    def test_badge_js_updates_oncall(self):
        """COV2: JS must set badge to 'On Call' when active_calls > 0."""
        content = _html()
        assert "On Call" in content, (
            "Expected 'On Call' text in JS badge state logic."
        )

    def test_badge_js_updates_processing(self):
        """COV2: JS must set badge to 'Processing' when swarm_workers > 0."""
        content = _html()
        assert "Processing" in content, (
            "Expected 'Processing' text in JS badge state logic."
        )

    def test_badge_js_updates_available(self):
        """COV2: JS must set badge to 'Available' as default state."""
        content = _html()
        assert "Available" in content, (
            "Expected 'Available' text in JS badge default state."
        )


# ---------------------------------------------------------------------------
# COV3 — Required DOM elements present
# ---------------------------------------------------------------------------


class TestCOV3_RequiredDOMElements:
    """COV3: All five required DOM element IDs must be present in the HTML."""

    def test_active_calls_element_present(self):
        """COV3: Element with id='active-calls' must exist."""
        content = _html()
        assert 'id="active-calls"' in content or "id='active-calls'" in content, (
            "Expected element with id='active-calls'."
        )

    def test_swarm_workers_element_present(self):
        """COV3: Element with id='swarm-workers' must exist."""
        content = _html()
        assert 'id="swarm-workers"' in content or "id='swarm-workers'" in content, (
            "Expected element with id='swarm-workers'."
        )

    def test_queue_depth_element_present(self):
        """COV3: Element with id='queue-depth' must exist."""
        content = _html()
        assert 'id="queue-depth"' in content or "id='queue-depth'" in content, (
            "Expected element with id='queue-depth'."
        )

    def test_calls_container_element_present(self):
        """COV3: Element with id='calls-container' must exist."""
        content = _html()
        assert 'id="calls-container"' in content or "id='calls-container'" in content, (
            "Expected element with id='calls-container'."
        )

    def test_workers_container_element_present(self):
        """COV3: Element with id='workers-container' must exist."""
        content = _html()
        assert 'id="workers-container"' in content or "id='workers-container'" in content, (
            "Expected element with id='workers-container'."
        )

    def test_last_update_element_present(self):
        """COV3: Element with id='last-update' must exist for timestamp display."""
        content = _html()
        assert 'id="last-update"' in content or "id='last-update'" in content, (
            "Expected element with id='last-update'."
        )


# ---------------------------------------------------------------------------
# Run summary
# ---------------------------------------------------------------------------

if __name__ == "__main__":
    result = pytest.main([__file__, "-v", "--tb=short"])
    sys.exit(result)
