#!/usr/bin/env python3
"""
Ingest 2nd Grade Math curriculum into the brain system.

Parses Curriculum_32_Weeks.md (table-based format), creates:
- 1 umbrella entity (math) β€” updates existing if present
- 5 phase entities
- 32 topic entities with key skills
- Edges: part_of, precedes

Usage:
    python3 ~/wiki/ingest_math_knowledge.py           # Full ingest
    python3 ~/wiki/ingest_math_knowledge.py --dry     # Preview only
    python3 ~/wiki/ingest_math_knowledge.py --query   # Run test queries
"""

import sys
import os
import re
from pathlib import Path
from datetime import date

sys.path.insert(0, str(Path.home() / '.hermes' / 'brain'))

import brain
brain._db_connection = None
brain.init_db()

TODAY = date.today().isoformat()
PLAN_PATH = Path.home() / 'Home_School' / '2nd_Grade' / 'Math' / 'Curriculum_32_Weeks.md'


def parse_plan():
    """Parse the Curriculum_32_Weeks.md (table-based format)."""
    if not PLAN_PATH.exists():
        print(f"[warn] Plan not found: {PLAN_PATH}")
        return {}

    content = PLAN_PATH.read_text()

    # Extract phase blocks β€” phases have descriptive names after the colon
    phase_blocks = re.findall(
        r'^## Phase (\d+): (.+?)\s*\n\n(.+?)(?=^## |\Z)',
        content, re.MULTILINE | re.DOTALL
    )

    topics = {}
    phase_teaching_notes = {}

    for phase_num_str, phase_name, body in phase_blocks:
        phase_num = int(phase_num_str)
        phase_name = phase_name.strip()

        # Extract teaching notes (if present)
        notes_match = re.search(r'\*\*Teaching Notes:\*\*\s*\n((?:(?!^\-).)*?)', body, re.MULTILINE | re.DOTALL)
        if notes_match:
            phase_teaching_notes[phase_num] = notes_match.group(1).strip()

        # Parse table rows β€” handle both formats:
        # | Week | Topic | Key Skills |
        # | Week | Topic | Key Skills | Visual Elements |
        table_rows = re.findall(r'^\|\s*(\d+)\s*\|\s*(.+?)\s*\|\s*(.+?)\s*(?:\|.*)?\s*\|?\s*$', body, re.MULTILINE)

        for week_str, topic, skills in table_rows:
            week = int(week_str)
            topic = topic.strip()
            skills = skills.strip()

            slug = re.sub(r'[^\w\s-]', '', topic.lower().strip())
            slug = re.sub(r'[\s_]+', '-', slug).strip('-')

            topics[week] = {
                "week": week,
                "topic": topic,
                "slug": slug,
                "phase": phase_num,
                "phase_name": phase_name,
                "key_skills": skills,
            }

    # Also extract the weekly lesson structure
    lesson_structure = ""
    ls_match = re.search(r'## Weekly Lesson Structure\s*\n\n(.+?)(?=^## |\Z)', content, re.MULTILINE | re.DOTALL)
    if ls_match:
        lesson_structure = ls_match.group(1).strip()

    # Extract standards alignment
    standards = ""
    std_match = re.search(r'## Standards Alignment.*?\n\n(.+?)(?=^## |\Z)', content, re.MULTILINE | re.DOTALL)
    if std_match:
        standards = std_match.group(1).strip()

    # Extract materials
    materials = ""
    mat_match = re.search(r'## Materials & Tools\s*\n\n(.+?)(?=^## |\Z)', content, re.MULTILINE | re.DOTALL)
    if mat_match:
        materials = mat_match.group(1).strip()

    # Extract pacing guidance
    pacing = ""
    pace_match = re.search(r'## Pacing Guidance\s*\n\n(.+?)(?=^## |\Z)', content, re.MULTILINE | re.DOTALL)
    if pace_match:
        pacing = pace_match.group(1).strip()

    return topics, {
        "phase_teaching_notes": phase_teaching_notes,
        "lesson_structure": lesson_structure,
        "standards": standards,
        "materials": materials,
        "pacing": pacing,
    }


