#!/usr/bin/env python3
"""Tiny server for the voice recorder: serves recorder.html + accepts the WAV upload.
POST /upload  (Content-Type: audio/wav, X-Filename header)  ->  saves to uploads/<name>.
Run: python3 voice_recorder/serve.py   (port 8777)  — expose via cloudflared for the phone."""
import http.server, socketserver, os, json, re
from pathlib import Path
DIR = Path(__file__).resolve().parent
UP = DIR / "uploads"; UP.mkdir(exist_ok=True)
# scripts live at ../broll_lab/videos on the Mac (repo layout) or ./broll_lab/videos on the VPS
VIDEOS = next((p for p in (DIR.parent / "broll_lab" / "videos", DIR / "broll_lab" / "videos") if p.exists()),
              DIR / "broll_lab" / "videos")
PORT = 8777

def projects():
    """Auto-discover every Day folder that has a VO script — Day 4, 5… appear automatically."""
    out = []
    for d in sorted(VIDEOS.glob("*/01 SCRIPT (voiceover).txt")):
        folder = d.parent.name                      # e.g. "Day 2 - India vs China (Cardboard)"
        m = re.match(r"Day (\d+)", folder)
        num = int(m.group(1)) if m else 0
        raw = d.read_text()
        script = raw.split("---", 1)[1].strip() if "---" in raw else raw.strip()
        title = re.sub(r"\s*\(Cardboard\)\s*$", "", folder)
        out.append({"id": f"day{num}", "num": num, "title": title,
                    "words": len(script.split()), "script": script})
    return sorted(out, key=lambda p: -p["num"])    # newest Day first

class H(http.server.SimpleHTTPRequestHandler):
    def __init__(self, *a, **k):
        super().__init__(*a, directory=str(DIR), **k)
    def end_headers(self):
        # PWAs cache the shell hard — force revalidation so deploys reach the phone immediately
        self.send_header("Cache-Control", "no-store, must-revalidate")
        super().end_headers()
    def _cors(self):
        self.send_header("Access-Control-Allow-Origin", "*")
        self.send_header("Access-Control-Allow-Headers", "Content-Type,X-Filename")
        self.send_header("Access-Control-Allow-Methods", "POST,GET,OPTIONS")
    def do_OPTIONS(self):
        self.send_response(200); self._cors(); self.end_headers()
    def do_GET(self):
        if self.path.split("?")[0] == "/projects":
            body = json.dumps(projects()).encode()
            self.send_response(200); self._cors()
            self.send_header("Content-Type", "application/json")
            self.send_header("Content-Length", str(len(body)))
            self.end_headers(); self.wfile.write(body)
        else:
            super().do_GET()
    def do_POST(self):
        if self.path.split("?")[0] == "/upload":
            name = os.path.basename(self.headers.get("X-Filename", "voice.wav")) or "voice.wav"
            # Takes are append-only: dayN_vo_full.wav -> dayN_vo-real_take-01.wav, -02, -03…
            # Rahman sends as many styles as he likes; the editor picks; nothing is overwritten.
            stem = re.sub(r"\.wav$", "", name, flags=re.I)
            stem = re.sub(r"_vo_full$", "", stem) + "_vo-real"
            # count EVERY take ever seen (incl. ingested/processed archives) so
            # numbers keep climbing after the Mac pulls files away — never reuse a number
            seen = [int(m.group(1)) for p in UP.rglob(f"{stem}_take-*.wav")
                    if (m := re.search(r"_take-(\d+)\.wav$", p.name))]
            fname = f"{stem}_take-{max(seen, default=0) + 1:02d}.wav"
            n = int(self.headers.get("Content-Length", 0))
            data = self.rfile.read(n)
            (UP / fname).write_bytes(data)
            print(f"UPLOAD: {fname}  ({len(data)} bytes)", flush=True)
            body = fname.encode()
            self.send_response(200); self._cors()
            self.send_header("Content-Length", str(len(body)))
            self.end_headers(); self.wfile.write(body)
        else:
            self.send_response(404); self.end_headers()

socketserver.TCPServer.allow_reuse_address = True
print(f"serving {DIR} on :{PORT}  (uploads -> {UP})", flush=True)
socketserver.TCPServer(("", PORT), H).serve_forever()
