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

Parses the 32_week_course_plan.md, creates:
- 1 umbrella entity (science)
- 4 phase entities (linked to umbrella)
- 32 topic entities with rich content (linked to phases)
- Edges: part_of, precedes

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

import sys
import os
import re
import json
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' / 'Science' / '32_week_course_plan.md'


# ---------------------------------------------------------------------------
# Parsing — identical structure to history ingest
# ---------------------------------------------------------------------------

def parse_plan():
    """Parse the 32_week_course_plan.md → dict of week -> topic data."""
    if not PLAN_PATH.exists():
        print(f"[warn] Plan not found: {PLAN_PATH}")
        return {}

    content = PLAN_PATH.read_text()
    topics = {}

    phase_blocks = re.findall(
        r'^## (FALL|WINTER|SPRING|YEAR-END): (.+?)\s*\n\n(.+?)(?=^## |\Z)',
        content, re.MULTILINE | re.DOTALL
    )

    season_to_phase = {"FALL": 1, "WINTER": 2, "SPRING": 3, "YEAR-END": 4}

    for season, phase_name, body in phase_blocks:
        phase_num = season_to_phase.get(season.strip(), 0)
        phase_name = phase_name.strip()

        week_parts = re.split(r'^(?=### Week \d+:)', body, flags=re.MULTILINE)

        for part in week_parts:
            m = re.match(r'^### Week (\d+): (.+?)\s*\n', part, re.MULTILINE)
            if not m:
                continue

            week = int(m.group(1))
            topic_name = m.group(2).strip()
            details = part[m.end():]

            focus_match = re.search(r'\*\*Focus:\*\*\s*(.+)', details)
            focus = focus_match.group(1).strip() if focus_match else ""

            obj_match = re.search(r'- \*\*Objectives:\*\* (.+)', details)
            objectives = obj_match.group(1).strip() if obj_match else ""

            act_match = re.search(r'- \*\*Activities:\*\*\s*\n((?:(?!- \*\*Assessment:).)*?)', details, re.DOTALL)
            activities = act_match.group(1).strip() if act_match else ""

            assess_match = re.search(r'- \*\*Assessment:\*\* (.+)', details)
            assessment = assess_match.group(1).strip() if assess_match else ""

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

            topics[week] = {
                "week": week,
                "topic": topic_name,
                "slug": slug,
                "phase": phase_num,
                "phase_name": f"{season.strip()}: {phase_name}",
                "focus": focus,
                "objectives": objectives,
                "activities": activities,
                "assessment": assessment,
            }

    return topics


# ---------------------------------------------------------------------------
# Entity creation — same pattern as history ingest
# ---------------------------------------------------------------------------

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,
    )


# ---------------------------------------------------------------------------
# Ingestion
# ---------------------------------------------------------------------------

def ingest_umbrella():
    content = f"""## Science Curriculum — 2nd Grade

Comprehensive 32-week science curriculum following NGSS standards.
Hands-on investigations, observation skills, and simple experiments.
Each week: learning objectives, activities, and assessment ideas.

### Structure
- **Phase 1 (FALL):** Physical Science — Matter and Its Interactions (Weeks 1–10)
- **Phase 2 (WINTER):** Life Science — Plants and Ecosystems (Weeks 11–20)
- **Phase 3 (SPRING):** Earth Science and Diversity of Life (Weeks 21–30)
- **Phase 4 (YEAR-END):** Engineering and Review (Weeks 31–32)

### NGSS Standards
- 2-PS1 (Matter and Its Properties)
- 2-LS1 (Organisms and Their Environments)
- 2-LS2 (Ecosystems: Interactions, Energy, and Dynamics)
- 2-ESS1 (Earth's Place in the Universe)
- 2-ESS2 (Earth's Systems)
- 2-ESS3 (Earth and Human Activity)
- 2-ETS1 (Engineering Design)

### Pedagogical Approach
- Science journaling and observation recording
- Fair testing with controlled variables
- Hands-on experiments and model building
- Data collection and graphing
- Integration with math (measuring, graphing) and literacy

**Ingested:** {TODAY}
**Source:** Home_School/2nd_Grade/Science/32_week_course_plan.md
"""
    eid = create_entity(
        content=content,
        category="curriculum/science",
        entity_type="curriculum_umbrella",
        pinned=True,
        strength="strong",
        metadata={"source": "science_curriculum_ingest", "date": TODAY},
    )
    print(f"  ✅ Umbrella: curriculum/science → {eid}")
    return eid


def ingest_phases(topics, umbrella_id):
    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']}\n"

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

{week_range} — {len(pdata['weeks'])} weeks of 2nd grade science curriculum.

### Topics
{topics_list}
"""
        category = f"curriculum/science/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": "science_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()):
        content = f"""## Science: Week {week} — {data['topic']}

**Phase:** {data['phase_name']}
**Focus:** {data['focus']}

### Objectives
{data['objectives']}

### Activities
{data['activities']}

### Assessment
{data['assessment']}
"""
        pinned = week <= 10 or week in [16, 20, 24, 26, 31, 32]

        category = f"curriculum/science/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"],
                "focus": data["focus"],
                "source": "science_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, 4):
        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


# ---------------------------------------------------------------------------
# Test queries
# ---------------------------------------------------------------------------

def run_test_queries():
    queries = [
        ("science curriculum phases", "phases"),
        ("states of matter solids liquids gases", "matter"),
        ("what do plants need to grow", "plants"),
        ("habitat types second grade science", "habitat"),
        ("water cycle evaporation", "water cycle"),
        ("weathering and erosion", "erosion"),
        ("animal adaptations", "adaptation"),
        ("engineering design challenge", "engineering"),
        ("properties of materials science", "properties"),
        ("food chain ecosystem", "ecosystem"),
    ]

    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


# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------

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

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

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

    print("\n[1] Parsing 32_week_course_plan.md...")
    topics = parse_plan()
    print(f"    Found {len(topics)} topics across 4 phases")

    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()

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

    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 + 4 + len(topics)
    print(f"\n=== DONE ===")
    print(f"  Entities: {total} (1 umbrella + 4 phases + {len(topics)} topics)")
    print(f"  Edges: {edge_count}")

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


if __name__ == "__main__":
    main()