#!/usr/bin/env python3
"""Check whether Google Play accepts API edits for this package."""

from __future__ import annotations

import argparse
from contextlib import contextmanager
from functools import partial
import json
import os
from pathlib import Path
from urllib.parse import quote

import google.auth.transport.requests
from google.oauth2 import service_account

from play_preflight_transport import call, fail
import requests


SCOPE = "https://www.googleapis.com/auth/androidpublisher"
BASE_URL = "https://androidpublisher.googleapis.com/androidpublisher/v3"


def write_ready(value: bool) -> None:
    with Path(os.environ["GITHUB_OUTPUT"]).open("a") as stream:
        stream.write(f"ready={'true' if value else 'false'}\n")


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument("--package", required=True)
    parser.add_argument("--service-account", required=True, type=Path)
    args = parser.parse_args()

    with requests.Session() as client:
        check_ready(client, args.package, args.service_account)


def check_ready(client, package: str, account: Path) -> None:
    with opened_edit(client, package, account) as edit:
        ready = edit is not None
    write_ready(ready)
    if ready:
        print("Google Play package is ready for automated uploads")


@contextmanager
def opened_edit(client, package: str, account: Path):
    """Own one preflight edit; callers may perform reads before its verified cleanup."""
    credentials = service_account.Credentials.from_service_account_file(
        account, scopes=[SCOPE]
    )
    request = partial(google.auth.transport.requests.Request(session=client), timeout=30)
    call("oauth_refresh", lambda: credentials.refresh(request), retry=True)
    headers = {"Authorization": f"Bearer {credentials.token}"}
    url = f"{BASE_URL}/applications/{package}/edits"
    # Retry only a proven failed connection; an ambiguous insert is never replayed.
    response = call("edit_create", lambda: client.post(url, headers=headers, json={}, timeout=30),
                    accepted=(200, 404), retry_connect=True)
    if response.status_code == 404:
        print(
            "::warning::Google Play package is not API-ready. The app session must upload the "
            "signed Android artifact retained by this build through its assigned Play Console "
            "and verify the resulting release before retrying API delivery."
        )
        yield None
        return
    try:
        edit_id = json.loads(response.text)["id"]
        if not isinstance(edit_id, str) or not edit_id or len(edit_id) > 512:
            raise ValueError("invalid edit identifier")
    except (ValueError, TypeError, KeyError):
        fail("edit_create", "invalid_response", 1)
    delete_url = f"{url}/{quote(edit_id, safe='')}"
    try:
        yield (delete_url, headers)
    finally:
        call("edit_cleanup", lambda: client.delete(delete_url, headers=headers, timeout=30),
             retry=True, edit_id=edit_id, accepted=(200, 204, 404))


if __name__ == "__main__":
    main()
