#!/usr/bin/env python3
"""scripts/attach_release_asset.py — upload one or more files as Gitea release
attachments.

REQ-228 (v1.18): PPTX (and any deck artifact) is attached to the phase's
Gitea release. Uses the Gitea API:
    POST /api/v1/repos/{owner}/{repo}/releases/{id}/assets
multipart form: name=<filename>, attachment=<file bytes>

REQ-270 (v1.23): supports dual PPTX attachment — the MARP PPTX (primary,
attached first) and the python-pptx PPTX (comparison artifact). Multiple
file paths are accepted; the first is the primary attachment.

Usage:
    python3 scripts/attach_release_asset.py <file-path> <release-id>
    python3 scripts/attach_release_asset.py <file-path> <file-path-2>... <release-id>
    python3 scripts/attach_release_asset.py docs/presentations/nova-autonomous-cloud-delivery.pptx 522
    python3 scripts/attach_release_asset.py \
        docs/presentations/nova-autonomous-cloud-delivery.pptx \
        docs/presentations/nova-autonomous-cloud-delivery-python.pptx 522

The last positional argument is always the release id; every preceding
argument is an asset path (backward compatible with the single-asset call).

Token resolution: reads NOVA_GITEA_TOKEN (or ACDL_GITEA_TOKEN) from .env.secrets
/ .env, matching the ship_phase.sh pattern. Never uses shell env tokens.
"""
import os
import sys
import json
import urllib.request
import urllib.error
from pathlib import Path

GITEA_BASE = "https://git.cloudinit.dev"
OWNER = "continuous-intelligence"
REPO = "acdl"


def resolve_token() -> str:
    for fn in (".env.secrets", ".env"):
        try:
            for line in Path(fn).read_text().splitlines():
                if line.startswith("NOVA_GITEA_TOKEN=") or line.startswith("ACDL_GITEA_TOKEN="):
                    return line.split("=", 1)[1].strip()
        except (FileNotFoundError, PermissionError):
            continue
    raise RuntimeError("No Gitea token found in .env.secrets or .env (NOVA_GITEA_TOKEN/ACDL_GITEA_TOKEN)")


def attach_asset(file_path: str, release_id: str) -> dict:
    token = resolve_token()
    p = Path(file_path)
    if not p.is_file():
        raise FileNotFoundError(f"Asset file not found: {file_path}")

    url = f"{GITEA_BASE}/api/v1/repos/{OWNER}/{REPO}/releases/{release_id}/assets"
    filename = p.name

    boundary = "----NovaBoundary7MAgYbk"
    body = (
        f"--{boundary}\r\n"
        f'Content-Disposition: form-data; name="name"\r\n\r\n'
        f"{filename}\r\n"
        f"--{boundary}\r\n"
        f'Content-Disposition: form-data; name="attachment"; filename="{filename}"\r\n'
        f"Content-Type: application/octet-stream\r\n\r\n"
    ).encode() + p.read_bytes() + f"\r\n--{boundary}--\r\n".encode()

    req = urllib.request.Request(
        url,
        data=body,
        headers={
            "Authorization": f"token {token}",
            "Content-Type": f"multipart/form-data; boundary={boundary}",
        },
        method="POST",
    )
    try:
        resp = urllib.request.urlopen(req, timeout=60)
        return json.loads(resp.read())
    except urllib.error.HTTPError as e:
        err = e.read().decode()[:300]
        raise RuntimeError(f"HTTP {e.code} attaching {filename} to release {release_id}: {err}") from e


if __name__ == "__main__":
    if len(sys.argv) < 3:
        print("Usage: attach_release_asset.py <file-path> [<file-path-2>...] <release-id>")
        sys.exit(1)
    asset_paths = sys.argv[1:-1]
    release_id = sys.argv[-1]
    for idx, path in enumerate(asset_paths):
        result = attach_asset(path, release_id)
        primary = " (primary)" if idx == 0 and len(asset_paths) > 1 else ""
        print(f"Attached{primary}: {result.get('name')} → release {release_id} (asset id {result.get('id')})")