#!/usr/bin/env python3
"""
Shared helpers for 2nd Grade Math curriculum generators.

Usage in generate_weekN.py:
    from math_helpers import *

    def monday():
        s1 = '<p class="note">...</p>' + b('2em')
        s2 = sec(1, "Title", s1)
        return page(1, "Monday", "Topic", s1 + s2 + s3 + ...)

    days = [
        ("Monday", "Topic", monday),
        ("Tuesday", "Topic", tuesday),
        ...
    ]

    generate(WEEK, days)
"""

import os
import glob
import math
from weasyprint import HTML

# ═══════════════════════════════════════════════════
# Color Palette
# ═══════════════════════════════════════════════════

PRIMARY   = "#3f51b5"
PRIMARY_BG = "#e8eaf6"
PRIMARY_BORDER = "#c5cae9"

RED      = "#ef5350"
BLUE     = "#42a5f5"
GREEN    = "#66bb6a"
YELLOW   = "#ffca28"
ORANGE   = "#ffa726"
PURPLE   = "#ab47bc"
PINK     = "#e91e63"
TEAL     = "#26c6da"
GOLD     = "#ffc107"

# ═══════════════════════════════════════════════════
# Base CSS — union of all week-specific styles
# ═══════════════════════════════════════════════════

CSS = r"""
@page { size: 8.5in 11in; margin: 0.5in; }
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Helvetica Neue', Arial, sans-serif; color: #222; font-size: 14px; line-height: 1.7; }
page { width: 7.5in; }
page + page { page-break-before: always; }

/* ── Header ── */
.head { display: flex; align-items: baseline; gap: 10px; padding-bottom: 4px; border-bottom: 3px solid #3f51b5; margin-bottom: 6px; }
.head .week { font-size: 18px; font-weight: 700; color: #3f51b5; letter-spacing: -0.5px; }
.head .day { font-size: 14px; font-weight: 600; color: #3f51b5; background: #e8eaf6; padding: 2px 10px; border-radius: 3px; }
.head .topic { font-size: 12px; color: #888; margin-left: auto; font-style: italic; }

/* ── Section ── */
.sec { margin-bottom: 8px; }
.sec.pb { break-after: avoid; page-break-after: avoid; }
.sec-head { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; }
.sec-n { font-size: 9px; font-weight: 700; color: #fff; background: #3f51b5; width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; border-radius: 3px; flex-shrink: 0; }
.sec-t { font-size: 13px; font-weight: 600; color: #333; }
.note { font-size: 10.5px; color: #999; font-style: italic; margin-bottom: 4px; }

/* ── Math grid ── */
.mgrid { display: grid; gap: 8px 0; }
.mgrid.c2 { grid-template-columns: 1fr 1fr; }
.mgrid.c3 { grid-template-columns: 1fr 1fr 1fr; }
.mgrid.c4 { grid-template-columns: 1fr 1fr 1fr 1fr; }

/* ── Blanks ── */
.b { display: inline-block; border-bottom: 1.5px solid #333; min-width: 8em; text-align: center; }
.bw { display: inline-block; border-bottom: 1.5px solid #333; min-width: 18em; text-align: center; }
.bl { display: inline-block; border-bottom: 1.5px solid #333; min-width: 22em; text-align: center; }

/* ── Boxes ── */
.abox { border: 1.5px solid #e0e0e0; border-radius: 4px; padding: 8px 10px; margin-bottom: 5px; }
.dbox { border: 1.5px dashed #ccc; border-radius: 4px; min-height: 80px; background: #fafafa; margin-bottom: 8px; }
.draw-box { border: 1.5px dashed #bbb; border-radius: 6px; min-height: 80px; background: #fafafa; margin: 8px 0; }
.starbox { border: 2px solid #ffc107; border-radius: 6px; padding: 10px 12px; margin-bottom: 8px; background: #fffde7; }
.selfcheck { border: 1.5px solid #4caf50; border-radius: 4px; padding: 6px 10px; margin-bottom: 5px; background: #f1f8e9; }

/* ── Table ── */
.tbl { width: 100%; border-collapse: collapse; margin-bottom: 8px; font-size: 12px; }
.tbl th { background: #f5f5f5; color: #333; padding: 5px 8px; text-align: center; border-bottom: 2px solid #3f51b5; font-weight: 600; font-size: 11.5px; }
.tbl td { padding: 5px 8px; border-bottom: 1px solid #eee; text-align: center; }

/* ── Word problem ── */
.wp { border-left: 3px solid #3f51b5; padding-left: 8px; margin-bottom: 8px; }

/* ── Number chart ── */
.chart { display: grid; grid-template-columns: repeat(10, 1fr); font-family: 'Courier New', monospace; font-size: 11px; text-align: center; line-height: 1; }
.chart .c { border: 1px solid #ddd; padding: 3px 1px; }
.chart .c.hl { background: #f5f5f5; }
.chart .c.miss { border: 1.5px dashed #3f51b5; min-height: 16px; background: #fafafa; }
.chart .c.hdr { background: #3f51b5; color: #fff; font-weight: 600; border-color: #3f51b5; }

/* ── Ordering boxes ── */
.orow { display: flex; gap: 3px; align-items: center; margin-bottom: 3px; font-family: 'Courier New', monospace; font-size: 14px; }
.obox { border: 1.5px solid #333; min-width: 2.2em; min-height: 1.4em; text-align: center; display: inline-block; }

/* ── Number bonds ── */
.bond { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; font-family: 'Courier New', monospace; font-size: 14px; }
.bcirc { border: 2px solid #3f51b5; border-radius: 50%; width: 38px; height: 38px; display: flex; align-items: center; justify-content: center; }

/* ── Skip counting ── */
.skrow { font-family: 'Courier New', monospace; font-size: 16px; display: flex; gap: 3px; align-items: center; flex-wrap: wrap; margin-bottom: 4px; }
.skn { display: inline-block; min-width: 2.5em; text-align: center; }
.skip-num { display: inline-block; width: 34px; height: 34px; line-height: 34px; text-align: center; border: 1.5px solid #3f51b5; border-radius: 50%; font-size: 14px; font-weight: 600; margin: 2px; }
.skip-blank { display: inline-block; width: 34px; height: 34px; line-height: 34px; text-align: center; border: 1.5px dashed #333; border-radius: 50%; font-size: 14px; margin: 2px; background: #fafafa; }

/* ── Star self-check ── */
.star-row { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; font-size: 13px; }
.stars { letter-spacing: 2px; color: #ccc; font-size: 16px; }

/* ── Ruler ── */
.ruler-container { position: relative; margin: 6px 0; }
.ruler { border: 1px solid #333; border-top: none; height: 28px; position: relative; background: #fffef0; }
.ruler-label { font-size: 9px; color: #666; text-align: center; margin-top: 2px; }
.ruler-marks { position: relative; height: 28px; }
.ruler-mark { position: absolute; bottom: 0; width: 1px; background: #333; }
.ruler-mark.major { height: 16px; }
.ruler-mark.mid { height: 12px; }
.ruler-mark.minor { height: 8px; }
.ruler-num { position: absolute; font-size: 9px; color: #333; transform: translateX(-50%); }
.measure-line { border-bottom: 2px solid #333; margin: 8px 0; position: relative; }
.obj-label { font-size: 11px; font-weight: 600; color: #333; display: inline-block; margin-bottom: 2px; }
.comparison { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; }
.comparison .val { font-family: 'Courier New', monospace; font-size: 13px; font-weight: 600; }

/* ── Multiplication ── */
.group-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin: 4px 0; }
.group-circle { width: 12px; height: 12px; display: inline-block; vertical-align: middle; }
.array-svg { width: 120px; height: auto; margin: 4px 0; }
.eqgroup-box { border: 2px solid #e0e0e0; border-radius: 8px; padding: 6px; display: inline-flex; gap: 3px; align-items: center; margin: 4px; min-width: 60px; justify-content: center; background: #fafafa; }
.mult-sign { font-size: 16px; font-weight: 700; color: #3f51b5; }
.div-sign { font-size: 16px; font-weight: 700; color: #3f51b5; }
.highlight { color: #3f51b5; font-weight: 700; }
.times-table { border: 2px solid #3f51b5; border-radius: 8px; padding: 8px; margin: 4px 0; background: #f5f5f5; }
.times-table h4 { font-size: 14px; color: #3f51b5; margin-bottom: 4px; }
.times-row { display: flex; align-items: center; gap: 6px; padding: 2px 0; font-size: 13px; }
.times-row .eq { color: #999; }
.chart-cell { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 28px; font-size: 11px; text-align: center; }
.chart-cell.header { font-weight: 700; background: #3f51b5; color: #fff; border-radius: 3px; }
.chart-cell.data { border: 1px solid #e0e0e0; }
.chart-cell.data.filled { background: #e8eaf6; font-weight: 600; color: #3f51b5; }
.chart-cell.data.empty { background: #fafafa; color: #ccc; }

/* ── Fluency grids ── */
.fluency-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 4px; }
.fluency-item { border: 1.5px solid #e0e0e0; border-radius: 4px; padding: 4px; text-align: center; font-size: 12px; }
.fluency-item .answer { margin-top: 2px; }

/* ── Scavenger / certificates ── */
.scavenger-card { border: 2px solid #ff9800; border-radius: 8px; padding: 8px 10px; margin-bottom: 6px; background: #fff3e0; }
.scavenger-card .clue { font-size: 11px; color: #e65100; font-weight: 600; }
.scavenger-card .answer-line { margin-top: 4px; }
.cert-border { border: 4px double #3f51b5; border-radius: 12px; padding: 20px; text-align: center; background: linear-gradient(to bottom, #fffde7, #fff); }
.cert-title { font-size: 24px; font-weight: 700; color: #3f51b5; margin-bottom: 4px; }
.cert-subtitle { font-size: 14px; color: #555; margin-bottom: 8px; }
.cert-name { font-size: 18px; border-bottom: 2px solid #333; display: inline-block; min-width: 200px; margin: 8px 0; }
.cert-body { font-size: 12px; color: #555; margin: 8px 0; line-height: 1.6; }
.mixed-problem { border: 1.5px solid #e0e0e0; border-radius: 4px; padding: 6px 10px; margin-bottom: 4px; }
.badge-row { display: flex; gap: 8px; flex-wrap: wrap; }
.badge { border: 2px solid; border-radius: 6px; padding: 4px 8px; font-size: 10px; font-weight: 600; }
.cat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; }
.cat-item { border: 1.5px solid #e0e0e0; border-radius: 4px; padding: 5px; text-align: center; font-size: 11px; }
.cat-svg { width: 100px; height: 100px; }

/* ── Work line ── */
.work-line { border-bottom: 1px solid #ddd; height: 24px; margin-bottom: 3px; }
"""

