"""
Curriculum outline JSON schema validation.

Validates lesson outline JSON against the Jinja2 template requirements.
Returns (valid: bool, errors: list[str]).
"""

import json
from typing import Tuple

# All section types supported by the History and ELA templates
VALID_SECTION_TYPES = {
    "reading",
    "questions",
    "vocab_grid",
    "sort_table",
    "true_false",
    "draw_grid",
    "fill_blank",
    "activity",
    "think",
    "review_table",
    "timeline",
    "vocab",
    "writing_space",
    "draw",
    "note",
    "summary",
    "objectives",
}

# Required top-level keys
REQUIRED_TOP_KEYS = {"week", "day", "topic", "subtitle", "icon", "pages"}

# Required page keys
REQUIRED_PAGE_KEYS = {"title", "sections"}

# Required section keys (all types need at least type + title)
REQUIRED_SECTION_KEYS = {"type", "title"}

# Type-specific required fields
TYPE_REQUIRED_FIELDS = {
    "reading": {"paragraphs"},
    "questions": {"questions"},
    "vocab_grid": {"words"},
    "sort_table": {"header", "rows"},
    "true_false": {"items"},
    "fill_blank": {"items"},
    "activity": {"content"},
    "think": {"questions"},
    "review_table": {"header", "rows"},
    "timeline": {"entries"},
    "vocab": {"words"},
    "writing_space": {"prompts"},
    "draw": {"instruction"},
    "note": {"content"},
    "summary": {"items"},
    "objectives": {"items"},
}


def validate_outline(data) -> Tuple[bool, list[str]]:
    """Validate a lesson outline dict. Returns (is_valid, list_of_errors)."""
    errors = []

    # Top-level keys
    missing = REQUIRED_TOP_KEYS - set(data.keys())
    if missing:
        errors.append(f"Missing top-level keys: {missing}")

    # Week/day sanity
    week = data.get("week")
    if not isinstance(week, int) or week < 1 or week > 32:
        errors.append(f"Invalid week: {week} (must be int 1-32)")

    day = data.get("day", "")
    if day not in ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday"):
        errors.append(f"Invalid day: {day}")

    # Pages
    pages = data.get("pages", [])
    if not isinstance(pages, list) or len(pages) == 0:
        errors.append("Missing or empty 'pages' array")
    else:
        if len(pages) > 5:
            errors.append(f"Too many pages: {len(pages)} (max 5)")
        for i, page in enumerate(pages):
            # Page title required on first page only, optional after
            page_required = {"sections"} if i > 0 else REQUIRED_PAGE_KEYS
            pmissing = page_required - set(page.keys())
            if pmissing:
                errors.append(f"Page {i+1}: missing keys {pmissing}")
            # Sections
            sections = page.get("sections", [])
            if not isinstance(sections, list) or len(sections) == 0:
                errors.append(f"Page {i+1}: missing or empty 'sections'")
            else:
                for j, sec in enumerate(sections):
                    # Required section keys
                    smissing = REQUIRED_SECTION_KEYS - set(sec.keys())
                    if smissing:
                        errors.append(f"Page {i+1}, Section {j+1}: missing keys {smissing}")
                        continue

                    stype = sec.get("type", "")
                    if stype not in VALID_SECTION_TYPES:
                        errors.append(
                            f"Page {i+1}, Section {j+1}: unsupported type '{stype}' "
                            f"(valid: {', '.join(sorted(VALID_SECTION_TYPES))})"
                        )
                        continue

                    # Type-specific fields
                    required = TYPE_REQUIRED_FIELDS.get(stype, set())
                    smissing_type = required - set(sec.keys())
                    if smissing_type:
                        errors.append(
                            f"Page {i+1}, Section {j+1}: type '{stype}' missing fields {smissing_type}"
                        )

                    # Content sanity
                    if stype == "reading":
                        paras = sec.get("paragraphs", [])
                        if len(paras) == 0:
                            errors.append(f"Page {i+1}: reading section has no paragraphs")
                        else:
                            for k, p in enumerate(paras):
                                word_count = len(str(p).split())
                                if word_count > 150:
                                    errors.append(
                                        f"Page {i+1}, Para {k+1}: {word_count} words "
                                        f"(target 80-120)"
                                    )

                    if stype in ("questions", "think"):
                        qs = sec.get("questions", [])
                        for k, q in enumerate(qs):
                            if "text" not in q:
                                errors.append(
                                    f"Page {i+1}, Q{k+1}: missing 'text' in question"
                                )

    return (len(errors) == 0, errors)


def validate_file(path: str) -> Tuple[bool, list[str]]:
    """Validate a JSON outline file. Returns (is_valid, errors)."""
    try:
        with open(path) as f:
            data = json.load(f)
    except json.JSONDecodeError as e:
        return False, [f"Invalid JSON: {e}"]
    except FileNotFoundError:
        return False, [f"File not found: {path}"]

    return validate_outline(data)


if __name__ == "__main__":
    import sys
    if len(sys.argv) < 2:
        print("Usage: python curriculum_schema.py <outline.json> [outline2.json ...]")
        sys.exit(1)

    all_ok = True
    for path in sys.argv[1:]:
        valid, errs = validate_file(path)
        status = "✓" if valid else "✗"
        print(f"{status} {path}")
        if not valid:
            all_ok = False
            for e in errs:
                print(f"    {e}")

    sys.exit(0 if all_ok else 1)
