#!/usr/bin/env python3
"""
Idempotent rebuild of the daily activity log from the glasses NOW-task source of truth.

Reads /data/cameron/agents_stuff/agents/glasses/now_log.md (append-only),
filters to a target date (default: today, local tz),
computes each task's duration as (next task start - this task start),
and rewrites the `## Activity log` section in /data/cameron/life/brandon/daily/YYYY-MM-DD.md.

Safe to call on every nudge — fully idempotent. If a nudge was missed and later
backfilled into now_log, the next rebuild self-heals everything.

CLI:
    python3 glasses_activity_rebuild.py              # rebuild for today (local)
    python3 glasses_activity_rebuild.py 2026-06-16   # rebuild for a specific date
"""
import datetime as dt
import re
import sys
from pathlib import Path

NOW_LOG = Path("/data/cameron/agents_stuff/agents/glasses/now_log.md")
DAILY_DIR = Path("/data/cameron/life/brandon/daily")
SECTION_HEADER = "## Activity log (what Cameron actually did during the day)"


def parse_log():
    entries = []
    if not NOW_LOG.exists():
        return entries
    for raw in NOW_LOG.read_text().splitlines():
        line = raw.strip()
        if not line or "|" not in line:
            continue
        ts_str, _, task = line.partition("|")
        ts_str = ts_str.strip()
        task = task.strip()
        if not ts_str or not task:
            continue
        try:
            ts = dt.datetime.fromisoformat(ts_str)
        except ValueError:
            continue
        entries.append((ts, task))
    entries.sort(key=lambda e: e[0])
    return entries


def filter_date(entries, target_date):
    return [(ts, task) for (ts, task) in entries if ts.astimezone().date() == target_date]


def format_duration(delta):
    secs = int(delta.total_seconds())
    if secs < 60:
        return f"{secs}s"
    mins = secs // 60
    if mins < 60:
        return f"{mins}m"
    hours, rem = divmod(mins, 60)
    return f"{hours}h{rem:02d}m"


def render_lines(entries):
    lines = []
    for i, (ts, task) in enumerate(entries):
        local = ts.astimezone()
        clock = local.strftime("%H:%M")
        if i + 1 < len(entries):
            dur = format_duration(entries[i + 1][0] - ts)
        else:
            dur = "ongoing"
        lines.append(f"- {clock} ({dur}) — {task}")
    return lines


def rewrite_section(date_str, lines):
    daily_file = DAILY_DIR / f"{date_str}.md"
    new_block = SECTION_HEADER + "\n" + "\n".join(lines) + "\n"

    if not daily_file.exists():
        DAILY_DIR.mkdir(parents=True, exist_ok=True)
        weekday = dt.datetime.fromisoformat(date_str).strftime("%a")
        header = f"# {date_str} ({weekday}) — Brandon Program Daily Log\n\n"
        daily_file.write_text(header + new_block)
        daily_file.chmod(0o600)
        return daily_file

    content = daily_file.read_text()
    pattern = re.compile(
        r"^" + re.escape(SECTION_HEADER) + r"\n(?:(?!^## |^---$)[^\n]*\n?)*",
        re.MULTILINE,
    )
    if pattern.search(content):
        content = pattern.sub(new_block, content)
    else:
        if not content.endswith("\n"):
            content += "\n"
        content += "\n" + new_block
    daily_file.write_text(content)
    daily_file.chmod(0o600)
    return daily_file


def main():
    if len(sys.argv) > 1:
        target_date = dt.date.fromisoformat(sys.argv[1])
    else:
        target_date = dt.datetime.now().astimezone().date()

    entries = filter_date(parse_log(), target_date)
    lines = render_lines(entries) if entries else ["_no NOW-task entries logged yet_"]
    daily_file = rewrite_section(target_date.isoformat(), lines)

    print(f"rebuilt {daily_file} from {len(entries)} entries for {target_date}")


if __name__ == "__main__":
    main()
