#!/usr/bin/env python3
"""
Patch Jellyfin home-screen section layout for every user on a given instance.

Default policy (this script):
  - Continue Watching (`resume`)          ENABLED for every user
  - Resume Audio       (`resumeaudio`)    preserved if present
  - Next Up            (`nextup`)         DISABLED (replaced with `none`)
  - Latest Media       (`latestmedia`)    preserved if present
  - If a user's layout was empty (factory default), seed slot 0 with `resume`

Idempotent. Safe to re-run.

Usage:
    JF_URL=https://arrflix.s8n.ru \
    JF_TOKEN=<admin token> \
    python3 bin/set-home-layout.py

Token retrieval (admin):
    docker cp jellyfin:/config/data/jellyfin.db /tmp/jf.db
    sqlite3 /tmp/jf.db \\
      'SELECT d.AccessToken FROM Devices d JOIN Users u ON d.UserId=u.Id
       WHERE u.Username="s8n" ORDER BY d.DateLastActivity DESC LIMIT 1'
"""
import json
import os
import sys
import urllib.parse
import urllib.request

JF_URL = os.environ.get("JF_URL")
JF_TOKEN = os.environ.get("JF_TOKEN")

if not JF_URL or not JF_TOKEN:
    sys.exit("set JF_URL and JF_TOKEN env vars")

# Jellyfin 10.10.3 web client uses 'Jellyfin Web' as the DisplayPreferences
# client name. The older 'emby' name is read by legacy SDKs only — writing
# only to 'emby' has no effect on the web UI. Patch every per-client doc to
# keep all consumers in sync.
CLIENTS = ["Jellyfin Web", "emby", "emby-mobile", "emby-web"]


def http(method, url, body=None):
    req = urllib.request.Request(url, method=method)
    req.add_header("X-Emby-Token", JF_TOKEN)
    data = None
    if body is not None:
        req.add_header("Content-Type", "application/json")
        data = json.dumps(body).encode()
    with urllib.request.urlopen(req, data=data) as r:
        text = r.read().decode()
        return r.status, (json.loads(text) if text else None)


def patch_user_client(user_id, client):
    q = urllib.parse.urlencode({"userId": user_id, "client": client})
    url = f"{JF_URL}/DisplayPreferences/usersettings?{q}"
    _, prefs = http("GET", url)
    cp = prefs.get("CustomPrefs") or {}

    sections = [cp.get(f"homesection{i}", "none") for i in range(10)]
    before = list(sections)

    sections = ["none" if s == "nextup" else s for s in sections]
    if "resume" not in sections:
        if "none" in sections:
            sections[sections.index("none")] = "resume"
        else:
            sections = ["resume"] + sections[:9]
    if "latestmedia" not in sections:
        for i, s in enumerate(sections):
            if s == "none":
                sections[i] = "latestmedia"
                break

    for i, s in enumerate(sections):
        cp[f"homesection{i}"] = s
    prefs["CustomPrefs"] = cp

    changed = before != sections
    if changed:
        http("POST", url, body=prefs)
    return changed, before, sections


def main():
    users = http("GET", f"{JF_URL}/Users")[1]
    print(f"{JF_URL} — {len(users)} users")
    for u in users:
        for client in CLIENTS:
            changed, before, after = patch_user_client(u["Id"], client)
            if changed:
                print(f"  [CHANGED] {u['Name']:<14} client={client:<14}  {before} -> {after}")
            else:
                print(f"  [  ok   ] {u['Name']:<14} client={client:<14}  {after}")


if __name__ == "__main__":
    main()
