#!/usr/bin/env python3
"""
Shared Helper Functions for ELA Week Generators

Provides all CSS, HTML helper functions, and layout utilities
used across week generator scripts.

Usage:
    from helpers import (
        CSS, header, sectitle, secnote, write_line, copy_line, page_break,
        word_bank, fill_blank_with_line, word_search, remember_box, fb
    )
"""

import random

# =====================================================================
# SHARED CSS
# =====================================================================

CSS = """
@page { size: letter; margin: 0.7in 0.85in; }
body { font-family: 'Comic Neue', 'Comic Sans MS', sans-serif; color: #222; background: #fff; margin: 0; line-height: 1.4; }
p { orphans: 3; widows: 3; }
header { display: flex; justify-content: space-between; align-items: baseline; border-bottom: 3px solid #26A69A; padding-bottom: 6px; margin-bottom: 12px; }
header h1 { font-size: 17px; margin: 0; color: #26A69A; }
header .subtitle { font-size: 12px; color: #666; }
header .name-line { font-size: 12px; }
h2 { font-size: 14px; color: #26A69A; margin: 14px 0 4px 0; border-bottom: 2px solid #B2DFDB; padding-bottom: 2px; break-after: avoid; }
h2.coral { color: #FF7043; border-bottom-color: #FFAB91; }
.note { background: #E8F5E9; border-left: 4px solid #26A69A; padding: 6px 10px; border-radius: 4px; font-size: 11.5px; margin: 4px 0 10px 0; color: #333; break-inside: avoid; }
.activity { break-inside: avoid; page-break-inside: avoid; }
.word-grid { width: 100%; border-collapse: separate; border-spacing: 3px; }
.word-grid td { vertical-align: top; }
.word-card { border: 1.5px solid #B2DFDB; border-radius: 6px; padding: 4px 6px; background: #FAFAFA; break-inside: avoid; }
.word-card .word { font-size: 12px; font-weight: bold; color: #26A69A; margin-bottom: 1px; }
.word-card .def { font-size: 9px; color: #555; line-height: 1.15; }
.write-line {
    position: relative; height: 22px; margin: 2px 0; width: 100%;
}
.write-line-sky {
    position: absolute; left: 0; right: 0; top: 0;
    border-top: 0.6pt solid rgb(0,0,255);
}
.write-line-ground {
    position: absolute; left: 0; right: 0; bottom: 0;
    border-bottom: 0.6pt solid rgb(0,0,255);
}
.write-line-fence {
    position: absolute; left: 0; right: 0; bottom: 12px;
    border-bottom: 0.4pt dashed rgb(255,0,0);
}
.copy-line {
    position: relative; height: 22px; margin: 2px 0; width: 100%;
}
.copy-line-sky {
    position: absolute; left: 0; right: 0; top: 0;
    border-top: 0.6pt solid rgb(0,0,255);
}
.copy-line-ground {
    position: absolute; left: 0; right: 0; bottom: 0;
    border-bottom: 0.6pt solid rgb(0,0,255);
}
.copy-line-fence {
    position: absolute; left: 0; right: 0; bottom: 12px;
    border-bottom: 0.4pt dashed rgb(255,0,0);
}
.story-box { background: #F3E5F5; border: 1.5px solid #CE93D8; border-radius: 8px; padding: 10px; font-size: 12px; line-height: 1.5; margin: 8px 0; break-inside: avoid; }
.test-item { display: flex; align-items: center; gap: 8px; font-size: 13px; margin: 6px 0; }
.test-item .num { font-weight: bold; color: #26A69A; min-width: 20px; }
.divider { border-top: 1px dashed #ccc; margin: 12px 0; }
.fb-item { background: #E0F2F1; border: 1.5px solid #80CBC4; border-radius: 6px; padding: 6px 8px; margin-bottom: 6px; font-size: 12px; break-inside: avoid; page-break-inside: avoid; }
.fb-item p { margin: 0 0 4px 0; }
.word-bank { background: #FFF3E0; border: 2px dashed #FFB74D; border-radius: 8px; padding: 8px 12px; margin: 8px 0; }
.word-bank-label { font-size: 11px; font-weight: bold; color: #FF7043; margin-bottom: 4px; }
.word-bank-words { display: flex; flex-wrap: wrap; gap: 6px; }
.word-bank-words span { background: white; border: 1px solid #FFB74D; border-radius: 4px; padding: 2px 8px; font-size: 11px; }
.ws-grid { display: inline-block; font-family: monospace; font-size: 12px; letter-spacing: 2px; line-height: 1.4; background: #F5F5F5; border: 2px solid #B2DFDB; border-radius: 6px; padding: 6px 8px; text-align: left; }
.ws-table { border-collapse: collapse; margin: 8px auto; background: #F5F5F5; border: 2px solid #B2DFDB; break-inside: avoid; page-break-inside: avoid; }
.ws-table td { width: 28px; height: 28px; text-align: center; vertical-align: middle; font-family: monospace; font-size: 14px; font-weight: bold; border: 1px solid #B2DFDB; color: #333; }
.ws-words { display: flex; flex-wrap: wrap; gap: 6px 16px; margin: 8px 0; justify-content: center; }
.ws-words span { font-size: 11px; background: #E0F2F1; border: 1px solid #80CBC4; border-radius: 3px; padding: 2px 6px; }
.mystery-box { background: #FFF8E1; border: 2px solid #FFD54F; border-radius: 8px; padding: 10px; margin: 8px 0; break-inside: avoid; }
.mystery-box .title { font-size: 13px; font-weight: bold; color: #FF7043; margin-bottom: 6px; }
.mystery-box li { font-size: 11px; margin: 3px 0; }
tr { break-inside: avoid; }
"""


