#!/usr/bin/env python3
from __future__ import annotations

import json
import re
from pathlib import Path

STREAM_ROOT = Path('/mnt/rpi/streaming')
WEB_ROOT = Path('/var/www/portal/streaming')
FILES_PREFIX = '/files/mnt/rpi/streaming'
VIDEO_EXTS = {'.mp4', '.mkv', '.webm', '.m4v'}
SUB_EXTS = {'.srt', '.vtt'}


def decode_text(path: Path) -> str:
    raw = path.read_bytes()
    if raw.startswith(b'\xff\xfe') or raw.startswith(b'\xfe\xff'):
        return raw.decode('utf-16')
    for enc in ('utf-8-sig', 'utf-8', 'latin-1'):
        try:
            return raw.decode(enc)
        except UnicodeDecodeError:
            pass
    return raw.decode('utf-8', errors='replace')


def srt_to_vtt(text: str) -> str:
    text = text.replace('\r\n', '\n').replace('\r', '\n').replace('\x00', '')
    text = re.sub(r'^(\d{2}:\d{2}:\d{2}),(\d{3})\s+-->\s+(\d{2}:\d{2}:\d{2}),(\d{3})$', r'\1.\2 --> \3.\4', text, flags=re.M)
    return 'WEBVTT\n\n' + text


def public_url(path: Path) -> str:
    rel = path.relative_to(STREAM_ROOT).as_posix()
    return f'{FILES_PREFIX}/{rel}'


def subtitle_for(video: Path) -> Path | None:
    stem = video.with_suffix('')
    candidates = [stem.with_suffix('.vtt'), stem.with_suffix('.srt')]
    for candidate in candidates:
        if candidate.exists():
            return candidate

    def norm(name: str) -> str:
        name = re.sub(r'_vol\d+x$', '', name, flags=re.I)
        name = re.sub(r'^[._-]+', '', name)
        return name.lower()

    wanted = norm(video.stem)
    for sibling in sorted(video.parent.iterdir()):
        if sibling.is_file() and sibling.suffix.lower() in SUB_EXTS and sibling != video:
            sibling_name = norm(sibling.stem)
            if sibling_name == wanted or sibling_name.startswith(wanted) or wanted.startswith(sibling_name):
                return sibling
    return None


def ensure_web_subtitle(sub: Path) -> str:
    if sub.suffix.lower() == '.vtt':
        return public_url(sub)
    rel = sub.relative_to(STREAM_ROOT)
    target = WEB_ROOT / 'subs' / rel.with_suffix('.vtt')
    target.parent.mkdir(parents=True, exist_ok=True)
    target.write_text(srt_to_vtt(decode_text(sub)), encoding='utf-8')
    return '/streaming/subs/' + rel.with_suffix('.vtt').as_posix()


def classify(path: Path) -> str:
    parts = path.relative_to(STREAM_ROOT).parts
    return parts[0] if parts else 'other'


def title_for(path: Path) -> str:
    return path.stem


def build_manifest() -> list[dict]:
    chosen = {}
    pref = {'.mp4': 0, '.webm': 1, '.m4v': 2, '.mkv': 3}
    for path in sorted(STREAM_ROOT.rglob('*')):
        if not path.is_file() or path.suffix.lower() not in VIDEO_EXTS:
            continue
        key = path.with_suffix('').relative_to(STREAM_ROOT).as_posix()
        prev = chosen.get(key)
        if prev is None or pref[path.suffix.lower()] < pref[prev.suffix.lower()]:
            chosen[key] = path

    items = []
    for path in sorted(chosen.values()):
        sub = subtitle_for(path)
        items.append({
            'title': title_for(path),
            'section': classify(path),
            'video': public_url(path),
            'subtitle': ensure_web_subtitle(sub) if sub else None,
            'hasSubtitle': bool(sub),
        })
    return items


def main() -> None:
    WEB_ROOT.mkdir(parents=True, exist_ok=True)
    (WEB_ROOT / 'subs').mkdir(parents=True, exist_ok=True)
    manifest = build_manifest()
    (WEB_ROOT / 'manifest.json').write_text(json.dumps(manifest, ensure_ascii=False, indent=2), encoding='utf-8')


if __name__ == '__main__':
    main()
