#!/usr/bin/env python3
"""Embed cover images into EPUB files that have no cover or a wrong cover.

Adapt the COVERS dict at the bottom for each batch.
Before running: sudo chown az-a:samba on the target EPUB directories.

Google Books cover URLs:
  https://books.google.com/books/content?id=BOOKID&printsec=frontcover&img=1&zoom=2
  zoom=1 → 128×170 (too small), zoom=2 → 575×750 (good)

Run as: python3 embed_cover.py
Requires: pymupdf not needed — pure Python zipfile + ElementTree.
"""
import zipfile, os, xml.etree.ElementTree as ET

BOOKS_DIR = "/media/HDD_1TB/Medien/Bücher"

NS = {
    "opf": "http://www.idpf.org/2007/opf",
    "dc": "http://purl.org/dc/elements/1.1/",
}
for prefix, uri in NS.items():
    ET.register_namespace(prefix, uri)

def embed_cover(epub_path, cover_file_path, cover_internal_name="cover.jpg", image_mime="image/jpeg"):
    """Add or replace cover image in an EPUB."""
    tmp_path = epub_path + ".tmp"
    
    with open(cover_file_path, 'rb') as cf:
        cover_data = cf.read()
    
    with zipfile.ZipFile(epub_path, 'r') as zin:
        container = ET.fromstring(zin.read("META-INF/container.xml").decode("utf-8"))
        opf_path = container.find(
            ".//{urn:oasis:names:tc:opendocument:xmlns:container}rootfile"
        ).get("full-path")
        opf_dir = os.path.dirname(opf_path)
        
        opf_root = ET.fromstring(zin.read(opf_path).decode("utf-8"))
        manifest = opf_root.find(f"{{{NS['opf']}}}manifest")
        metadata = opf_root.find(f"{{{NS['opf']}}}metadata")
        
        # Remove existing cover if present
        old_cover_id = None
        for item in list(manifest.findall(f"{{{NS['opf']}}}item")):
            if "cover-image" in (item.get("properties") or ""):
                old_cover_id = item.get("id")
                manifest.remove(item)
        for meta in list(metadata.findall(f"{{{NS['opf']}}}meta")):
            if meta.get("name") == "cover":
                metadata.remove(meta)
                break
        
        cover_href = cover_internal_name
        if opf_dir and opf_dir != ".":
            cover_href = f"{opf_dir}/{cover_internal_name}"
        
        # Add new cover
        cover_id = "cover-image"
        ET.SubElement(manifest, f"{{{NS['opf']}}}item", {
            "id": cover_id,
            "href": cover_href,
            "media-type": image_mime,
            "properties": "cover-image"
        })
        ET.SubElement(metadata, f"{{{NS['opf']}}}meta", {
            "name": "cover", "content": cover_id
        })
        
        new_opf = ET.tostring(opf_root, encoding="utf-8", xml_declaration=True)
        
        full_cover_path = cover_internal_name
        if opf_dir and opf_dir != ".":
            full_cover_path = f"{opf_dir}/{cover_internal_name}"
        
        with zipfile.ZipFile(tmp_path, 'w', zipfile.ZIP_DEFLATED) as zout:
            for item in zin.infolist():
                zout.writestr(item, zin.read(item.filename))
            zout.writestr(full_cover_path, cover_data)
    
    os.replace(tmp_path, epub_path)
    print(f"  DONE: {os.path.basename(epub_path)} ({len(cover_data)} bytes, {old_cover_id and 'replaced' or 'new'})")
    return True

# === CONFIGURE COVERS BELOW ===
COVERS = {
    # f"{BOOKS_DIR}/Author/Book.epub": {
    #     "cover_file": "/tmp/cover_image.jpg",
    #     "cover_internal": "cover.jpg",
    #     "image_mime": "image/jpeg"
    # },
}

for epub_path, cfg in COVERS.items():
    try:
        embed_cover(epub_path, cfg["cover_file"], cfg.get("cover_internal", "cover.jpg"), cfg.get("image_mime", "image/jpeg"))
    except Exception as e:
        print(f"  ERROR: {os.path.basename(epub_path)} - {e}")