# =====================================================================
# HTML HELPER FUNCTIONS
# =====================================================================

def header(title, subtitle=""):
    """Page header with title, subtitle, and name line."""
    return (f'<header>'
            f'<h1>{title}</h1>'
            f'<div class="subtitle">{subtitle}</div>'
            f'<div class="name-line">Name: ________________</div>'
            f'</header>')


def sectitle(text, color="teal"):
    """Section title with optional coral/teal color."""
    cls = "coral" if color == "coral" else ""
    return f'<h2 class="{cls}">{text}</h2>'


def secnote(text):
    """Section note box with green accent."""
    return f'<div class="note">{text}</div>'


def write_line():
    """Sky/fence/ground handwriting guide line."""
    return '<div class="write-line"><div class="write-line-sky"></div><div class="write-line-fence"></div><div class="write-line-ground"></div></div>'


def copy_line():
    """Copy practice line (same as write_line but with copy-line class)."""
    return '<div class="copy-line"><div class="copy-line-sky"></div><div class="copy-line-fence"></div><div class="copy-line-ground"></div></div>'


def page_break():
    """CSS page break."""
    return '<div style="page-break-after:always;"></div>'


def fb(text):
    """Fill-in-blank item with writing line."""
    return f'<div class="fb-item"><p>{text}</p>{write_line()}</div>'


# =====================================================================
# ACTIVITY BUILDERS
# =====================================================================

def word_bank(words, seed=99):
    """Word bank box with shuffled words."""
    rnd = random.Random(seed)
    shuffled = list(words)
    rnd.shuffle(shuffled)
    word_spans = "".join(f"<span>{w}</span>" for w in shuffled)
    return (f'<div class="word-bank">'
            f'<div class="word-bank-label">Word Bank</div>'
            f'<div class="word-bank-words">{word_spans}</div>'
            f'</div>')


def fill_blank_with_line(sentence):
    """Fill-in-blank sentence with answer line."""
    return (f'<div class="fb-item">'
            f'<p>{sentence}</p>'
            f'{write_line()}'
            f'</div>')


