import os, re, json, csv, subprocess, textwrap
from pathlib import Path
from collections import defaultdict, Counter
from PIL import Image, ImageOps, ImageFilter
import pytesseract
from docx import Document
from docx.shared import Pt, Cm, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT, WD_CELL_VERTICAL_ALIGNMENT

ROOT = Path('/home/agent/family/Lernen/Mathe 4. Klasse')
OUT = Path('/home/agent/family/Lernen/Valerie_Mathe_4_Klasse_Lernpaket')
OUT.mkdir(parents=True, exist_ok=True)
OCR_DIR = OUT / '_ocr'
OCR_DIR.mkdir(exist_ok=True)

IMAGE_EXT = {'.jpg','.jpeg','.png','.webp'}
DOC_EXT = {'.docx'}

def rel(p): return str(Path(p).relative_to(ROOT))

def classify(path: Path):
    s = rel(path).lower()
    if 'addition' in s or 'subtraktion' in s: return 'Addition & Subtraktion'
    if 'division' in s or 'multiplikation' in s: return 'Multiplikation & Division'
    if 'gewicht' in s or 'hohl' in s or 'masse' in s: return 'Grössen: Gewichte & Hohlmasse'
    if 'geometrie' in s or '4.14' in s: return 'Geometrie'
    if 'themenbuch' in s: return 'Themenbuch / Jahresstoff'
    return 'Gemischte 4.-Klasse-Aufgaben'

def material_type(path: Path):
    s = rel(path).lower()
    if 'prüfung' in s or 'test' in s or 'matheprüfung' in s: return 'Prüfung/Test'
    if 'themenbuch' in s: return 'Themenbuch-Foto'
    if path.suffix.lower() == '.docx': return 'Word-Dokument'
    if path.suffix.lower() in IMAGE_EXT: return 'Foto/Scan'
    return 'Sonstiges'

def priority(topic, mtype):
    if mtype == 'Prüfung/Test': return 'hoch'
    if topic in ['Multiplikation & Division','Grössen: Gewichte & Hohlmasse','Geometrie']: return 'hoch'
    if topic == 'Addition & Subtraktion': return 'mittel-hoch'
    if topic == 'Themenbuch / Jahresstoff': return 'mittel'
    return 'mittel'

def extract_docx(path: Path):
    try:
        doc=Document(str(path))
        parts=[]
        for p in doc.paragraphs:
            t=p.text.strip()
            if t: parts.append(t)
        for table in doc.tables:
            for row in table.rows:
                vals=[c.text.strip() for c in row.cells if c.text.strip()]
                if vals: parts.append(' | '.join(vals))
        return '\n'.join(parts)
    except Exception as e:
        return f'[DOCX_EXTRACT_ERROR] {e}'

def ocr_image(path: Path):
    cache = OCR_DIR / (re.sub(r'[^A-Za-z0-9_.-]+','_', rel(path)) + '.txt')
    if cache.exists(): return cache.read_text(errors='ignore')
    try:
        img = Image.open(path).convert('RGB')
        # Downscale huge photos for speed, but keep readability
        max_side=2200
        w,h=img.size
        if max(w,h)>max_side:
            scale=max_side/max(w,h)
            img=img.resize((int(w*scale), int(h*scale)))
        gray=ImageOps.grayscale(img)
        gray=ImageOps.autocontrast(gray)
        gray=gray.filter(ImageFilter.SHARPEN)
        text=pytesseract.image_to_string(gray, lang='deu+eng', config='--psm 6')
    except Exception as e:
        text=f'[OCR_ERROR] {e}'
    cache.write_text(text, encoding='utf-8')
    return text

# Inventory + extraction
files=[]
for p in sorted(ROOT.rglob('*')):
    if p.is_file():
        topic=classify(p); mtype=material_type(p)
        files.append({
            'path': rel(p), 'name': p.name, 'folder': str(p.parent.relative_to(ROOT)),
            'ext': p.suffix.lower(), 'size': p.stat().st_size, 'topic': topic,
            'type': mtype, 'priority': priority(topic,mtype)
        })

texts={}
for i,f in enumerate(files,1):
    p=ROOT/f['path']
    if p.suffix.lower() in DOC_EXT:
        texts[f['path']]=extract_docx(p)
    elif p.suffix.lower() in IMAGE_EXT:
        texts[f['path']]=ocr_image(p)
    else:
        texts[f['path']]=''