# Teacher guide specific CSS additions
TEACHER_CSS = r"""
""" + CSS + r"""
/* Teacher guide overrides */
.tg-head { display: flex; align-items: baseline; gap: 10px; padding-bottom: 4px; border-bottom: 3px solid #4caf50; margin-bottom: 6px; }
.tg-head .week { font-size: 18px; font-weight: 700; color: #4caf50; letter-spacing: -0.5px; }
.tg-head .day { font-size: 13px; font-weight: 600; color: #4caf50; background: #e8f5e9; padding: 2px 10px; border-radius: 3px; }
.tg-head .topic { font-size: 11.5px; color: #888; margin-left: auto; font-style: italic; }

.tg-sec { margin-bottom: 5px; }
.tg-sec-head { display: flex; align-items: center; gap: 6px; margin-bottom: 3px; }
.tg-sec-n { font-size: 10px; font-weight: 700; color: #fff; background: #4caf50; width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; border-radius: 3px; flex-shrink: 0; }
.tg-sec-t { font-size: 12.5px; font-weight: 600; color: #333; }

.tg-answer { color: #4caf50; font-weight: 700; font-size: 13px; }
.tg-label { font-size: 10px; color: #999; }
.tg-note { font-size: 10.5px; color: #999; font-style: italic; margin-bottom: 4px; }

.tg-mgrid { display: grid; gap: 3px 0; }
.tg-mgrid.c2 { grid-template-columns: 1fr 1fr; }
.tg-mgrid.c3 { grid-template-columns: 1fr 1fr 1fr; }
.tg-mgrid.c4 { grid-template-columns: 1fr 1fr 1fr 1fr; }
.tg-mgrid.c5 { grid-template-columns: repeat(5, 1fr); }

.tg-problem { font-family: 'Courier New', monospace; font-size: 12px; margin-bottom: 2px; }
.tg-problem .ans { color: #4caf50; font-weight: 700; }

.tg-box { border: 1px solid #c8e6c9; border-radius: 4px; padding: 4px 8px; margin-bottom: 3px; background: #f9fbe7; }

.tg-section-title { font-size: 14px; font-weight: 700; color: #4caf50; margin-bottom: 4px; margin-top: 6px; }
"""


