from __future__ import annotations

from pathlib import Path
import re

from bs4 import BeautifulSoup
from google.oauth2 import service_account
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

ROOT = Path(__file__).resolve().parents[1]
CREDENTIALS = ROOT / "pythonyoubeupload-5e32167f1c2c.json"
SOURCE_DOC_ID = "1pMGQKWarc07-JaVlkYcgF9FZb2hgXPZi02kIX4k5It4"
HTML_FILE = ROOT / "html-workspace" / "rujukan" / "bab-02-template-rujukan.html"
NEW_TITLE = "Template Rujukan BAB 2 - Gambaran Umum dan Analisis Situasi Eksternal"

SCOPES = [
    "https://www.googleapis.com/auth/documents",
    "https://www.googleapis.com/auth/drive",
]


def normalize(text: str) -> str:
    return re.sub(r"\s+", " ", text).strip()


def parse_template():
    soup = BeautifulSoup(HTML_FILE.read_text(encoding="utf-8"), "lxml")
    elements = []
    for tag in soup.select("main.page h1, main.page h2, main.page h3, main.page h4, main.page h5, main.page .note"):
        text = normalize(tag.get_text(" "))
        if not text:
            continue
        if "Catatan:" in text:
            continue
        name = tag.name.lower()
        if name == "h1":
            text = text.replace("BAB 2 Gambaran", "BAB 2\nGambaran")
            style = "TITLE"
        elif name == "h2":
            style = "HEADING_1"
        elif name == "h3":
            style = "HEADING_2"
        elif name == "h4":
            style = "HEADING_3"
        elif name == "h5":
            style = "NORMAL_TEXT"
        else:
            style = "NORMAL_TEXT"
        elements.append((text, style))
    return elements


def main():
    creds = service_account.Credentials.from_service_account_file(CREDENTIALS, scopes=SCOPES)
    drive = build("drive", "v3", credentials=creds)
    docs = build("docs", "v1", credentials=creds)

    # Prefer copying the reference document so the new document inherits its Google Docs theme/styles.
    # If the owner's Drive quota blocks copying, create a blank Docs file owned by the service account
    # and apply matching A4/heading styles through the Docs API.
    try:
        copied = drive.files().copy(
            fileId=SOURCE_DOC_ID,
            body={"name": NEW_TITLE},
            fields="id, name, webViewLink",
            supportsAllDrives=True,
        ).execute()
        new_doc_id = copied["id"]
        created_name = copied["name"]
    except HttpError as exc:
        if exc.resp.status != 403 or "storageQuotaExceeded" not in str(exc):
            raise
        created = docs.documents().create(body={"title": NEW_TITLE}).execute()
        new_doc_id = created["documentId"]
        created_name = NEW_TITLE

    doc = docs.documents().get(documentId=new_doc_id).execute()
    end_index = doc["body"]["content"][-1]["endIndex"]
    requests = []
    if end_index > 2:
        requests.append({"deleteContentRange": {"range": {"startIndex": 1, "endIndex": end_index - 1}}})

    elements = parse_template()
    full_text = "\n\n".join(text for text, _style in elements) + "\n"
    requests.append({"insertText": {"location": {"index": 1}, "text": full_text}})

    cursor = 1
    for text, style in elements:
        start = cursor
        end = cursor + len(text)
        if style != "NORMAL_TEXT":
            requests.append({
                "updateParagraphStyle": {
                    "range": {"startIndex": start, "endIndex": end},
                    "paragraphStyle": {"namedStyleType": style},
                    "fields": "namedStyleType",
                }
            })
        if style == "TITLE":
            requests.append({
                "updateParagraphStyle": {
                    "range": {"startIndex": start, "endIndex": end},
                    "paragraphStyle": {"alignment": "CENTER"},
                    "fields": "alignment",
                }
            })
        cursor = end + 2

    # A4-like page setup and common report margins.
    requests.append({
        "updateDocumentStyle": {
            "documentStyle": {
                "pageSize": {
                    "width": {"magnitude": 595.28, "unit": "PT"},
                    "height": {"magnitude": 841.89, "unit": "PT"},
                },
                "marginTop": {"magnitude": 72, "unit": "PT"},
                "marginBottom": {"magnitude": 72, "unit": "PT"},
                "marginLeft": {"magnitude": 72, "unit": "PT"},
                "marginRight": {"magnitude": 72, "unit": "PT"},
            },
            "fields": "pageSize,marginTop,marginBottom,marginLeft,marginRight",
        }
    })

    docs.documents().batchUpdate(documentId=new_doc_id, body={"requests": requests}).execute()

    try:
        drive.permissions().create(
            fileId=new_doc_id,
            body={"type": "anyone", "role": "writer"},
            fields="id",
            supportsAllDrives=True,
        ).execute()
    except HttpError:
        drive.permissions().create(
            fileId=new_doc_id,
            body={"type": "anyone", "role": "reader"},
            fields="id",
            supportsAllDrives=True,
        ).execute()

    print(f"Created: {created_name}")
    print(f"Document ID: {new_doc_id}")
    print(f"Link: https://docs.google.com/document/d/{new_doc_id}/edit")


if __name__ == "__main__":
    main()
