#!/usr/bin/env python3
"""
Curriculum Week Validator
Run BEFORE generating PDFs to catch data errors early.

Usage:
    python3 validate_week.py generate_week9.py
"""

import sys
import re
import os

INAPPROPRIATE_WORDS = {
    "undress", "dress", "naked", "bare", "strip", "stripped",
    "bath", "shower", "toilet", "potty",
}

errors = []
warnings = []

def error(msg):
    errors.append(msg)
    print(f"  āŒ {msg}")

def warn(msg):
    warnings.append(msg)
    print(f"  āš ļø  {msg}")

def ok(msg):
    print(f"  āœ… {msg}")


def check_words(words, topic=""):
    if not isinstance(words, (list, tuple)):
        error(f"Words ({topic}): not a list/tuple — {type(words)}")
        return []
    
    word_names = []
    for item in words:
        if isinstance(item, tuple):
            word = item[0]
        elif isinstance(item, str):
            word = item
        else:
            error(f"Words ({topic}): invalid item — {item}")
            continue
        
        word_names.append(word)
        
        if len(word) < 6:
            error(f"Words: '{word}' is only {len(word)} letters — minimum is 6")
        if word.lower() in INAPPROPRIATE_WORDS:
            error(f"Words: '{word}' is inappropriate for 2nd grade")
    
    seen = set()
    for w in word_names:
        if w.lower() in seen:
            error(f"Words: duplicate — '{w}'")
        seen.add(w.lower())
    
    if len(word_names) != 12:
        warn(f"Words: expected 12 words, found {len(word_names)}")
    
    return word_names


def check_story(story, words, topic=""):
    story_lower = story.lower()
    missing = [w for w in words if w.lower() not in story_lower]
    
    if missing:
        error(f"Story ({topic}): missing words: {', '.join(missing)}")
    else:
        ok(f"Story ({topic}): all {len(words)} words present")
    
    # Grammar checks
    patterns = {
        r'\bunsafe\s+\w+\b': "unsafe used as verb? (should be adjective)",
        r'\bdishonest\s+(?:place|thing|box|room|house|building|car|park|garden|tree|path|door|wall)\b': "dishonest used for non-person?",
        r'\bremaken\b': "remaken → should be 'remade'",
        r'\bundress': "undress → inappropriate for 2nd grade",
    }
    
    for pattern, msg in patterns.items():
        if re.search(pattern, story, re.IGNORECASE):
            error(f"Story ({topic}): {msg}")


def check_fill_data(data, topic=""):
    if not isinstance(data, (list, tuple)):
        error(f"Fill ({topic}): not a list/tuple")
        return
    
    for i, item in enumerate(data):
        if isinstance(item, tuple):
            if len(item) != 2:
                error(f"Fill ({topic}) item {i}: expected (sentence, answer), got {len(item)} items")
            elif "__" not in item[0]:
                warn(f"Fill ({topic}) item {i}: sentence has no blank markers (__)")
        else:
            error(f"Fill ({topic}) item {i}: expected (sentence, answer) tuple, got {type(item).__name__}")


def check_tuple_list(data, expected_len, name, topic=""):
    if not isinstance(data, (list, tuple)):
        error(f"{name} ({topic}): not a list/tuple")
        return
    
    for i, item in enumerate(data):
        if isinstance(item, tuple):
            if len(item) != expected_len:
                error(f"{name} ({topic}) item {i}: expected {expected_len} items, got {len(item)}")
        else:
            error(f"{name} ({topic}) item {i}: expected tuple, got {type(item).__name__}")