# ═══════════════════════════════════════════════════
# Core HTML Helpers
# ═══════════════════════════════════════════════════

def page(week_num, day, topic, body):
    """Build a complete HTML page for a student worksheet."""
    return f"""<!DOCTYPE html>
<html><head><meta charset="utf-8">
<style>{CSS}</style></head><body>

<page>
{hdr(week_num, day, topic)}

{body}

</page>
</body></html>"""


def page_multi(week_num, day, topic, *page_bodies):
    """Build multi-page HTML with multiple <page> blocks."""
    pages = ""
    for i, body in enumerate(page_bodies):
        if i == 0:
            pages = f"<page>\n{hdr(week_num, day, topic)}\n\n{body}\n\n</page>"
        else:
            pages += f"\n<page>\n\n{body}\n\n</page>"
    return f"""<!DOCTYPE html>
<html><head><meta charset="utf-8">
<style>{CSS}</style></head><body>

{pages}
</body></html>"""


def hdr(week_num, day, topic):
    """Page header with week number, day, and topic."""
    return (f'<div class="head">'
            f'<span class="week">Week {week_num}</span>'
            f'<span class="day">{day}</span>'
            f'<span class="topic">{topic}</span>'
            f'</div>')


def sec(n, title, body, pb=False):
    """Numbered section. Set pb=True for page break before."""
    cls = 'sec pb' if pb else 'sec'
    return (f'<div class="{cls}">'
            f'<div class="sec-head"><span class="sec-n">{n}</span><span class="sec-t">{title}</span></div>'
            f'{body}</div>')


