"""Regression tests for the C Margin faculty-preview mockup shell.

The shell is a port of the "C Margin" design (dir-c-margin.jsx): paper top bar,
full-bleed maroon pylon hero with a gold Fraunces course number, a left jump-to
TOC rail, quiet bordered page cards, and a right rail with Legend + Shortcuts.
"""

import json
import os
import shutil
import sys
from pathlib import Path

import pytest

sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "scripts"))

import mockup_manager
import staging_manager

_REAL_PLUGIN_ROOT = Path(__file__).resolve().parents[1]


@pytest.fixture
def generated_preview(tmp_path, monkeypatch):
    monkeypatch.setattr(mockup_manager, "get_plugin_root", lambda: str(tmp_path))
    monkeypatch.setattr(staging_manager, "get_plugin_root", lambda: str(tmp_path))

    # generate_preview() reads templates/mockup-html/ relative to the plugin
    # root. The fixture repoints the root to tmp_path, so copy the real
    # template tree in — otherwise generate_preview falls back to the minimal
    # inline shell and the C Margin assertions below never see the real shell.
    src_templates = _REAL_PLUGIN_ROOT / "templates" / "mockup-html"
    dst_templates = tmp_path / "templates" / "mockup-html"
    shutil.copytree(src_templates, dst_templates)

    course_id = "99998"
    mockup_manager.create_manifest(
        course_id,
        "LAW 515 Advanced Evidence",
        term="Spring 2026",
        faculty="Rivera",
    )
    manifest_path = Path(mockup_manager._manifest_path(course_id))
    manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
    manifest["courseCode"] = "LAW 515"
    manifest_path.write_text(json.dumps(manifest), encoding="utf-8")

    mockup_manager.save_page(
        course_id,
        "m0-00a-start-here.html",
        "<h3>Start Here</h3>",
        page_type="subheader",
    )
    mockup_manager.save_page(
        course_id,
        "m0-00-syllabus.html",
        "<h2>Syllabus</h2><p>Course policies and weekly rhythm.</p>",
        page_type="page",
    )
    mockup_manager.save_page(
        course_id,
        "m1-04-discussion.html",
        "<div><h2>Discussion Preview</h2><p>Placeholder card content.</p></div>",
        page_type="placeholder",
    )

    result = mockup_manager.generate_preview(course_id)
    assert result["ok"] is True
    output_path = Path(result["path"])
    return output_path, output_path.read_text(encoding="utf-8")


def test_preview_output_is_self_contained_and_small(generated_preview):
    output_path, html = generated_preview

    assert output_path.name == "LAW 515 Advanced Evidence Mockup.html"
    # One <style> block; no megabyte base64 font payloads.
    assert html.count("<style>") == 1
    assert "base64" not in html.lower()
    assert output_path.stat().st_size < 900 * 1024
    # C Margin loads Fraunces / Source Sans 3 / JetBrains Mono via a single
    # Google Fonts stylesheet link (with preconnect) — the designer's intended
    # fallback for ASU's proprietary fonts. That is the ONLY external resource.
    assert "fonts.googleapis.com" in html
    assert "Fraunces" in html


def test_preview_has_maroon_hero_and_gold_pylon(generated_preview):
    _, html = generated_preview

    assert "--maroon:#8C1D40" in html
    assert "--gold:#FFC627" in html
    assert "pylon-hero" in html
    assert "pylon-number" in html
    # The pylon number is the numeric part of the course code.
    assert "515" in html


def test_preview_hero_title_strips_course_code_prefix(tmp_path, monkeypatch):
    monkeypatch.setattr(mockup_manager, "get_plugin_root", lambda: str(tmp_path))
    monkeypatch.setattr(staging_manager, "get_plugin_root", lambda: str(tmp_path))
    shutil.copytree(
        _REAL_PLUGIN_ROOT / "templates" / "mockup-html",
        tmp_path / "templates" / "mockup-html",
    )

    course_id = "99997"
    mockup_manager.create_manifest(
        course_id,
        "LAW 515: Contracts",
        term="Spring 2026",
        faculty="Rivera",
    )
    manifest_path = Path(mockup_manager._manifest_path(course_id))
    manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
    manifest["courseCode"] = "LAW 515"
    manifest_path.write_text(json.dumps(manifest), encoding="utf-8")
    mockup_manager.save_page(
        course_id,
        "m0-00-syllabus.html",
        "<h2>Syllabus</h2><p>Course policies.</p>",
        page_type="page",
    )

    result = mockup_manager.generate_preview(course_id)
    assert result["ok"] is True
    html = Path(result["path"]).read_text(encoding="utf-8")
    assert '<h1 class="hero-title" id="preview-title">Contracts</h1>' in html
    assert '<h1 class="hero-title" id="preview-title">LAW 515' not in html


@pytest.mark.parametrize(
    ("course_name", "course_code", "expected_title"),
    [
        ("LAW 515A: Advanced Evidence", "LAW 515A", "Advanced Evidence"),
        ("ACCTG 501: Tax Research", "ACCTG 501", "Tax Research"),
        ("BIO-201: Human Physiology", "BIO 201", "Human Physiology"),
    ],
)
def test_preview_hero_title_strips_supported_course_code_shapes(
    course_name, course_code, expected_title
):
    assert mockup_manager._preview_course_title(
        course_name, course_code, "99996"
    ) == expected_title


def test_preview_has_collapsible_toc_filter_and_right_rail(generated_preview):
    _, html = generated_preview

    # Collapsible jump-to TOC rail.
    assert "aria-expanded" in html
    assert "toc-filter" in html
    assert "Filter pages" in html
    # Right rail.
    assert "THIS PREVIEW" in html
    assert "Legend" in html
    assert "Shortcuts" in html


def test_preview_renders_page_placeholder_and_subheader(generated_preview):
    _, html = generated_preview

    assert "m0-00-syllabus" in html
    assert "Syllabus" in html
    assert "status-placeholder" in html
    assert "Discussion Preview" in html
    assert "Start Here" in html


def test_preview_shortcuts_script_handles_j_and_k(generated_preview):
    _, html = generated_preview

    assert 'document.addEventListener("keydown", function(event)' in html
    assert 'key === "j" && sections[sectionIndex + 1]' in html
    assert 'key === "k" && sections[sectionIndex - 1]' in html
    assert 'activeElementIsTextInput()' in html
    assert 'tag === "input" || tag === "textarea"' in html


def test_preview_page_body_uses_canvas_page_content_styles(generated_preview):
    _, html = generated_preview

    assert '<div class="page-content"><h2>Syllabus</h2>' in html
    assert '<div class="pc">' not in html
    assert ".page-content h1 { font-size: 1.75em; font-weight: 500;" in html
    assert ".page-content h2 { font-size: 1.5em; font-weight: 500;" in html
    assert '.page-content th:not([style*="background"])' in html


def test_preview_uses_root_tokens(generated_preview):
    _, html = generated_preview

    assert ":root {" in html
    assert "--bg:#fbfaf7" in html
    assert "--rule:#ece6dc" in html
    assert "in one scroll" in html
