import argparse
import json
import re
import sys
from datetime import datetime
from pathlib import Path

sys.path.insert(0, "/home/.z/google-oauth")
from google_auth import get_credentials
from googleapiclient.discovery import build

TEMPLATE_PRESENTATION_ID = "1iKqcIyyAI5sfP0pCxyMp32Ar646M2vdFmQWsAss0kBA"
TITLE_LAYOUT_NAMES = {"Title slide", "TITLE_SLIDE", "TITLE"}
BODY_LAYOUT_NAMES = {"Title and body", "One column text", "TITLE_AND_BODY"}


def normalize_name(name: str) -> str:
    return re.sub(r"[^a-z0-9]+", " ", (name or "").lower()).strip()


def parse_args():
    p = argparse.ArgumentParser(description="Create a Google Slides deck in Rob's account using the ClawCon template theme.")
    p.add_argument("--input", required=True, help="Path to a JSON file with deck spec")
    p.add_argument("--title", help="Override deck title")
    p.add_argument("--template-id", default=TEMPLATE_PRESENTATION_ID, help="Google Slides presentation ID to use as theme/template source")
    p.add_argument("--dump-template-layouts", action="store_true", help="Print available layouts from the template and exit")
    return p.parse_args()


def load_spec(path: str):
    data = json.loads(Path(path).read_text())
    if not isinstance(data, dict):
        raise ValueError("Deck spec must be a JSON object")
    slides = data.get("slides")
    if not isinstance(slides, list) or not slides:
        raise ValueError("Deck spec must include a non-empty slides array")
    return data


def get_services():
    creds = get_credentials()
    return build("drive", "v3", credentials=creds), build("slides", "v1", credentials=creds)


def get_layouts(slides_api, presentation_id):
    pres = slides_api.presentations().get(presentationId=presentation_id).execute()
    layouts = {}
    for layout in pres.get("layouts", []):
        props = layout.get("layoutProperties", {})
        raw = props.get("displayName") or props.get("name") or ""
        layouts[normalize_name(raw)] = layout["objectId"]
    return layouts, pres


def find_layout_id(layouts, candidates):
    for candidate in candidates:
        lid = layouts.get(normalize_name(candidate))
        if lid:
            return lid
    return None


def placeholder_ids(slide):
    title_id = None
    body_id = None
    subtitle_id = None
    fallback = None
    for el in slide.get("pageElements", []):
        shape = el.get("shape")
        if not shape:
            continue
        oid = el.get("objectId")
        fallback = fallback or oid
        ph = shape.get("placeholder", {})
        pht = ph.get("type")
        if pht in {"TITLE", "CENTERED_TITLE"} and not title_id:
            title_id = oid
        elif pht == "SUBTITLE" and not subtitle_id:
            subtitle_id = oid
        elif pht == "BODY" and not body_id:
            body_id = oid
    return title_id, body_id, subtitle_id, fallback


def copy_template_deck(drive, template_id, title):
    copied = drive.files().copy(fileId=template_id, body={"name": title}).execute()
    return copied["id"]


def clear_existing_slides(slides_api, pres_id):
    pres = slides_api.presentations().get(presentationId=pres_id).execute()
    delete_reqs = [{"deleteObject": {"objectId": s["objectId"]}} for s in pres.get("slides", [])]
    if delete_reqs:
        slides_api.presentations().batchUpdate(presentationId=pres_id, body={"requests": delete_reqs}).execute()


def create_slides(slides_api, pres_id, title_layout_id, body_layout_id, slides):
    create_reqs = []
    for idx, slide in enumerate(slides, 1):
        layout_id = title_layout_id if slide.get("layout") == "title" else body_layout_id
        req = {"objectId": f"slide_{idx:03d}"}
        if layout_id:
            req["slideLayoutReference"] = {"layoutId": layout_id}
        create_reqs.append({"createSlide": req})
    slides_api.presentations().batchUpdate(presentationId=pres_id, body={"requests": create_reqs}).execute()


def write_content(slides_api, pres_id, slides):
    pres = slides_api.presentations().get(presentationId=pres_id).execute()
    text_reqs = []
    for idx, slide in enumerate(pres.get("slides", [])):
        content = slides[idx]
        title_id, body_id, subtitle_id, fallback = placeholder_ids(slide)
        title = content.get("title", "")
        body = content.get("body", "")
        subtitle = content.get("subtitle")
        bullets = content.get("bullets")
        if bullets and not body:
            body = "\n".join(f"• {x}" for x in bullets)

        if title:
            target = title_id or fallback
            if target:
                text_reqs.append({"insertText": {"objectId": target, "insertionIndex": 0, "text": title}})

        if subtitle:
            target = subtitle_id or body_id or fallback
            if target:
                text_reqs.append({"insertText": {"objectId": target, "insertionIndex": 0, "text": subtitle}})
        elif body:
            target = body_id or subtitle_id or fallback
            if target:
                if target == (title_id or fallback) and title:
                    text_reqs.append({"insertText": {"objectId": target, "insertionIndex": len(title), "text": "\n\n" + body}})
                else:
                    text_reqs.append({"insertText": {"objectId": target, "insertionIndex": 0, "text": body}})

    if text_reqs:
        slides_api.presentations().batchUpdate(presentationId=pres_id, body={"requests": text_reqs}).execute()


def main():
    args = parse_args()
    spec = load_spec(args.input)
    title = args.title or spec.get("title") or f"Untitled Deck ({datetime.now().strftime('%Y-%m-%d %H:%M')})"

    drive, slides_api = get_services()
    layouts, _ = get_layouts(slides_api, args.template_id)

    if args.dump_template_layouts:
        print(json.dumps(sorted(layouts.keys()), indent=2))
        return

    title_layout_id = find_layout_id(layouts, TITLE_LAYOUT_NAMES)
    body_layout_id = find_layout_id(layouts, BODY_LAYOUT_NAMES)
    if not title_layout_id or not body_layout_id:
        raise RuntimeError("Could not find title/body layouts in template")

    pres_id = copy_template_deck(drive, args.template_id, title)
    clear_existing_slides(slides_api, pres_id)
    create_slides(slides_api, pres_id, title_layout_id, body_layout_id, spec["slides"])
    write_content(slides_api, pres_id, spec["slides"])

    pres = slides_api.presentations().get(presentationId=pres_id).execute()
    image_counts = [sum(1 for el in s.get("pageElements", []) if "image" in el) for s in pres.get("slides", [])]
    print(json.dumps({
        "presentation_id": pres_id,
        "url": f"https://docs.google.com/presentation/d/{pres_id}/edit",
        "title": title,
        "slide_count": len(pres.get("slides", [])),
        "images_per_slide": image_counts,
        "template_id": args.template_id,
    }, indent=2))


if __name__ == "__main__":
    main()
