#!/usr/bin/env python3
"""Audit weeks 1-8 of the rewritten math curriculum."""

import os
import re
import subprocess
import sys
from pathlib import Path

BASE = Path("/home/vincent/Home_School/2nd_Grade/Math")
REPORT_LINES = []

def log(msg=""):
    print(msg)
    REPORT_LINES.append(msg)

def check_week(week_num, rewritten_file):
    log(f"\n{'='*60}")
    log(f"## Week {week_num}")
    log(f"{'='*60}")
    
    issues = []
    warnings = []
    principles_met = {
        "fewer_drill": False,
        "estimation": False,
        "multiple_strategies": False,
        "better_word_problems": False,
        "open_ended": False,
        "number_talks": False,
        "friday_reflection": False,
    }
    
    # 1. Check which generator to use
    rewritten = BASE / rewritten_file
    original = BASE / f"generate_week{week_num}.py"
    
    gen_file = rewritten if rewritten.exists() else original
    if not gen_file.exists():
        issues.append(f"Generator NOT FOUND: {gen_file.name}")
        return issues, warnings, principles_met
    
    log(f"**Generator:** {gen_file.name}")
    content = gen_file.read_text()
    
    # 2. Check for corruption
    if "File unchanged since last read" in content:
        issues.append("CORRUPTION: Contains 'File unchanged since last read'")
    
    # 3. Check docstring
    doc_match = re.search(r'(?:"""|\'\'\')(.*?)\1', content, re.DOTALL)
    if doc_match:
        docstring = doc_match.group(1)
        log(f"**Docstring:** {docstring[:200].strip()[:100]}...")
    else:
        warnings.append("No docstring found")
    
    # 4. Check imports
    import_lines = [l.strip() for l in content.split('\n') if l.strip().startswith('import ') or l.strip().startswith('from ')]
    log(f"**Imports:** {len(import_lines)} lines")
    
    # 5. Run generator and check for errors
    log(f"**Running generator...**")
    result = subprocess.run(
        [sys.executable, str(gen_file)],
        capture_output=True, text=True, timeout=120,
        cwd=str(BASE)
    )
    
    if result.returncode != 0:
        issues.append(f"GENERATION FAILED (exit {result.returncode})")
        if result.stderr:
            # Get last 5 lines of stderr
            stderr_lines = result.stderr.strip().split('\n')[-5:]
            issues.append(f"  stderr: {'; '.join(stderr_lines)}")
    else:
        log(f"  ✓ Generated successfully")
        stdout_lines = [l.strip() for l in result.stdout.strip().split('\n') if l.strip()]
        for line in stdout_lines:
            log(f"  {line}")
    
    # 6. Check PDF output
    week_dir = BASE / f"Week_{week_num}"
    if week_dir.exists():
        pdfs = sorted(week_dir.glob("*.pdf"))
        log(f"**PDFs in {week_dir.name}:** {len(pdfs)}")
        for pdf in pdfs:
            size_kb = pdf.stat().st_size / 1024
            log(f"  - {pdf.name} ({size_kb:.0f} KB)")
            if size_kb < 5:
                warnings.append(f"  {pdf.name} is very small ({size_kb:.0f} KB) — possibly empty")
            if size_kb > 500:
                warnings.append(f"  {pdf.name} is very large ({size_kb:.0f} KB)")
    else:
        issues.append(f"Output directory Week_{week_num} does not exist")
    
    # 7. Check New Standard compliance by scanning content
    # Look for evidence of each principle
    lower_content = content.lower()
    
    # Principle 1: 40% fewer drill problems
    # Count problem-generating loops - fewer = better
    problem_count_matches = re.findall(r'for\s+\w+\s+in\s+range\((\d+)\)', content)
    if problem_count_matches:
        max_problems = max(int(x) for x in problem_count_matches)
        if max_problems <= 6:
            principles_met["fewer_drill"] = True
            log(f"  ✓ Fewer drill (max {max_problems} problems)")
        else:
            issues.append(f"  Too many drill problems (max {max_problems}, target ≤6)")
    else:
        log(f"  ? No range() loops found — activity count unclear")
    
    # Principle 2: Estimation before calculating
    if any(w in lower_content for w in ['estimate', 'about how', 'roughly', 'approximately', 'before you calculate']):
        principles_met["estimation"] = True
        log(f"  ✓ Has estimation activities")
    else:
        warnings.append("  No estimation activities detected")
    
    # Principle 3: Multiple strategies
    if any(w in lower_content for w in ['two ways', 'show another way', 'different method', 'number line', 'draw a picture', 'mental math', 'strategy']):
        principles_met["multiple_strategies"] = True
        log(f"  ✓ Multiple strategies encouraged")
    else:
        warnings.append("  No multiple-strategy prompts detected")
    
    # Principle 4: Better word problems (not keyword-spotting)
    if any(w in lower_content for w in ['explain', 'describe how', 'tell why', 'reason', 'thinking']):
        principles_met["better_word_problems"] = True
        log(f"  ✓ Reasoning-based word problems")
    else:
        warnings.append("  Word problems may be keyword-spotting style")
    
    # Principle 5: Open-ended challenges
    if any(w in lower_content for w in ['create your own', 'make up', 'design your', 'write a problem', 'challenge', 'bonus']):
        principles_met["open_ended"] = True
        log(f"  ✓ Open-ended challenges present")
    else:
        warnings.append("  No open-ended challenges detected")
    
    # Principle 6: Number talks
    if any(w in lower_content for w in ['number talk', 'explain without', 'compare without', 'which is larger', 'which is bigger', 'without calculating']):
        principles_met["number_talks"] = True
        log(f"  ✓ Number talks present")
    else:
        warnings.append("  No number talks detected")
    
    # Principle 7: Friday reflection
    if any(w in lower_content for w in ['self-check', 'self check', 'reflection', 'one thing i learned', 'what i learned', 'how did you', '⭐', 'self-assess']):
        principles_met["friday_reflection"] = True
        log(f"  ✓ Friday reflection present")
    else:
        warnings.append("  No Friday self-check/reflection detected")
    
    # 8. Check for pre-filled answers
    if re.search(r'answer\s*=\s*["\']?\d+', content):
        # Check if answers appear in the HTML/template
        if 'answer' in lower_content and ('blank' not in lower_content or 'fill' not in lower_content):
            pass  # answers in code are fine if not rendered
    # Look for answer keys in wrong places
    if re.findall(r'<td>\s*\d+\s*</td>', content):
        potential_answers = re.findall(r'<td>\s*(\d+)\s*</td>', content)
        if len(potential_answers) > 10:
            warnings.append(f"  Many <td> with numbers ({len(potential_answers)}) — check for pre-filled answers")
    
    # 9. Activity count check (max 5 per day)
    # Count distinct activity sections
    activity_sections = re.findall(r'class="section|id="section|<div class="activity|section_title|activity_title', content)
    if activity_sections:
        # Rough estimate: 5 sections/day * 5 days = 25
        sections_per_day = len(activity_sections) / 5
        if sections_per_day > 6:
            warnings.append(f"  ~{sections_per_day:.0f} sections/day (max 5 recommended)")
    
    return issues, warnings, principles_met