# Add text stats/snippets
for f in files:
    txt=texts.get(f['path'],'')
    clean=' '.join(txt.split())
    f['ocr_chars']=len(clean)
    f['snippet']=clean[:220]

# Inventory CSV/JSON
with (OUT/'00_Inventar_Mathe_4_Klasse.csv').open('w',newline='',encoding='utf-8') as fh:
    w=csv.DictWriter(fh, fieldnames=['path','name','folder','ext','size','topic','type','priority','ocr_chars','snippet'])
    w.writeheader(); w.writerows(files)
(OUT/'00_Inventar_Mathe_4_Klasse.json').write_text(json.dumps(files,ensure_ascii=False,indent=2),encoding='utf-8')
(OUT/'00_OCR_Extrakte.json').write_text(json.dumps(texts,ensure_ascii=False,indent=2),encoding='utf-8')

# Summaries
by_topic=defaultdict(lambda: {'files':0,'bytes':0,'types':Counter(),'prio':Counter()})
for f in files:
    b=by_topic[f['topic']]; b['files']+=1; b['bytes']+=f['size']; b['types'][f['type']]+=1; b['prio'][f['priority']]+=1

# Generate markdown docs

def md_table(rows, headers):
    out=['| '+' | '.join(headers)+' |','| '+' | '.join(['---']*len(headers))+' |']
    for r in rows: out.append('| '+' | '.join(str(r.get(h,'')) for h in headers)+' |')
    return '\n'.join(out)

summary_rows=[]
for topic,d in sorted(by_topic.items()):
    summary_rows.append({'Thema':topic,'Dateien':d['files'],'Material':', '.join(f'{k}: {v}' for k,v in d['types'].items()),'Priorität':d['prio'].most_common(1)[0][0]})

lernlandkarte = f"""# Valerie – Mathe 4. Klasse: Lernlandkarte aus Emilias Unterlagen

**Quelle:** `/home/agent/family/Lernen/Mathe 4. Klasse`  
**Ziel:** Emilias Vorjahresunterlagen als strukturiertes, prüfungsnahes Lernsystem für Valerie nutzen.

## 1. Materialübersicht

{md_table(summary_rows, ['Thema','Dateien','Material','Priorität'])}

## 2. Didaktische Prioritäten

### A. Sofort relevant / hoher Hebel
1. **Multiplikation & Division** – Kernkompetenz 4. Klasse, viele Folgefehler entstehen hier.
2. **Grössen: Gewichte & Hohlmasse** – typische Prüfungsfallen: Einheiten, Umrechnungen, Textaufgaben.
3. **Geometrie** – Begriffe, Figuren, saubere Darstellung; oft gut trainierbar.
4. **Prüfungsroutine** – Aufgaben genau lesen, Einheiten notieren, Zwischenresultate sauber schreiben.

### B. Fundament sichern
- Addition/Subtraktion schriftlich und im Kopf.
- Zahlenraum und Stellenwertverständnis.
- Textaufgaben: Frage markieren, wichtige Zahlen einkreisen, Rechnung planen.

### C. Später vertiefen
- Themenbuch-Fotos als Nachschlagewerk und Pool für Zusatzaufgaben.
- Challenge-Aufgaben erst nach sicherem Basisniveau.

## 3. Empfohlenes Vorgehen

1. **Standortbestimmung** mit Diagnoseblatt durchführen – ohne Hilfe, 35–45 Minuten.
2. **Fehler nicht nur korrigieren, sondern kategorisieren:** Rechenfehler, Verständnisfehler, Einheitenfehler, Lesefehler.
3. **3 Lernblöcke pro Woche à 20 Minuten:** kurz, regelmässig, mit sofortigem Feedback.
4. **Alle 3–4 Wochen Mini-Prüfung** aus Emilias Prüfungslogik erstellen.
5. **Fehlerkartei führen:** Jede wiederkehrende Fehlerart bekommt eine Karte mit Merksatz + 3 Mini-Aufgaben.

## 4. Nutzung der vorhandenen Ordner

- `Addition und Subtraktion`: Fundament, Einstieg und Sicherheit.
- `Division`: hoher Fokus; hier früh Sicherheit aufbauen.
- `Gewichte und Hohlmasse`: Einheiten-Training + Prüfungsvorbereitung.
- `Geometrie`: Begriffe und Zeichengenauigkeit.
- `Prüfung Division`: Prüfungssimulation und Erwartungshorizont.
- `Gesamtes Mathematik Themenbuch 4. Klasse`: Themenpool / Nachschlagewerk.

## 5. Nächste sinnvolle Pakete

1. **Division sicher lernen** inkl. Rechenwege und Kontrolle.
2. **Gewichte & Hohlmasse** inkl. Umrechnungstabelle und Textaufgaben.
3. **Prüfungstraining 1** aus Emilias fotografierten Prüfungen.
4. **Geometrie-Basis** mit Begriffskarten.
"""
(OUT/'01_Lernlandkarte_Valerie_Mathe_4_Klasse.md').write_text(lernlandkarte,encoding='utf-8')

