#!/usr/bin/env python3
"""Inject the ARRFLIX middle-theme v6 (logo center, Movies/Series left, search right)
into a Jellyfin web overlay's index.html. Idempotent — run repeatedly without drift.

Markers:
  /* ARRFLIX-MIDDLE-THEME-BEGIN */ ... /* ARRFLIX-MIDDLE-THEME-END */    inside <style> and <script>
  <!--ARRFLIX-FAVICON-BEGIN-->     ... <!--ARRFLIX-FAVICON-END-->        between <link> tags

Usage:
  python3 bin/inject-middle-theme.py [target.html]
  ARRFLIX_OVERLAY_PATH=/opt/docker/jellyfin/web-overrides/index.html python3 bin/inject-middle-theme.py

Default target: <repo_root>/web-overrides/index.html
Assets read from <repo_root>/web-overrides/assets/:
  - arrflix-A.b64           favicon base64 (no data: prefix)
  - arrflix-wordmark.b64-url center-logo data-URL (with data: prefix)

Doc 29 covers the design, the auth gate, and the video-page hide rule.
"""
import os, re, sys, pathlib, time

ROOT = pathlib.Path(__file__).resolve().parent.parent
DEFAULT_TARGET = ROOT / "web-overrides" / "index.html"
ASSETS = ROOT / "web-overrides" / "assets"

target = pathlib.Path(sys.argv[1]) if len(sys.argv) > 1 else pathlib.Path(os.environ.get("ARRFLIX_OVERLAY_PATH", DEFAULT_TARGET))
if not target.exists():
    sys.exit(f"target overlay not found: {target}")

logo_a_b64 = (ASSETS / "arrflix-A.b64").read_text(encoding="utf-8").strip()
wordmark_url = (ASSETS / "arrflix-wordmark.b64-url").read_text(encoding="utf-8").strip()

START = "/* ARRFLIX-MIDDLE-THEME-BEGIN */"
END = "/* ARRFLIX-MIDDLE-THEME-END */"

CSS = (
    "body.arrflix-themed .skinHeader .headerTop{display:flex!important;align-items:center;position:relative;min-height:48px}\n"
    "body.arrflix-themed .skinHeader .headerLeft,body.arrflix-themed .skinHeader .headerRight{flex:1 1 0;display:flex;align-items:center}\n"
    "body.arrflix-themed .skinHeader .headerLeft{justify-content:flex-start;gap:.4em}\n"
    "body.arrflix-themed .skinHeader .headerRight{justify-content:flex-end}\n"
    "body.arrflix-themed .skinHeader .headerHomeButton,body.arrflix-themed .skinHeader .pageTitleWithLogo{display:none!important}\n"
    "body.arrflix-themed .skinHeader .headerLeft > h3.pageTitle:not(.pageTitleWithLogo){display:none!important}\n"
    "body.arrflix-themed .skinHeader .headerCastButton,body.arrflix-themed .skinHeader .headerSyncButton{display:none!important}\n"
    "body.arrflix-themed .headerTabs.sectionTabs{display:none!important}\n"
    "/* Hide entire header during video playback */\n"
    "body.arrflix-video-active:not(:has(#loginPage:not(.hide))) .skinHeader,body.arrflix-video-active .arrflix-headerLogo,body.arrflix-video-active .arrflix-nav{display:none!important}\n"
    ".arrflix-headerLogo{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:120px;height:38px;"
    "background:center/contain no-repeat url('" + wordmark_url + "');"
    "z-index:1;display:block;text-indent:-9999px;overflow:hidden}\n"
    ".arrflix-headerLogo:hover{filter:brightness(1.15)}\n"
    ".arrflix-nav{text-transform:uppercase;letter-spacing:.08em;font-weight:600;padding:0 .9em;color:#fff!important;text-decoration:none;display:inline-flex;align-items:center;height:100%;font-size:.85em}\n"
    ".arrflix-nav:hover{color:#E50914!important}\n"
)