def b(w="3em"):
    """Short answer blank — larger defaults for 7-year-old handwriting."""
    return f'<span class="b" style="min-width:{w}"></span>'


def bw(w="10em"):
    """Wide answer blank."""
    return f'<span class="bw" style="min-width:{w}"></span>'


def bl(w="14em"):
    """Long answer blank (sentences/paragraphs)."""
    return f'<span class="bl" style="min-width:{w}"></span>'


def generate(week_dir, days):
    """
    Generate student PDFs for all days.
    
    days: list of (day_name, topic, html_func)
          or (day_name, topic, html_func, teacher_func)
    
    Example:
        days = [
            ("Monday", "Counting", monday, monday_tg),
            ("Tuesday", "Place Value", tuesday, tuesday_tg),
            ...
        ]
    """
    os.makedirs(week_dir, exist_ok=True)
    for f in glob.glob(os.path.join(week_dir, "*.pdf")):
        os.remove(f)

    for day_name, topic, html_func, *rest in days:
        html = html_func()
        filename = f"W{day_name.capitalize()[0]}{day_name[1:]}_{'_'.join(topic.split())}"
        # Sanitize filename
        filename = "".join(c for c in filename if c.isalnum() or c in "_ -")
        filename = filename.replace(" ", "_").replace("--", "_").replace("-_", "_")

        path = os.path.join(week_dir, f"Week_{day_name[0]}{day_name[1:]}_{topic.replace(' ', '_')}.pdf")
        HTML(string=html).write_pdf(path)
        print(f"Created: {path}")

        # Teacher guide
        if rest:
            teacher_func = rest[0]
            tg_html = teacher_func()
            tg_path = os.path.join(week_dir, f"Teacher_Guide_Week_{day_name[0]}{day_name[1:]}_{topic.replace(' ', '_')}.pdf")
            HTML(string=tg_html).write_pdf(tg_path)
            print(f"Created: {tg_path}")


def generate_simple(week_dir, days, filenames=None):
    """
    Simple generate — uses provided filenames or auto-generates.
    
    days: list of (day_name, topic, html_func)
    filenames: optional list of (student_filename, teacher_filename) tuples
               or just (filename,) if no teacher guide
    """
    os.makedirs(week_dir, exist_ok=True)
    for f in glob.glob(os.path.join(week_dir, "*.pdf")):
        os.remove(f)

    for i, (day_name, topic, func, *rest) in enumerate(days):
        html = func()
        if filenames and i < len(filenames):
            fname = filenames[i][0]
        else:
            fname = f"Week_{day_name[0]}{day_name[1:]}_{topic.replace(' ', '_')}"

        path = os.path.join(week_dir, f"{fname}.pdf")
        HTML(string=html).write_pdf(path)
        print(f"Created: {path}")

        # Teacher guide
        if rest:
            tg_html = rest[0]()
            if filenames and i < len(filenames) and len(filenames[i]) > 1:
                tg_fname = filenames[i][1]
            else:
                tg_fname = f"Teacher_Guide_{fname}"
            tg_path = os.path.join(week_dir, f"{tg_fname}.pdf")
            HTML(string=tg_html).write_pdf(tg_path)
            print(f"Created: {tg_path}")


# ═══════════════════════════════════════════════════
# SVG Generators
# ═══════════════════════════════════════════════════

def circle_svg(color, r=6, stroke="#333", stroke_width=1.5):
    """Generate a small circle SVG for equal groups."""
    return f'<svg viewBox="0 0 24 24" width="12" height="12"><circle cx="12" cy="12" r="{r}" fill="{color}" stroke="{stroke}" stroke-width="{stroke_width}"/></svg>'


def eq_group_svg(count, color=BLUE, label=""):
    """Generate an equal group box with circles."""
    circles = ''.join([f'<span class="group-circle">{circle_svg(color)}</span>' for _ in range(count)])
    return f'<div class="eqgroup-box">{circles}</div>'


def array_svg(rows, cols, color=BLUE, width="120"):
    """Generate an SVG array grid of dots."""
    cell = 14
    gap = 2
    svg_w = cols * (cell + gap) + gap
    svg_h = rows * (cell + gap) + gap
    svg = f'<svg class="array-svg" viewBox="0 0 {svg_w} {svg_h}" style="width:{width}px; height:auto;" width="{width}" height="auto">\n'
    for r in range(rows):
        for c in range(cols):
            x = gap + c * (cell + gap)
            y = gap + r * (cell + gap)
            svg += f'<circle cx="{x+cell/2}" cy="{y+cell/2}" r="{cell/2-1}" fill="{color}" stroke="#333" stroke-width="1"/>\n'
    svg += '</svg>'
    return svg