lernplan = """# Valerie – 10-Wochen-Lernplan Mathe 4. Klasse

## Grundprinzip
- 3 Einheiten pro Woche à 20 Minuten.
- Jede Einheit: 3 Min. Kopfrechnen, 12 Min. Hauptthema, 5 Min. Kontrolle/Fehlerkarte.
- Lieber regelmässig kurz als selten lang.

| Woche | Schwerpunkt | Ziel | Mini-Kontrolle |
|---|---|---|---|
| 1 | Standortbestimmung | Stärken/Lücken erkennen | Diagnoseblatt |
| 2 | Addition/Subtraktion | sicher schriftlich rechnen | 10 gemischte Rechnungen |
| 3 | Multiplikation | Reihen, halbschriftlich, Tabellen | 1-Minuten-Reihencheck |
| 4 | Division Grundlagen | teilen, Rest, Probe | 8 Divisionen mit Probe |
| 5 | Division Textaufgaben | Rechnung aus Text ableiten | 5 Textaufgaben |
| 6 | Gewichte | g/kg/t umrechnen | Umrechnungstest |
| 7 | Hohlmasse | ml/cl/dl/l umrechnen | Umrechnungstest |
| 8 | Geometrie | Figuren, Umfang, sauber zeichnen | Begriffe + Zeichnung |
| 9 | Gemischte Prüfung 1 | Ausdauer + Genauigkeit | Probeprüfung 35 Min. |
| 10 | Fehler gezielt schliessen | persönliche Schwächen | Wiederholungsprüfung |

## Eltern-Checkliste pro Woche
- Kann Valerie erklären, *warum* sie so rechnet?
- Schreibt sie Einheiten konsequent dazu?
- Kontrolliert sie Divisionen mit Multiplikation?
- Sind Fehler einmalig oder wiederkehrend?
- Wirkt sie überfordert? Dann Stoff halbieren, nicht Druck erhöhen.
"""
(OUT/'02_10_Wochen_Lernplan.md').write_text(lernplan,encoding='utf-8')

pruefung = """# Prüfungstraining – Vorgehen mit Emilias Unterlagen

## Prüfungsroutine für Valerie
1. Name, Datum, Zeit prüfen.
2. Jede Aufgabe zuerst lesen, dann wichtige Wörter/Zahlen markieren.
3. Bei Grössen: Einheit immer mitschreiben.
4. Bei Division: Probe mit Multiplikation.
5. Am Schluss 5 Minuten Kontrollrunde.

## Fehlerkategorien
| Kategorie | Beispiel | Sofortmassnahme |
|---|---|---|
| Rechenfehler | 7×8 falsch | Reihen-Kartei, 2 Minuten täglich |
| Stellenwertfehler | Einer/Zehner verwechselt | Zahlen stellenweise sprechen lassen |
| Einheitenfehler | 1 kg = 100 g | Umrechnungstreppe üben |
| Lesefehler | Frage übersehen | Frage unterstreichen |
| Darstellungsfehler | Rechnung unleserlich | Kästchen nutzen, Zwischenschritte |

## Mini-Prüfungssystem
- **Basisprüfung:** 20–25 Min., einfache Zahlen, Fokus Sicherheit.
- **Normalprüfung:** 35–45 Min., gemischt wie Schule.
- **Challenge:** Zusatzaufgaben nur wenn Normalprüfung >80% sitzt.

## Bewertungsvorschlag
- 90–100%: sehr sicher
- 75–89%: gut, einzelne Fehlerkarten
- 60–74%: Thema nochmals gezielt üben
- <60%: Grundlagen statt neuer Stoff
"""
(OUT/'04_Pruefungstraining_und_Fehlerkartei.md').write_text(pruefung,encoding='utf-8')