def main():
    if len(sys.argv) < 2:
        print("Usage: python3 validate_week.py <generate_weekX.py>")
        sys.exit(1)
    
    filepath = sys.argv[1]
    if not os.path.exists(filepath):
        print(f"File not found: {filepath}")
        sys.exit(1)
    
    with open(filepath, 'r') as f:
        content = f.read()
    
    week_match = re.search(r'week(\d+)', filepath, re.IGNORECASE)
    week_num = f"Week {week_match.group(1)}" if week_match else "Unknown"
    
    print(f"šŸ” Validating: {os.path.basename(filepath)}")
    print(f"   {week_num}")
    print("=" * 60)
    
    # ---- Core Fields ----
    print("\nšŸ“¦ Core Fields:")
    
    core_fields = [
        ("WEEK", "Week directory path"),
        ("WORDS", "Word list"),
        ("LEARNING_TEXT", "Learning box text"),
    ]
    
    for field, desc in core_fields:
        if f"{field} = " in content or f"{field}=" in content:
            ok(f"{field} — {desc}")
        else:
            error(f"Missing: {field} — {desc}")
    
    # ---- Day Story Fields ----
    print("\nšŸ“– Day Stories:")
    
    story_fields = [
        ("MONDAY_STORY", "Monday"),
        ("TUESDAY_READING", "Tuesday"),
        ("WEDNESDAY_READING", "Wednesday"),
        ("THURSDAY_STORY", "Thursday"),
        ("FRIDAY_REVIEW_STORY", "Friday"),
    ]
    
    for field, day in story_fields:
        if field in content:
            ok(f"{field} — {day} story")
        else:
            error(f"Missing: {field} — {day} story")
    
    # ---- Activity Data ----
    print("\nšŸ“‹ Activity Data:")
    
    # Monday fields — grammar practice varies (strings for sentence fixing, tuples for prefixes)
    monday_fields = [
        ("MONDAY_GRAMMAR_PRACTICE", "Monday grammar practice"),
        ("MONDAY_FILL_DATA", "Monday fill-in-blank"),
        ("MONDAY_OPPOSITE_WORDS", "Monday opposites"),
        ("MONDAY_SENTENCE_WORDS", "Monday sentence words"),
    ]
    
    for field, name in monday_fields:
        if field in content:
            ok(f"{field} — {name}")
        else:
            error(f"Missing: {field} — {name}")
    
    tuesday_fields = [
        ("TUESDAY_LEARNING", "Tuesday learning"),
        ("TUESDAY_COMP_QUESTIONS", "Tuesday comp questions"),
        ("TUESDAY_REMEMBER_1", "Tuesday remember 1"),
        ("TUESDAY_REMEMBER_2", "Tuesday remember 2"),
        ("TUESDAY_SWAP_DATA", "Tuesday word swap"),
        ("TUESDAY_BUILDER_PROMPTS", "Tuesday sentence builder"),
    ]
    
    for field, name in tuesday_fields:
        if field in content:
            ok(f"{field} — {name}")
        else:
            error(f"Missing: {field} — {name}")
    
    wednesday_fields = [
        ("WEDNESDAY_LEARNING", "Wednesday learning"),
        ("WEDNESDAY_VOCAB_Q", "Wednesday vocab question"),
        ("WEDNESDAY_SYN_ANT", "Wednesday synonyms/antonyms"),
        ("WEDNESDAY_SORT_DATA", "Wednesday sentence sort"),
        ("WEDNESDAY_CORRECT", "Wednesday correct sentences"),
        ("WEDNESDAY_FILL", "Wednesday fill-in-blank"),
        ("WEDNESDAY_CONTEXT", "Wednesday context clues"),
    ]
    
    for field, name in wednesday_fields:
        if field in content:
            ok(f"{field} — {name}")
        else:
            error(f"Missing: {field} — {name}")
    
    thursday_fields = [
        ("THURSDAY_LEARNING", "Thursday learning"),
        ("THURSDAY_COMP_QUESTIONS", "Thursday comp questions"),
        ("THURSDAY_SORT_DATA", "Thursday sentence sort"),
        ("THURSDAY_DETECTIVE", "Thursday spelling detective"),
        ("THURSDAY_SWAP_DATA", "Thursday word swap"),
        ("THURSDAY_PARA_PROMPTS", "Thursday paragraph builder"),
    ]
    
    for field, name in thursday_fields:
        if field in content:
            ok(f"{field} — {name}")
        else:
            error(f"Missing: {field} — {name}")
    
    friday_fields = [
        ("FRIDAY_STORY_QUESTIONS", "Friday story questions"),
        ("FRIDAY_OPPOSITE_WORDS", "Friday opposite pairs"),
        ("FRIDAY_BUILDER_WORDS", "Friday sentence builder"),
        ("FRIDAY_JOURNAL_WORDS", "Friday word journal"),
    ]
    
    for field, name in friday_fields:
        if field in content:
            ok(f"{field} — {name}")
        else:
            error(f"Missing: {field} — {name}")
    
    # ---- Teacher Guide Data ----
    print("\nšŸ‘Øā€šŸ« Teacher Guide Data:")
    
    # Teacher guide — check core fields, some days skip separate answer keys
    teacher_fields = [
        ("TEACHER_MONDAY_GRAMMAR_EXPLANATION", "Monday grammar explanation"),
        ("TEACHER_MONDAY_FILL_ANSWERS", "Monday fill answers"),
        ("TEACHER_MONDAY_OPPOSITE_ANSWERS", "Monday opposite answers"),
        ("TEACHER_MONDAY_SENTENCE_WORDS", "Monday sentence words"),
        ("TEACHER_TUESDAY_SCRAMBLE_ANSWERS", "Tuesday scramble answers"),
        ("TEACHER_TUESDAY_COMP_ANSWERS", "Tuesday comp answers"),
        ("TEACHER_THURSDAY_DETECTIVE_ANSWERS", "Thursday detective answers"),
    ]
    
    for field, name in teacher_fields:
        if field in content:
            ok(f"Teacher: {name}")
        else:
            warn(f"Missing teacher data: {field} ({name})")
    
    # Friday comp answers — optional (may be inline with questions)
    if "TEACHER_FRIDAY_COMP_ANSWERS" in content or "FRIDAY_COMP_ANSWERS" in content:
        ok("Teacher: Friday comp answers")
    else:
        warn("No separate Friday comp answers (may be inline)")
    
    # ---- Word List ----
    print("\nšŸ“ Word List:")
    
    try:
        words_match = re.search(r'WORDS\s*=\s*(\[.*?\])', content, re.DOTALL)
        if words_match:
            words = eval(words_match.group(1))
            word_names = check_words(words, "Main")
            
            # Check story coverage
            for day, key in [("Monday", "MONDAY_STORY"), ("Tuesday", "TUESDAY_READING"),
                             ("Wednesday", "WEDNESDAY_READING"), ("Thursday", "THURSDAY_STORY"),
                             ("Friday", "FRIDAY_REVIEW_STORY")]:
                story_match = re.search(rf'{key}\s*=\s*\((.*?)\)', content, re.DOTALL)
                if story_match:
                    story = story_match.group(1).replace('\\n', '\n')
                    check_story(story, word_names, day)
    except Exception as e:
        warn(f"Could not parse word list: {e}")
    
    # ---- Main Block ----
    print("\nšŸš€ Main Block:")
    
    # Check for main execution — some weeks use if __name__, some just call at top level
    has_guarded = "if __name__" in content or "if '__name__'" in content
    has_direct_calls = all(f"generate_{day}(" in content for day in ["monday", "tuesday", "wednesday", "thursday", "friday"])
    
    if has_guarded or has_direct_calls:
        ok(f"Execution: {'guarded block' if has_guarded else 'direct calls at top level'}")
    else:
        error("No generation calls found")
    
    for gen in ["generate_monday", "generate_tuesday", "generate_wednesday",
                "generate_thursday", "generate_friday"]:
        if f"{gen}(" in content:
            ok(f"Call to {gen}")
        else:
            error(f"Missing call to {gen}")
    
    if "generate_teacher_guide" in content or "generate_teacher" in content:
        ok("Teacher guide generation")
    else:
        warn("No teacher guide generation")
    
    # ---- Fill Data Format ----
    print("\nšŸ“‹ Fill Data Format:")
    
    fill_fields = [
        ("MONDAY_FILL_DATA", "Monday fill data"),
    ]
    
    for field, name in fill_fields:
        if field in content:
            try:
                match = re.search(rf'{field}\s*=\s*(\[.*?\])', content, re.DOTALL)
                if match:
                    data = eval(match.group(1))
                    check_fill_data(data, name)
            except Exception as e:
                error(f"Could not parse {name}: {e}")
    
    # ---- Summary ----
    print("\n" + "=" * 60)
    print(f"\nšŸ“Š Validation Results:")
    print(f"   Errors:   {len(errors)}")
    print(f"   Warnings: {len(warnings)}")
    
    if errors:
        print(f"\nāŒ FAILED — {len(errors)} error(s) to fix:")
        for e in errors:
            print(f"   • {e}")
        sys.exit(1)
    elif warnings:
        print(f"\nāš ļø  PASSED with {len(warnings)} warning(s):")
        for w in warnings:
            print(f"   • {w}")
    else:
        print(f"\nšŸŽ‰ ALL CHECKS PASSED! Safe to generate PDFs.")


if __name__ == "__main__":
    main()