def shape_svg(shape_type, color=BLUE, size=40):
    """Generate a shape SVG."""
    if shape_type == "square":
        return f'<svg viewBox="0 0 40 40" width="{size}" height="{size}"><rect x="4" y="4" width="32" height="32" rx="2" fill="{color}" stroke="#333" stroke-width="1.5" opacity="0.6"/></svg>'
    elif shape_type == "circle":
        return f'<svg viewBox="0 0 40 40" width="{size}" height="{size}"><circle cx="20" cy="20" r="16" fill="{color}" stroke="#333" stroke-width="1.5" opacity="0.6"/></svg>'
    elif shape_type == "triangle":
        return f'<svg viewBox="0 0 40 40" width="{size}" height="{size}"><polygon points="20,4 36,36 4,36" fill="{color}" stroke="#333" stroke-width="1.5" opacity="0.6"/></svg>'
    elif shape_type == "rectangle":
        return f'<svg viewBox="0 0 50 30" width="{size+10}" height="{size}"><rect x="2" y="2" width="46" height="26" rx="2" fill="{color}" stroke="#333" stroke-width="1.5" opacity="0.6"/></svg>'
    elif shape_type == "star":
        pts = "20,2 25,14 38,14 27,22 31,36 20,27 9,36 13,22 2,14 15,14"
        return f'<svg viewBox="0 0 40 40" width="{size}" height="{size}"><polygon points="{pts}" fill="{color}" stroke="#333" stroke-width="1.5" opacity="0.6"/></svg>'
    return ''


def clock_svg(hour, minute, size=50):
    """Generate a simple analog clock SVG."""
    h_angle = (hour % 12) * 30 + minute * 0.5
    m_angle = minute * 6

    def hand_coords(angle, length, cx=25, cy=25):
        rad = math.radians(angle - 90)
        return f"{cx},{cy} {cx + length * math.cos(rad)},{cy + length * math.sin(rad)}"

    h_line = hand_coords(h_angle, 12)
    m_line = hand_coords(m_angle, 18)

    return f'''<svg viewBox="0 0 50 50" width="{size}" height="{size}">
    <circle cx="25" cy="25" r="22" fill="#fff" stroke="#333" stroke-width="1.5"/>
    <line x1="25" y1="3" x2="25" y2="7" stroke="#333" stroke-width="1.5"/>
    <line x1="25" y1="43" x2="25" y2="47" stroke="#333" stroke-width="1.5"/>
    <line x1="3" y1="25" x2="7" y2="25" stroke="#333" stroke-width="1.5"/>
    <line x1="43" y1="25" x2="47" y2="25" stroke="#333" stroke-width="1.5"/>
    <line {h_line} stroke="#333" stroke-width="2.5" stroke-linecap="round"/>
    <line {m_line} stroke="#e53935" stroke-width="1.5" stroke-linecap="round"/>
    <circle cx="25" cy="25" r="2" fill="#333"/>
    </svg>'''


def fraction_svg(numerator, denominator, color=BLUE, size=40):
    """Generate a fraction circle SVG (pie chart style)."""
    angle_per = 360 / denominator
    paths = ''
    for i in range(numerator):
        start = angle_per * i - 90
        end = angle_per * (i + 1) - 90
        x1 = 20 + 18 * math.cos(math.radians(start))
        y1 = 20 + 18 * math.sin(math.radians(start))
        x2 = 20 + 18 * math.cos(math.radians(end))
        y2 = 20 + 18 * math.sin(math.radians(end))
        large = 1 if angle_per > 180 else 0
        paths += f'<path d="M 20 20 L {x1:.1f} {y1:.1f} A 18 18 0 {large} 1 {x2:.1f} {y2:.1f} Z" fill="{color}" stroke="#333" stroke-width="0.8" opacity="0.7"/>'
    for i in range(denominator):
        start = angle_per * i - 90
        x1 = 20 + 18 * math.cos(math.radians(start))
        y1 = 20 + 18 * math.sin(math.radians(start))
        paths += f'<line x1="20" y1="20" x2="{x1:.1f}" y2="{y1:.1f}" stroke="#333" stroke-width="0.6"/>'
    paths += f'<circle cx="20" cy="20" r="18" fill="none" stroke="#333" stroke-width="1"/>'
    return f'<svg viewBox="0 0 40 40" width="{size}" height="{size}">{paths}</svg>'