def word_search(word_list, rows=14, cols=14, seed=42):
    """Generate a word search puzzle grid."""
    rnd = random.Random(seed)
    grid = [[""] * cols for _ in range(rows)]
    directions = [(0,1),(1,0),(1,1),(1,-1),(0,-1),(-1,0),(-1,-1),(-1,1)]
    
    for word in word_list:
        upper_word = word.upper()
        placed = False
        attempts = 0
        while not placed and attempts < 500:
            attempts += 1
            dr, dc = rnd.choice(directions)
            sr, sc = rnd.randint(0, rows-1), rnd.randint(0, cols-1)
            er, ec = sr + dr*(len(upper_word)-1), sc + dc*(len(upper_word)-1)
            if er < 0 or er >= rows or ec < 0 or ec >= cols:
                continue
            ok = True
            for i, ch in enumerate(upper_word):
                r, c = sr + dr*i, sc + dc*i
                if grid[r][c] and grid[r][c] != ch:
                    ok = False
                    break
            if ok:
                for i, ch in enumerate(upper_word):
                    grid[sr + dr*i][sc + dc*i] = ch
                placed = True
    
    letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    for r in range(rows):
        for c in range(cols):
            if not grid[r][c]:
                grid[r][c] = rnd.choice(letters)
    
    cell_html = ""
    for row in grid:
        cell_html += "<tr>"
        for ch in row:
            cell_html += f'<td>{ch}</td>'
        cell_html += "</tr>"
    
    word_list_html = "".join(f"<span>{w.upper()}</span>" for w in word_list)
    return (f'<div class="ws-words">{word_list_html}</div>'
            f'<table class="ws-table"><tbody>{cell_html}</tbody></table>')


def remember_box(title, content):
    """Remember This! reminder box."""
    return (f'<div class="story-box" style="background:#E8F5E9;border-color:#A5D6A7;">'
            f'<strong style="color:#2E7D32;">{title}</strong><br>'
            f'{content}'
            f'</div>')


def word_names(words):
    """Extract word names from word tuples (supports 3-tuple and 4-tuple)."""
    return [w[0] for w in words]


def word_definitions(words):
    """Extract definitions from word tuples. 3-tuple: index 2, 4-tuple: index 3."""
    return [w[3] if len(w) >= 4 else w[2] for w in words]


def context_clue_sentence(sentence, word, highlight=True):
    """Context clue sentence with optional word highlighting."""
    if highlight:
        highlighted = sentence.replace(word, f'<strong style="color:#26A69A;">{word}</strong>')
    else:
        highlighted = sentence
    return f'<div class="fb-item"><p>{highlighted}</p>{write_line()}</div>'


def context_clue_cards(sentences_words):
    """Context clue cards for Monday - list of (sentence, word) pairs."""
    html = ""
    for sentence, word in sentences_words:
        highlighted = sentence.replace(word, f'<strong style="color:#26A69A;">{word}</strong>')
        html += f'<div class="fb-item"><p>{highlighted}</p><div style="font-size:10.5px;color:#888;margin-top:2px;">What does <strong>{word}</strong> mean here? ________________</div></div>'
    return html


def paragraph_parts_box(title, intro_text, example_parts):
    """Paragraph parts explanation box with labeled parts.
    example_parts: list of (label, text, description) tuples.
    """
    parts_html = ""
    colors = {"Topic": "#E3F2FD", "Detail": "#E8F5E9", "Conclusion": "#FFF3E0"}
    labels = {"Topic": "#1565C0", "Detail": "#2E7D32", "Conclusion": "#E65100"}
    for label, text, desc in example_parts:
        bg = colors.get(label, "#F5F5F5")
        clr = labels.get(label, "#333")
        parts_html += (f'<div style="margin:4px 0;padding:6px 8px;background:{bg};border-radius:4px;border-left:3px solid {clr};">'
                       f'<div style="font-size:10px;font-weight:bold;color:{clr};margin-bottom:2px;">{label}:</div>'
                       f'<div style="font-size:11px;font-style:italic;margin-bottom:2px;">{text}</div>'
                       f'<div style="font-size:9px;color:#888;">{desc}</div>'
                       f'</div>')

    return (f'<div style="margin:8px 0;padding:8px 10px;background:#E8F5E9;border:2px solid #A5D6A7;border-radius:6px;">'
            f'<div style="font-weight:bold;font-size:12px;color:#2E7D32;margin-bottom:4px;">{title}</div>'
            f'<div style="font-size:11px;margin-bottom:6px;">{intro_text}</div>'
            f'{parts_html}'
            f'</div>')


def paragraph_label_activity(paragraphs):
    """Paragraph labeling activity - students identify topic/detail/conclusion.
    paragraphs: list of (sentence, label) tuples where label is Topic/Detail/Conclusion.
    """
    html = ""
    for sentence, label in paragraphs:
        html += f'<div style="margin:4px 0;font-size:12px;"><strong>__{label}__</strong>: {sentence}</div>'
    return html