eltern = """# Elternleitfaden – Valerie in Mathe 4. Klasse begleiten

## Was hilft am meisten
- Kurz und regelmässig üben.
- Fehler freundlich als Information behandeln.
- Valerie den Rechenweg erklären lassen.
- Nicht sofort vorsagen; lieber fragen: „Was ist gefragt?“ / „Welche Einheit brauchst du?“

## Gute Fragen beim Helfen
- Was weisst du schon?
- Was wird gesucht?
- Welche Rechnung passt dazu?
- Kannst du dein Ergebnis überschlagen?
- Welche Einheit gehört zur Antwort?

## Warnsignale
- Valerie rechnet nur auswendig ohne Verständnis.
- Sie überspringt Einheiten.
- Sie vermeidet Textaufgaben.
- Sie braucht sehr lange wegen Unsicherheit bei Reihen/Division.

## Dann gezielt reagieren
- Bei Reihenproblemen: 2 Minuten täglich, spielerisch.
- Bei Textaufgaben: erst markieren, dann rechnen.
- Bei Einheiten: Umrechnungstabelle sichtbar aufhängen.
- Bei Prüfungsstress: kurze Probeprüfungen mit Timer üben.
"""
(OUT/'05_Elternleitfaden.md').write_text(eltern,encoding='utf-8')

# Diagnoseblatt docx

def style_doc(doc):
    styles=doc.styles
    styles['Normal'].font.name='Arial'
    styles['Normal'].font.size=Pt(11)

def add_title(doc, title, subtitle=None):
    p=doc.add_paragraph()
    p.alignment=WD_ALIGN_PARAGRAPH.CENTER
    r=p.add_run(title); r.bold=True; r.font.size=Pt(18); r.font.color.rgb=RGBColor(31,78,121)
    if subtitle:
        p=doc.add_paragraph(); p.alignment=WD_ALIGN_PARAGRAPH.CENTER
        r=p.add_run(subtitle); r.font.size=Pt(11); r.italic=True

def add_task(doc, num, text, lines=1):
    p=doc.add_paragraph()
    r=p.add_run(f'{num}. '); r.bold=True
    p.add_run(text)
    for _ in range(lines):
        doc.add_paragraph('   ' + '_'*78)

def make_diag(path, solutions=False):
    doc=Document(); style_doc(doc)
    sec=doc.sections[0]; sec.top_margin=Cm(1.5); sec.bottom_margin=Cm(1.5); sec.left_margin=Cm(1.6); sec.right_margin=Cm(1.6)
    add_title(doc, 'Valerie – Standortbestimmung Mathe 4. Klasse', 'Bearbeitungszeit: ca. 40 Minuten. Ohne Hilfe. Rechenwege sichtbar notieren.')
    doc.add_paragraph('Name: __________________________   Datum: ________________   Zeit: _______')
    doc.add_paragraph('Hinweis: Bei Textaufgaben die Frage unterstreichen und die Einheit in der Antwort notieren.')
    tasks = [
        ('Kopfrechnen: 8×7 = ___, 6×9 = ___, 42:6 = ___, 56:8 = ___', '56, 54, 7, 7', 1),
        ('Schriftlich addieren: 3 458 + 2 769 =', '6 227', 2),
        ('Schriftlich subtrahieren: 7 004 − 2 586 =', '4 418', 2),
        ('Multipliziere halbschriftlich: 36 × 7 =', '252', 2),
        ('Dividiere mit Probe: 684 : 3 =', '228; Probe: 228×3=684', 3),
        ('Dividiere mit Rest: 95 : 6 =', '15 Rest 5', 2),
        ('Ergänze: 1 kg = ___ g, 3 l = ___ ml, 250 cm = ___ m ___ cm', '1000 g; 3000 ml; 2 m 50 cm', 2),
        ('Ordne der Grösse nach: 750 g, 1 kg, 250 g, 1 500 g', '250 g, 750 g, 1 kg, 1 500 g', 2),
        ('Textaufgabe: Valerie kauft 4 Hefte zu je 3 Fr. und einen Stift für 2 Fr. Wie viel bezahlt sie?', '4×3 + 2 = 14 Fr.', 3),
        ('Textaufgabe: 72 Bonbons werden gerecht auf 8 Kinder verteilt. Wie viele bekommt jedes Kind?', '9 Bonbons', 2),
        ('Geometrie: Zeichne ein Rechteck mit 6 cm Länge und 3 cm Breite. Berechne den Umfang.', 'Umfang = 2×6 + 2×3 = 18 cm', 4),
        ('Sachproblem mit Einheiten: Ein Krug enthält 1 l Saft. Valerie schenkt 3 Gläser à 200 ml ein. Wie viel bleibt übrig?', '1 l = 1000 ml; 1000 - 600 = 400 ml', 3),
        ('Zahlenverständnis: Zerlege 4 706 in Tausender, Hunderter, Zehner, Einer.', '4T, 7H, 0Z, 6E', 2),
        ('Prüfungsaufgabe gemischt: 248 + 3×36 − 84 : 4 =', '248 + 108 - 21 = 335', 3),
    ]
    if not solutions:
        for i,(t,s,l) in enumerate(tasks,1): add_task(doc,i,t,l)
        doc.add_page_break()
        doc.add_heading('Auswertung für Eltern', level=1)
        doc.add_paragraph('Pro Aufgabe 1 Punkt. Markiere Fehlerarten: R = Rechenfehler, V = Verständnis, E = Einheit, L = Lesefehler, D = Darstellung.')
        table=doc.add_table(rows=1, cols=5); table.alignment=WD_TABLE_ALIGNMENT.CENTER
        hdr=table.rows[0].cells
        for c,h in zip(hdr,['Thema','Aufgaben','Punkte','Fehlerart','Massnahme']): c.text=h
        rows=[('Kopfrechnen/Reihen','1','/1','',''),('Addition/Subtraktion','2–3','/2','',''),('Multiplikation/Division','4–6','/3','',''),('Grössen/Einheiten','7–8,12','/3','',''),('Textaufgaben','9–10,12','/3','',''),('Geometrie','11','/1','',''),('Zahlenverständnis','13–14','/2','','')]
        for row in rows:
            cells=table.add_row().cells
            for c,v in zip(cells,row): c.text=v
        doc.add_paragraph('Interpretation: 12–14 Punkte = sehr guter Start; 9–11 = solide mit gezielten Lücken; 6–8 = Grundlagen wiederholen; <6 = zuerst Basisaufbau ohne Zeitdruck.')
    else:
        for i,(t,s,l) in enumerate(tasks,1):
            add_task(doc,i,t,1)
            p=doc.add_paragraph(); p.add_run('Lösung: ').bold=True; p.add_run(s)
    doc.save(path)