def fraction_bar_svg(numerator, denominator, color=BLUE, width=100, height=20):
    """Generate a fraction bar SVG (rectangular bar divided into parts)."""
    part_w = width / denominator
    bars = ''
    for i in range(denominator):
        fill = color if i < numerator else '#f5f5f5'
        bars += f'<rect x="{i * part_w}" y="0" width="{part_w}" height="{height}" fill="{fill}" stroke="#333" stroke-width="0.5"/>'
    return f'<svg viewBox="0 0 {width} {height}" width="{width}" height="{height}">{bars}</svg>'


def coin_svg(coin_type, size=20):
    """Generate a coin SVG."""
    coins = {
        'penny': ('#b77', 'P', '#795548'),
        'nickel': ('#c0c0c0', 'N', '#9e9e9e'),
        'dime': ('#e0e0e0', 'D', '#bdbdbd'),
        'quarter': ('#90a4ae', 'Q', '#78909c'),
    }
    bg, label, stroke = coins.get(coin_type, ('#ccc', '?', '#999'))
    return f'<svg viewBox="0 0 20 20" width="{size}" height="{size}"><circle cx="10" cy="10" r="9" fill="{bg}" stroke="{stroke}" stroke-width="1"/><text x="10" y="14" text-anchor="middle" font-size="8" font-weight="700" fill="#fff">{label}</text></svg>'


def grid_svg(rows, cols, cell=14, gap=1, filled_cells=None, color=BLUE):
    """Generate a square grid SVG for area/perimeter."""
    total_w = cols * cell + (cols - 1) * gap
    total_h = rows * cell + (rows - 1) * gap
    cells = ''
    for r in range(rows):
        for c in range(cols):
            x = c * (cell + gap)
            y = r * (cell + gap)
            fill = color if filled_cells and (r, c) in filled_cells else '#f5f5f5'
            cells += f'<rect x="{x}" y="{y}" width="{cell}" height="{cell}" fill="{fill}" stroke="#333" stroke-width="0.5"/>'
    return f'<svg viewBox="0 0 {total_w} {total_h}" width="{total_w + 2}" height="{total_h + 2}">{cells}</svg>'


