"""
glance.py: helpers shared by video_episode.py and article_episode.py.

Both turn a source into an MP3 whose ID3 chapters each carry an image, so a
podcast app that shows chapter artwork (e.g. Overcast) becomes a slow
slideshow you can glance at while you listen. Imported, not run directly;
the importing script's uv header supplies the dependencies (mutagen).
"""

import re
import subprocess
import sys
from pathlib import Path

CACHE = Path.home() / "Library" / "Caches" / "glanceable-podcast"

# 945px is the largest chapter art the iPhone shows (per Alex Chan's write-up).
MAX_SIZE = 945

# Correct for non-square pixels, then fit within max_size x max_size.
SCALE = r"scale=iw*sar:ih,scale=min(iw\,{s}):min(ih\,{s}):force_original_aspect_ratio=decrease"


def fail(msg):
  print(f"error: {msg}", file=sys.stderr)
  sys.exit(1)


def run(cmd):
  """Run a command, exiting with the tail of its stderr if it fails."""
  proc = subprocess.run(cmd, capture_output=True, text=True)
  if proc.returncode != 0:
    tail = "\n".join(proc.stderr.strip().splitlines()[-15:])
    fail(f"{Path(cmd[0]).name} failed:\n{tail}")
  return proc


def fmt_ts(seconds):
  h, rem = divmod(int(seconds), 3600)
  m, s = divmod(rem, 60)
  return f"{h}:{m:02}:{s:02}" if h else f"{m}:{s:02}"


def slugify(text, fallback="episode"):
  return re.sub(r"[^a-z0-9]+", "-", text.lower()).strip("-")[:60] or fallback


def duration_ms(path):
  out = run(["ffprobe", "-v", "error", "-show_entries", "format=duration",
             "-of", "default=nw=1:nk=1", str(path)]).stdout
  return int(float(out.strip()) * 1000)


def write_tags(mp3, chapters, total_ms, cover, meta):
  """Write episode tags plus one CHAP frame per image.

  chapters is [(start_seconds, jpg_path), ...] in time order; each image is
  shown until the next one starts. No CTOC on purpose: a long list of short
  picture chapters would swamp a player's chapter list."""
  from mutagen.id3 import APIC, CHAP, ID3, TDRC, TIT2, TPE1, WOAS, PictureType

  tags = ID3()
  tags.add(TIT2(encoding=3, text=meta["title"]))
  if meta.get("author"):
    tags.add(TPE1(encoding=3, text=meta["author"]))
  if meta.get("original_date"):
    tags.add(TDRC(encoding=3, text=meta["original_date"]))
  if meta.get("link"):
    tags.add(WOAS(url=meta["link"]))
  tags.add(APIC(mime="image/jpeg", type=PictureType.COVER_FRONT, desc="Cover",
                data=Path(cover).read_bytes()))

  starts = [int(t * 1000) for t, _ in chapters]
  for i, (_, img) in enumerate(chapters):
    start = starts[i]
    end = starts[i + 1] if i + 1 < len(starts) else total_ms
    if start >= total_ms or end <= start:
      continue
    picture = APIC(mime="image/jpeg", type=PictureType.OTHER, data=Path(img).read_bytes())
    tags.add(CHAP(element_id=f"img{i + 1}", start_time=start, end_time=min(end, total_ms),
                  sub_frames=[picture]))
  tags.save(mp3)