JS = """
(function(){
  function isVideoPage(){
    try{
      var h=(location.hash||'').toLowerCase();
      if (h.indexOf('/video') !== -1) return true;
      var osd = document.querySelector('#videoOsdPage:not(.hide)');
      if (osd) return true;
      var v = document.querySelector('.htmlVideoPlayer:not(.hide), video.htmlvideoplayer:not(.hide)');
      if (v && getComputedStyle(v).display !== 'none') return true;
    }catch(e){}
    return false;
  }
  function isAuthed(){
    try{
      if (document.querySelector('.pageContainer.loginPage:not(.hide)')) return false;
      if (document.querySelector('#loginPage:not(.hide)')) return false;
      var h = (location.hash || '').toLowerCase();
      if (h.indexOf('/login') !== -1 || h.indexOf('/wizard') !== -1 || h.indexOf('/forgotpassword') !== -1 || h.indexOf('/selectserver') !== -1) return false;
      if (window.ApiClient && typeof window.ApiClient.isLoggedIn === 'function' && !window.ApiClient.isLoggedIn()) return false;
      var raw = localStorage.getItem('jellyfin_credentials');
      if (!raw) return false;
      var creds = JSON.parse(raw);
      if (!creds || !creds.Servers || !creds.Servers.length || !creds.Servers[0].AccessToken) return false;
      return true;
    } catch(e){ return false; }
  }
  function teardown(){
    document.body.classList.remove('arrflix-themed');
    var top = document.querySelector('.skinHeader .headerTop'); if (!top) return;
    var logo = top.querySelector('.arrflix-headerLogo'); if (logo) logo.remove();
    Array.prototype.forEach.call(document.querySelectorAll('.arrflix-nav'), function(n){ n.remove(); });
  }
  function relayoutHeader(){
    document.body.classList.toggle('arrflix-video-active', isVideoPage());
    if (!isAuthed()) { teardown(); return; }
    var top=document.querySelector('.skinHeader .headerTop'); if(!top) return;
    document.body.classList.add('arrflix-themed');
    var left=top.querySelector('.headerLeft');
    if(left && !left.querySelector('[data-arrflix-nav=\"movies\"]')){
      left.insertAdjacentHTML('beforeend',
        '<a is=\"emby-linkbutton\" class=\"emby-button arrflix-nav\" data-arrflix-nav=\"movies\" href=\"#/movies.html\">Movies</a>'+
        '<a is=\"emby-linkbutton\" class=\"emby-button arrflix-nav\" data-arrflix-nav=\"series\" href=\"#/tv.html\">Series</a>'
      );
    }
    if(!top.querySelector('.arrflix-headerLogo')){
      var a=document.createElement('a');
      a.className='arrflix-headerLogo';
      a.href='#/home.html';
      a.setAttribute('aria-label','ARRFLIX home');
      a.textContent='ARRFLIX';
      var right=top.querySelector('.headerRight');
      top.insertBefore(a, right || null);
    }
  }
  function start(){
    relayoutHeader();
    try{ new MutationObserver(relayoutHeader).observe(document.body,{childList:true,subtree:true}); }catch(e){}
    window.addEventListener('hashchange', relayoutHeader);
    setInterval(relayoutHeader,1500);
  }
  if(document.readyState==='loading') document.addEventListener('DOMContentLoaded',start,{once:true}); else start();
})();
"""

FAVICON_LINKS = (
    "<!--ARRFLIX-FAVICON-BEGIN-->"
    "<link rel=\"icon\" type=\"image/png\" sizes=\"180x180\" data-arrflix-icon=\"A\" href=\"data:image/png;base64," + logo_a_b64 + "\">"
    "<link rel=\"apple-touch-icon\" sizes=\"180x180\" data-arrflix-icon=\"A\" href=\"data:image/png;base64," + logo_a_b64 + "\">"
    "<!--ARRFLIX-FAVICON-END-->"
)
FAVICON_HIJACK_JS = (
    "<script>/* ARRFLIX-FAVICON-HIJACK-BEGIN */"
    "(function(){"
    "var A_URL='data:image/png;base64," + logo_a_b64 + "';"
    "function pin(){"
    "Array.prototype.forEach.call(document.querySelectorAll('link[rel=\"shortcut icon\"], link[rel=\"icon\"], link[rel=\"apple-touch-icon\"]'),function(l){"
    "if(l.getAttribute('data-arrflix-icon')==='A')return;"
    "if((l.href||'').indexOf('data:image/png')!==-1 && l.href.length>200 && l.getAttribute('data-arrflix-icon')!=='A'){l.parentNode&&l.parentNode.removeChild(l);}"
    "});"
    "Array.prototype.forEach.call(document.querySelectorAll('link[data-arrflix-icon=\"A\"]'),function(l){if(l.href!==A_URL) l.href=A_URL;});"
    "}"
    "function start(){pin();try{new MutationObserver(pin).observe(document.head||document.documentElement,{childList:true,subtree:true,attributes:true,attributeFilter:['href']});}catch(e){}setInterval(pin,1000);}"
    "if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',start,{once:true});else start();"
    "})();"
    "/* ARRFLIX-FAVICON-HIJACK-END */</script>"
)

src = target.read_text(encoding="utf-8")
src = re.sub(re.escape("<style>" + START) + r".*?" + re.escape(END + "</style>"), "", src, flags=re.DOTALL)
src = re.sub(re.escape("<script>" + START) + r".*?" + re.escape(END + "</script>"), "", src, flags=re.DOTALL)
src = re.sub(r"<!--ARRFLIX-FAVICON-BEGIN-->.*?<!--ARRFLIX-FAVICON-END-->", "", src, flags=re.DOTALL)
src = re.sub(r"<script>/\* ARRFLIX-FAVICON-HIJACK-BEGIN \*/.*?/\* ARRFLIX-FAVICON-HIJACK-END \*/</script>", "", src, flags=re.DOTALL)

PATCH = "<style>" + START + CSS + END + "</style>" + "<script>" + START + JS + END + "</script>" + FAVICON_LINKS + FAVICON_HIJACK_JS
if "</head>" not in src:
    sys.exit("no </head> in target")
src2 = src.replace("</head>", PATCH + "</head>", 1)

backup = target.with_suffix(target.suffix + f".bak.pre-middle-v6.{int(time.time())}")
backup.write_text(target.read_text(encoding="utf-8"), encoding="utf-8")
target.write_text(src2, encoding="utf-8")
print(f"OK v6 wrote {len(src2)} bytes to {target}; backup at {backup}")
