"""Tests for staging meta render fallbacks in unified_staging_review.

Covers:
- module_number auto-extraction from filename for ALL object types (not just pages)
- title fallback chain: meta.title → JSON quiz title → first HTML heading → obj_id
- Explicit meta values always win over auto-extraction
"""

import json
import pathlib
import sys


SCRIPTS_DIR = pathlib.Path(__file__).resolve().parents[1] / "scripts"
sys.path.insert(0, str(SCRIPTS_DIR))

import unified_staging_review  # noqa: E402


def _stage_file(tmp_path, course_id, obj_type, filename, content, meta=None):
    obj_dir = tmp_path / course_id / "staging" / obj_type
    obj_dir.mkdir(parents=True, exist_ok=True)
    obj_dir.joinpath(filename).write_text(content, encoding="utf-8")
    if meta is not None:
        obj_dir.joinpath(filename + ".meta.json").write_text(
            json.dumps(meta), encoding="utf-8"
        )


def _scan(tmp_path, course_id, monkeypatch):
    monkeypatch.setattr(unified_staging_review, "COURSES_DIR", tmp_path)
    return unified_staging_review.scan_staged_items(course_id)


# 1. Pages auto-extract module from filename — regression
def test_pages_extract_module_from_filename(tmp_path, monkeypatch):
    _stage_file(tmp_path, "c1", "pages", "m4-overview.html", "<h2>Overview</h2>")
    items = _scan(tmp_path, "c1", monkeypatch)
    page = next(i for i in items if i["type"] == "pages")
    assert page["module_number"] == 4


# 2. Assignment with meta.module_number=2 is grouped under Module 2
def test_assignment_meta_module_number_explicit(tmp_path, monkeypatch):
    _stage_file(
        tmp_path, "c1", "assignments",
        "homework-alignment-review.html",
        "<h3>HW</h3>",
        meta={"module_number": 2, "title": "HW Review"},
    )
    items = _scan(tmp_path, "c1", monkeypatch)
    item = next(i for i in items if i["type"] == "assignments")
    assert item["module_number"] == 2


# 3. Assignment without meta but filename m3-foo → mod_num = 3 (NEW)
def test_assignment_extracts_module_from_filename(tmp_path, monkeypatch):
    _stage_file(
        tmp_path, "c1", "assignments",
        "m3-homework.html", "<h3>HW</h3>",
    )
    items = _scan(tmp_path, "c1", monkeypatch)
    item = next(i for i in items if i["type"] == "assignments")
    assert item["module_number"] == 3


# 4. Assignment without meta and no module pattern in filename → 999
def test_assignment_no_meta_no_pattern_is_unmapped(tmp_path, monkeypatch):
    _stage_file(
        tmp_path, "c1", "assignments",
        "random-name.html", "<h3>X</h3>",
    )
    items = _scan(tmp_path, "c1", monkeypatch)
    item = next(i for i in items if i["type"] == "assignments")
    assert item["module_number"] == 999


# 5. Quiz with explicit meta.title preserved
def test_quiz_meta_title_preserved(tmp_path, monkeypatch):
    body = json.dumps({"quiz": {"title": "JSON Title"}})
    _stage_file(
        tmp_path, "c1", "quizzes", "m1-quiz.json", body,
        meta={"title": "Explicit Meta Title", "module_number": 1},
    )
    items = _scan(tmp_path, "c1", monkeypatch)
    item = next(i for i in items if i["type"] == "quizzes")
    assert item["meta_title"] == "Explicit Meta Title"


# 6. Assignment with explicit meta.title beats heading extraction
def test_assignment_meta_title_wins_over_heading(tmp_path, monkeypatch):
    _stage_file(
        tmp_path, "c1", "assignments",
        "m1-hw.html", "<h3>Heading Text</h3>",
        meta={"title": "Explicit Title", "module_number": 1},
    )
    items = _scan(tmp_path, "c1", monkeypatch)
    item = next(i for i in items if i["type"] == "assignments")
    assert item["meta_title"] == "Explicit Title"


# 7. Assignment without meta.title falls back to first heading text
def test_assignment_falls_back_to_first_heading(tmp_path, monkeypatch):
    _stage_file(
        tmp_path, "c1", "assignments",
        "m2-hw.html",
        '<div><h3 class="x">Module 2 Homework <span>Review</span></h3></div>',
    )
    items = _scan(tmp_path, "c1", monkeypatch)
    item = next(i for i in items if i["type"] == "assignments")
    assert item["meta_title"] == "Module 2 Homework Review"


# 8. Assignment without meta.title and no headings → meta_title stays None
def test_assignment_no_heading_no_meta_title(tmp_path, monkeypatch):
    _stage_file(
        tmp_path, "c1", "assignments",
        "m1-plain.html", "<p>no heading here</p>",
    )
    items = _scan(tmp_path, "c1", monkeypatch)
    item = next(i for i in items if i["type"] == "assignments")
    assert item["meta_title"] in (None, "")


# 9. Quiz without meta.title but quiz JSON has quiz.title → that wins (regression)
def test_quiz_falls_back_to_json_title(tmp_path, monkeypatch):
    body = json.dumps({"quiz": {"title": "Quiz From JSON"}})
    _stage_file(tmp_path, "c1", "quizzes", "m1-quiz.json", body)
    items = _scan(tmp_path, "c1", monkeypatch)
    item = next(i for i in items if i["type"] == "quizzes")
    assert item["meta_title"] == "Quiz From JSON"


# 10. Discussion picks up heading title and module from filename
def test_discussion_heading_and_filename_module(tmp_path, monkeypatch):
    _stage_file(
        tmp_path, "c1", "discussions",
        "m5-intro.html", "<h2>Module 5 Discussion</h2>",
    )
    items = _scan(tmp_path, "c1", monkeypatch)
    item = next(i for i in items if i["type"] == "discussions")
    assert item["module_number"] == 5
    assert item["meta_title"] == "Module 5 Discussion"