def bar_graph_svg(data, colors, labels=None, width=200, height=100):
    """Generate a simple bar graph SVG."""
    n = len(data)
    bar_w = min(20, (width - (n + 1) * 6) // n)
    gap = (width - n * bar_w) // (n + 1)
    max_val = max(data) if data else 1
    bars = ''
    for i, (val, color) in enumerate(zip(data, colors)):
        x = gap + i * (bar_w + gap)
        bar_h = int(val / max_val * (height - 25))
        y = height - 12 - bar_h
        bars += f'<rect x="{x}" y="{y}" width="{bar_w}" height="{bar_h}" fill="{color}" stroke="#333" stroke-width="0.8" rx="2"/>'
        bars += f'<text x="{x + bar_w//2}" y="{y - 2}" text-anchor="middle" font-size="7" fill="#333">{val}</text>'
        if labels and i < len(labels):
            bars += f'<text x="{x + bar_w//2}" y="{height - 2}" text-anchor="middle" font-size="6" fill="#666">{labels[i]}</text>'
    return f'<svg viewBox="0 0 {width} {height}" width="{width}" height="{height}">{bars}<line x1="0" y1="{height-10}" x2="{width}" y2="{height-10}" stroke="#333" stroke-width="1"/></svg>'


def star_svg(color=GOLD, size=16):
    """Generate a star SVG."""
    pts = "8,1 10,6 16,6 11,10 13,16 8,12 3,16 5,10 0,6 6,6"
    return f'<svg viewBox="0 0 16 16" width="{size}" height="{size}"><polygon points="{pts}" fill="{color}" stroke="#333" stroke-width="0.8"/></svg>'


def trophy_svg(size=32):
    """Generate a trophy SVG."""
    return f'''<svg viewBox="0 0 32 32" width="{size}" height="{size}">
    <polygon points="10,4 22,4 20,16 12,16" fill="#ffc107" stroke="#333" stroke-width="1"/>
    <rect x="11" y="16" width="10" height="3" rx="1" fill="#ff9800" stroke="#333" stroke-width="0.8"/>
    <rect x="13" y="19" width="6" height="3" fill="#8d6e63" stroke="#333" stroke-width="0.8"/>
    <rect x="10" y="22" width="12" height="3" rx="1" fill="#795548" stroke="#333" stroke-width="0.8"/>
    <circle cx="16" cy="10" r="2" fill="#fff" stroke="#333" stroke-width="0.5"/>
    </svg>'''


def medal_svg(letter, color=BLUE, size=30):
    """Generate a medal SVG."""
    return f'''<svg viewBox="0 0 30 30" width="{size}" height="{size}">
    <polygon points="15,0 18,10 28,10 20,16 23,26 15,20 7,26 10,16 2,10 12,10" fill="{color}" stroke="#333" stroke-width="1.2"/>
    <text x="15" y="18" text-anchor="middle" font-size="10" font-weight="700" fill="#fff">{letter}</text>
    </svg>'''


def check_svg(size=14):
    """Generate a checkmark SVG."""
    return f'<svg viewBox="0 0 16 16" width="{size}" height="{size}"><circle cx="8" cy="8" r="7" fill="#4caf50" stroke="#333" stroke-width="0.8"/><text x="8" y="12" text-anchor="middle" font-size="10" fill="#fff">&check;</text></svg>'


# ═══════════════════════════════════════════════════
# Multiplication Helpers
# ═══════════════════════════════════════════════════

def times_table_html(factor, color=BLUE):
    """Generate a mini times table for a given factor."""
    rows = []
    for i in range(11):
        rows.append(f'<div class="times-row"><span>{factor} <span class="mult-sign">&times;</span> {i}</span><span class="eq">=</span><span class="highlight">{factor * i}</span></div>')
    return f'<div class="times-table" style="border-color:{color};"><h4 style="color:{color}">The {factor}s</h4>{"".join(rows)}</div>'


def skip_count_html(numbers, blanks_indices, color=BLUE):
    """Generate skip counting circles with blanks at specified indices."""
    parts = []
    for i, n in enumerate(numbers):
        if i in blanks_indices:
            parts.append('<span class="skip-blank"></span>')
        else:
            parts.append(f'<span class="skip-num" style="border-color:{color}; color:{color};">{n}</span>')
    return ''.join(parts)


def mini_chart_html(facts, max_factor=5):
    """Generate a mini multiplication chart with some facts filled."""
    html = '<table style="border-collapse:collapse; margin:4px 0;">\n'
    html += '<tr><td class="chart-cell header">&times;</td>'
    for c in range(max_factor + 1):
        html += f'<td class="chart-cell header">{c}</td>'
    html += '</tr>\n'
    for r in range(max_factor + 1):
        html += f'<tr><td class="chart-cell header">{r}</td>'
        for c in range(max_factor + 1):
            if (r, c) in facts:
                html += f'<td class="chart-cell data filled">{r * c}</td>'
            else:
                html += '<td class="chart-cell data empty">&nbsp;</td>'
        html += '</tr>\n'
    html += '</table>'
    return html


# ═══════════════════════════════════════════════════
# Ruler Helpers
# ═══════════════════════════════════════════════════

def ruler_inches(length_inches=12):
    """Generate an inch ruler with CSS positioning."""
    total_width = length_inches * 48
    marks = ''
    for i in range(length_inches * 4):
        pos = i * 12
        inch_val = i // 4
        if i % 4 == 0:
            marks += f'<div class="ruler-mark major" style="left:{pos}px"></div>'
            if inch_val > 0:
                marks += f'<div class="ruler-num" style="left:{pos}px">{inch_val}</div>'
        elif i % 2 == 0:
            marks += f'<div class="ruler-mark mid" style="left:{pos}px"></div>'
        else:
            marks += f'<div class="ruler-mark minor" style="left:{pos}px"></div>'
    return (f'<div class="ruler-container">'
            f'<div class="ruler" style="width:{total_width}px">'
            f'<div class="ruler-marks">{marks}</div>'
            f'</div>'
            f'<div class="ruler-label">inches</div>'
            f'</div>')


def ruler_cm(length_cm=15):
    """Generate a centimeter ruler with CSS positioning."""
    total_width = length_cm * 24
    marks = ''
    for i in range(length_cm * 2):
        pos = i * 12
        cm_val = i // 2
        if i % 2 == 0:
            marks += f'<div class="ruler-mark major" style="left:{pos}px"></div>'
            if cm_val > 0:
                marks += f'<div class="ruler-num" style="left:{pos}px">{cm_val}</div>'
        else:
            marks += f'<div class="ruler-mark mid" style="left:{pos}px"></div>'
    return (f'<div class="ruler-container">'
            f'<div class="ruler" style="width:{total_width}px">'
            f'<div class="ruler-marks">{marks}</div>'
            f'</div>'
            f'<div class="ruler-label">centimeters</div>'
            f'</div>')


def measure_line(px_length, label="", unit="inches"):
    """Generate a measurement line with label and blank."""
    return (f'<div style="display:flex; align-items:center; gap:6px; margin-bottom:4px;">'
            f'<div class="measure-line" style="width:{px_length}px"></div>'
            f'{label if label else ""} '
            f'<span class="b" style="min-width:2em"></span> {unit}'
            f'</div>')


def measure_line_cm(px_length, label=""):
    """Generate a measurement line in centimeters."""
    return (f'<div style="display:flex; align-items:center; gap:6px; margin-bottom:4px;">'
            f'<div class="measure-line" style="width:{px_length}px"></div>'
            f'{label if label else ""} '
            f'<span class="b" style="min-width:2em"></span> cm'
            f'</div>')


# ═══════════════════════════════════════════════════
# Teacher Guide Helpers
# ═══════════════════════════════════════════════════

def tg_page(day, topic, body):
    """Build a complete teacher guide HTML page."""
    return f"""<!DOCTYPE html>
<html><head><meta charset="utf-8">
<style>{TEACHER_CSS}</style></head><body>

<page>
<div class="tg-head">
<span class="week">Teacher Guide</span>
<span class="day">{day}</span>
<span class="topic">{topic}</span>
</div>

{body}

</page>
</body></html>"""


def tg_page_multi(day, topic, *page_bodies):
    """Build multi-page teacher guide."""
    pages = ""
    for i, body in enumerate(page_bodies):
        header = ""
        if i == 0:
            header = '<div class="tg-head"><span class="week">Teacher Guide</span><span class="day">{}</span><span class="topic">{}</span></div>'.format(day, topic)
        pages += f"<page>\n{header}\n\n{body}\n\n</page>"
    return f"""<!DOCTYPE html>
<html><head><meta charset="utf-8">
<style>{TEACHER_CSS}</style></head><body>

{pages}
</body></html>"""


def tg_sec(n, title, answers):
    """Teacher guide section with numbered answers."""
    items = ""
    for i, ans in enumerate(answers, 1):
        items += f'<div class="tg-problem">{i}. <span class="ans">{ans}</span></div>\n'
    return (f'<div class="tg-sec">'
            f'<div class="tg-sec-head"><span class="tg-sec-n">{n}</span><span class="tg-sec-t">{title}</span></div>'
            f'<div class="tg-box">{items}</div></div>')


def tg_grid_answers(n, title, answers, cols=2):
    """Teacher guide section with answers in a grid."""
    grid_class = f"tg-mgrid.c{cols}"
    items = "".join(f'<div class="tg-box" style="text-align:center"><span class="tg-answer">{a}</span></div>' for a in answers)
    return (f'<div class="tg-sec">'
            f'<div class="tg-sec-head"><span class="tg-sec-n">{n}</span><span class="tg-sec-t">{title}</span></div>'
            f'<div class="{grid_class}">{items}</div></div>')


def tg_note(text):
    """Teacher note."""
    return f'<p class="tg-note">{text}</p>'


def tg_section_title(text):
    """Section divider title."""
    return f'<div class="tg-section-title">{text}</div>'


# ═══════════════════════════════════════════════════
# Column Math Helpers (vertical format)
# ═══════════════════════════════════════════════════

def col_add(a, b_val, digits=2, ans_w=None):
    """
    Vertical column addition (no answer line - student writes underneath).
    digits: 2 for 2-digit, 3 for 3-digit numbers
    """
    width = 50 if digits == 2 else 60
    return (f'<div class="colbox" style="display:inline-block; width:{width}px;">'
            f'<div style="text-align:right; padding:4px 0;"><span style="font-size:17px; font-family:monospace;">{a}</span></div>'
            f'<div style="text-align:right; padding:4px 0;"><span style="font-size:17px; font-family:monospace;">+ {b_val}</span></div>'
            f'<div style="border-top:2px solid #333; margin:3px 0;"></div>'
            f'<div style="height:3.5em;"></div></div>')


def col_sub(a, b_val, digits=2, ans_w=None):
    """
    Vertical column subtraction (no answer line - student writes underneath).
    digits: 2 for 2-digit, 3 for 3-digit numbers
    """
    width = 50 if digits == 2 else 60
    return (f'<div class="colbox" style="display:inline-block; width:{width}px;">'
            f'<div style="text-align:right; padding:4px 0;"><span style="font-size:17px; font-family:monospace;">{a}</span></div>'
            f'<div style="text-align:right; padding:4px 0;"><span style="font-size:17px; font-family:monospace;">- {b_val}</span></div>'
            f'<div style="border-top:2px solid #333; margin:3px 0;"></div>'
            f'<div style="height:3.5em;"></div></div>')


def col_add_inline(a, b_val, digits=2):
    """Inline horizontal addition for grid display."""
    blank_size = "4.5em" if digits == 2 else "5.5em"
    return f'<span style="font-family:monospace; font-size:15px;">{a} + {b_val} = </span>' + b(blank_size)


def col_sub_inline(a, b_val, digits=2):
    """Inline horizontal subtraction for grid display."""
    blank_size = "4.5em" if digits == 2 else "5.5em"
    return f'<span style="font-family:monospace; font-size:15px;">{a} - {b_val} = </span>' + b(blank_size)