make_diag(str(OUT/'03_Diagnoseblatt_Valerie_Mathe_4_Klasse.docx'), False)
make_diag(str(OUT/'03_Diagnoseblatt_Valerie_Mathe_4_Klasse_Loesungen.docx'), True)

# Create a short README
readme = f"""# Valerie Mathe 4. Klasse Lernpaket

Erstellt aus Emilias Unterlagen im Ordner `Mathe 4. Klasse`.

## Dateien
- `00_Inventar_Mathe_4_Klasse.csv/json`: vollständige Materialliste mit OCR-Snippets
- `00_OCR_Extrakte.json`: maschinenlesbare OCR-/DOCX-Extrakte
- `01_Lernlandkarte_Valerie_Mathe_4_Klasse.md`: Themen, Prioritäten, Vorgehen
- `02_10_Wochen_Lernplan.md`: Lernplan für die ersten 10 Wochen
- `03_Diagnoseblatt_Valerie_Mathe_4_Klasse.docx`: Standortbestimmung für Valerie
- `03_Diagnoseblatt_Valerie_Mathe_4_Klasse_Loesungen.docx`: Lösungen/Auswertung
- `04_Pruefungstraining_und_Fehlerkartei.md`: Prüfungsvorgehen und Fehlerkartei
- `05_Elternleitfaden.md`: kurze Anleitung für Eltern

## Zählung
- Originaldateien analysiert: {len(files)}
- OCR/DOCX-Extrakte erstellt: {len(texts)}
"""
(OUT/'README.md').write_text(readme,encoding='utf-8')

# Convert DOCX to PDF if libreoffice available
try:
    subprocess.run(['libreoffice','--headless','--convert-to','pdf','--outdir',str(OUT),str(OUT/'03_Diagnoseblatt_Valerie_Mathe_4_Klasse.docx'),str(OUT/'03_Diagnoseblatt_Valerie_Mathe_4_Klasse_Loesungen.docx')], check=True, capture_output=True, text=True, timeout=120)
except Exception as e:
    (OUT/'PDF_CONVERSION_NOTE.txt').write_text(str(e), encoding='utf-8')

print(json.dumps({'out':str(OUT),'files_analyzed':len(files),'topics':summary_rows}, ensure_ascii=False, indent=2))