def create_entity(content, category, entity_type="memory", pinned=False, strength="moderate", metadata=None):
    return brain.create_entity(
        content=content,
        entity_type=entity_type,
        category=category,
        strength=strength,
        pinned=pinned,
        metadata=metadata or {},
        log=True,
    )


def ingest_umbrella(extras):
    """Create/update math umbrella entity."""
    content = f"""## Math Curriculum β€” 2nd Grade

Complete 32-week, 5-phase math curriculum for second grade. Each week covers
a focused topic with daily lessons building toward mastery. Designed for
homeschool use with hands-on practice, word problems, and visual activities.

**Structure:** 5 phases, 32 weeks, Mon–Fri lessons per week.
**Format:** 10 problems per lesson, horizontal math format.

### Phases
- **Phase 1:** Number Sense & Foundations (Weeks 1–6)
- **Phase 2:** Addition & Subtraction to 100 (Weeks 7–14)
- **Phase 3:** Measurement, Time & Money (Weeks 15–20)
- **Phase 4:** Geometry & Fractions (Weeks 21–26)
- **Phase 5:** Multiplication, Division & Patterns (Weeks 27–32)

### Standards Alignment (Common Core 2nd Grade)
{extras['standards']}

### Weekly Lesson Structure
{extras['lesson_structure']}

### Materials & Tools
{extras['materials']}

### Pacing Guidance
{extras['pacing']}

**Ingested:** {TODAY}
**Source:** Home_School/2nd_Grade/Math/Curriculum_32_Weeks.md
"""
    eid = create_entity(
        content=content,
        category="curriculum/math",
        entity_type="curriculum_umbrella",
        pinned=True,
        strength="strong",
        metadata={"source": "math_curriculum_ingest", "date": TODAY},
    )
    print(f"  βœ… Umbrella: curriculum/math β†’ {eid}")
    return eid


def ingest_phases(topics, umbrella_id, extras):
    phase_weeks = {}
    for week, data in sorted(topics.items()):
        pn = data["phase"]
        if pn not in phase_weeks:
            phase_weeks[pn] = {"name": data["phase_name"], "weeks": []}
        phase_weeks[pn]["weeks"].append(week)

    phase_ids = {}

    for pn, pdata in sorted(phase_weeks.items()):
        week_range = f"Weeks {min(pdata['weeks'])}–{max(pdata['weeks'])}"
        topics_list = ""
        for w in sorted(pdata['weeks']):
            topics_list += f"- Week {w}: {topics[w]['topic']} β€” {topics[w]['key_skills']}\n"

        teaching_notes = extras['phase_teaching_notes'].get(pn, "")
        notes_section = f"\n### Teaching Notes\n{teaching_notes}\n" if teaching_notes else ""

        content = f"""## Math Phase {pn}: {pdata['name']}

{week_range} β€” {len(pdata['weeks'])} weeks of 2nd grade math curriculum.

### Topics
{topics_list}{notes_section}
"""
        category = f"curriculum/math/phase-{pn}"
        eid = create_entity(
            content=content,
            category=category,
            entity_type="curriculum_phase",
            pinned=pn <= 2,
            strength="strong" if pn <= 2 else "moderate",
            metadata={"phase": pn, "weeks": sorted(pdata['weeks']), "source": "math_curriculum_ingest"},
        )
        phase_ids[pn] = eid
        print(f"  βœ… Phase {pn}: {pdata['name']} β†’ {eid[:12]}...")
        brain.add_edge(eid, "part_of", umbrella_id)

    return phase_ids


def ingest_topics(topics, phase_ids):
    topic_ids = {}

    for week, data in sorted(topics.items()):
        # Pin checkpoint weeks and foundational topics
        pinned = week <= 6 or week in [14, 20, 26, 32]

        content = f"""## Math: Week {week} β€” {data['topic']}

**Phase:** {data['phase_name']}
**Key Skills:** {data['key_skills']}
"""
        category = f"curriculum/math/topic/week-{week}"
        eid = create_entity(
            content=content,
            category=category,
            entity_type="curriculum_topic",
            pinned=pinned,
            strength="moderate",
            metadata={
                "week": week,
                "phase": data["phase"],
                "topic": data["topic"],
                "key_skills": data["key_skills"],
                "source": "math_curriculum_ingest",
            },
        )
        topic_ids[week] = eid
        print(f"  βœ… Wk {week}: {data['topic']} β†’ {eid[:12]}...")

    return topic_ids


