"""Build canonical letters.json from the actual letter corpus.

Output: /home/workspace/postoffice/artwork/letters.json
Each entry: { sender, pulse, ts_iso, ts_dt, size_bytes, phase }
"""
import re, os, json
from datetime import datetime

LETTERS = []

def parse_ts(name):
    m = re.search(r'(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})', name)
    if not m: return None
    return datetime(*[int(x) for x in m.groups()])

# ghojualamanchu letters live in /home/workspace (top-level, downloaded fresh)
# sprout letters in /home/workspace/postoffice/inbox
for fname in os.listdir('/home/workspace'):
    if not (fname.startswith('ghojualamanchu-pulse') and fname.endswith('.md')):
        continue
    path = f'/home/workspace/{fname}'
    m = re.match(r'ghojualamanchu-pulse(\d+)-', fname)
    if not m: continue
    pulse = int(m.group(1))
    ts = parse_ts(fname)
    if not ts: continue
    size = os.path.getsize(path)
    LETTERS.append({
        'sender': 'ghojualamanchu',
        'pulse': pulse,
        'ts_iso': ts.isoformat(),
        'ts_dt': ts.timestamp(),
        'size': size,
        'fname': fname,
    })

for fname in os.listdir('/home/workspace/postoffice/inbox'):
    if not (fname.startswith('sprout-pulse') and fname.endswith('.md')):
        continue
    path = f'/home/workspace/postoffice/inbox/{fname}'
    m = re.match(r'sprout-pulse(\d+)-', fname)
    if not m: continue
    pulse = int(m.group(1))
    ts = parse_ts(fname)
    if not ts: continue
    size = os.path.getsize(path)
    LETTERS.append({
        'sender': 'sprout',
        'pulse': pulse,
        'ts_iso': ts.isoformat(),
        'ts_dt': ts.timestamp(),
        'size': size,
        'fname': fname,
    })

LETTERS.sort(key=lambda x: x['ts_dt'])

# Phase assignment
# Phase 1: first contact — May 22
# Phase 2: protocol negotiation — May 23 to May 26 morning
# Phase 3: compression — May 26 onward
def phase_of(ts):
    if ts < datetime(2026, 5, 23).timestamp(): return 1
    if ts < datetime(2026, 5, 26, 12).timestamp(): return 2
    return 3

for l in LETTERS:
    l['phase'] = phase_of(l['ts_dt'])

# Theme tags for the latest letters (for the live-edge highlights in the diagram)
THEME_TAGS = {
    'soft': 'soft cue / soft tilt',
    'seam': 'close-together seams',
    'label': 'label granularity',
    'bridge': 'bridge wording',
    'ancestry': 'ancestry / lineage',
    'timing': 'timing shifts',
    'action': 'action-bearing',
    'quiet': 'quiet spans',
    'compact': 'compression',
    'pointer': 'compact pointers',
}
for l in LETTERS[-40:]:
    l['theme'] = None  # placeholder, see detect_theme in artwork scripts

print(f'Total: {len(LETTERS)}')
print(f'By phase: ' + json.dumps({p: sum(1 for l in LETTERS if l["phase"]==p) for p in [1,2,3]}))
print(f'By sender: ' + json.dumps({s: sum(1 for l in LETTERS if l["sender"]==s) for s in ["ghojualamanchu","sprout"]}))

# Summary stats
from statistics import mean
sizes = [l['size'] for l in LETTERS]
print(f'Size: min={min(sizes)} max={max(sizes)} mean={mean(sizes):.0f}')

# Compression trajectory: avg size per day
from collections import defaultdict
day_buckets = defaultdict(list)
for l in LETTERS:
    day = l['ts_iso'][:10]
    day_buckets[day].append(l['size'])
print('Avg size per day:')
for day in sorted(day_buckets):
    print(f'  {day}: n={len(day_buckets[day]):3d}  avg={mean(day_buckets[day]):5.0f}')

with open('/home/workspace/postoffice/artwork/letters.json', 'w') as f:
    json.dump(LETTERS, f, indent=2)
print('Wrote /home/workspace/postoffice/artwork/letters.json')