def main():
    log("# Math Curriculum Audit — Weeks 1-8")
    log(f"Date: {__import__('datetime').date.today().isoformat()}")
    log("")
    
    # Week mapping: which generator is the "rewritten" version
    week_generators = {
        1: "generate_week1.py",           # original, marked ❌ empty
        2: "generate_week2_rewritten.py", # rewritten
        3: "generate_week3.py",           # rewritten (no _rewritten suffix)
        4: "generate_week4_rewritten.py", # rewritten
        5: "generate_week5_rewritten.py", # rewritten
        6: "generate_week6.py",           # rewritten
        7: "generate_week7_rewritten.py", # rewritten
        8: "generate_week8_rewritten.py", # rewritten
    }
    
    all_results = {}
    
    for week, gen_file in week_generators.items():
        issues, warnings, principles = check_week(week, gen_file)
        all_results[week] = {
            "issues": issues,
            "warnings": warnings,
            "principles": principles,
        }
    
    # Summary table
    log(f"\n\n{'='*60}")
    log("## SUMMARY")
    log(f"{'='*60}")
    log("")
    
    header = f"{'Week':>4} | {'Gen':<35} | {'Errs':>4} | {'Warn':>4} | {'Principles':>10} | Grade"
    log(header)
    log("-" * len(header))
    
    for week in range(1, 9):
        r = all_results[week]
        p = r["principles"]
        met_count = sum(1 for v in p.values() if v)
        
        if len(r["issues"]) == 0 and met_count >= 5:
            grade = "A"
        elif len(r["issues"]) == 0 and met_count >= 3:
            grade = "B"
        elif len(r["issues"]) <= 2 and met_count >= 2:
            grade = "C"
        elif len(r["issues"]) <= 3:
            grade = "D"
        else:
            grade = "F"
        
        log(f"{week:>4} | {week_generators[week]:<35} | {len(r['issues']):>4} | {len(r['warnings']):>4} | {met_count:>4}/7      | {grade}")
    
    # Detail issues
    log(f"\n\n## ISSUES BY WEEK")
    for week in range(1, 9):
        r = all_results[week]
        if r["issues"] or r["warnings"]:
            log(f"\n### Week {week}")
            for issue in r["issues"]:
                log(f"  ❌ {issue}")
            for warn in r["warnings"]:
                log(f"  ⚠️  {warn}")
    
    # Principles summary
    log(f"\n\n## PRINCIPLES COMPLIANCE")
    principles_names = {
        "fewer_drill": "40% fewer drill",
        "estimation": "Estimation first",
        "multiple_strategies": "Multiple strategies",
        "better_word_problems": "Better word problems",
        "open_ended": "Open-ended challenges",
        "number_talks": "Number talks",
        "friday_reflection": "Friday reflection",
    }
    
    log("")
    header = f"{'Principle':<25} " + "".join(f" W{w:>2}" for w in range(1, 9))
    log(header)
    for pname, label in principles_names.items():
        row = f"{label:<25}"
        for week in range(1, 9):
            met = all_results[week]["principles"][pname]
            row += f" {'✓' if met else '✗':>2}"
        log(row)
    
    # Save report
    report_path = BASE / "AUDIT_WEEKS1to8.md"
    report_path.write_text("\n".join(REPORT_LINES))
    log(f"\n\n✓ Report saved to {report_path}")


if __name__ == "__main__":
    main()