def create_edges(topics, phase_ids, topic_ids):
    edge_count = 0

    for week, data in topics.items():
        phase = data["phase"]
        if phase in phase_ids and week in topic_ids:
            if brain.add_edge(topic_ids[week], "part_of", phase_ids[phase]):
                edge_count += 1

    for week in range(1, 32):
        if week in topic_ids and (week + 1) in topic_ids:
            if brain.add_edge(topic_ids[week], "precedes", topic_ids[week + 1]):
                edge_count += 1

    for p in range(1, 5):
        if p in phase_ids and (p + 1) in phase_ids:
            if brain.add_edge(phase_ids[p], "precedes", phase_ids[p + 1]):
                edge_count += 1

    print(f"  βœ… {edge_count} edges created")
    return edge_count


def run_test_queries():
    queries = [
        ("math curriculum phases", "phases"),
        ("place value tens ones", "place value"),
        ("addition subtraction regrouping", "regrouping"),
        ("measurement time money", "measurement"),
        ("geometry shapes fractions", "geometry"),
        ("multiplication division equal groups", "multiplication"),
        ("telling time clock", "time"),
        ("area perimeter square units", "area"),
        ("fraction equal parts", "fractions"),
        ("addition facts to 20 fluency", "fluency"),
    ]

    print("\n=== TEST QUERIES ===")
    passed = 0
    for q, _ in queries:
        result = brain.search(q, limit=3)
        hits = len(result) if result else 0
        status = "βœ“" if hits > 0 else "βœ—"
        print(f"  {status} '{q}' β†’ {hits} hits")
        if hits > 0:
            passed += 1

    print(f"\n  Results: {passed}/{len(queries)} queries returned hits")
    return passed >= len(queries) * 0.8


def main():
    mode = sys.argv[1] if len(sys.argv) > 1 else "--ingest"

    if mode == "--query":
        run_test_queries()
        return

    print("=== Math Curriculum Brain Ingestion ===")

    print("\n[1] Parsing Curriculum_32_Weeks.md...")
    topics, extras = parse_plan()
    print(f"    Found {len(topics)} topics across 5 phases")
    if extras['phase_teaching_notes']:
        print(f"    Teaching notes for {len(extras['phase_teaching_notes'])} phases")
    if extras['standards']:
        print(f"    Standards alignment: {len(extras['standards'])} chars")

    if not topics:
        print("[error] No topics found")
        return

    if mode == "--dry":
        print("\n--- DRY RUN ---")
        phases_seen = set()
        for week, data in sorted(topics.items()):
            if data['phase'] not in phases_seen:
                print(f"\n  Phase {data['phase']}: {data['phase_name']}")
                phases_seen.add(data['phase'])
            print(f"    Wk {week}: {data['topic']}")
        print(f"\n  Total: {len(topics)} topics")
        return

    print("\n[2] Creating umbrella entity...")
    umbrella_id = ingest_umbrella(extras)

    print("\n[3] Ingesting phase entities...")
    phase_ids = ingest_phases(topics, umbrella_id, extras)

    print("\n[4] Ingesting topic entities...")
    topic_ids = ingest_topics(topics, phase_ids)

    print("\n[5] Creating relationship edges...")
    edge_count = create_edges(topics, phase_ids, topic_ids)

    total = 1 + 5 + len(topics)
    print(f"\n=== DONE ===")
    print(f"  Entities: {total} (1 umbrella + 5 phases + {len(topics)} topics)")
    print(f"  Edges: {edge_count}")

    print("\n[6] Running test queries...")
    run_test_queries()


if __name__ == "__main__":
    main()