# -*- coding: utf-8 -*-
"""Gateway Token Provider: AK-SK → Bearer Token.

Calls aliyun CLI to exchange Alibaba Cloud AK-SK credentials
for a Bearer Token used by the intelligent gateway A2A endpoint.
Supports token caching and automatic refresh.
"""

import asyncio
import json
import logging
import os
import time

logger = logging.getLogger("qwenpaw").getChild(
    __name__.replace("plugin_cloudpaw.", ""),
)

_TOKEN_REFRESH_MARGIN_SECONDS = 300  # refresh 5 min before expiry


class GatewayTokenProvider:
    """Exchange AK-SK for a Bearer Token via aliyun CLI.

    The token is cached and refreshed automatically when expired.
    """

    def __init__(
        self,
        ak: str = "",
        sk: str = "",
        client_id: str = "4081417976505782102",
        scope: str = "/internal/agenthub",
        endpoint: str = "ramoauth.aliyuncs.com",
    ):
        self._ak = ak or os.environ.get("ALIBABA_CLOUD_ACCESS_KEY_ID", "")
        self._sk = sk or os.environ.get("ALIBABA_CLOUD_ACCESS_KEY_SECRET", "")
        self._client_id = client_id
        self._scope = scope
        self._endpoint = endpoint
        self._cached_token: str = ""
        self._token_expire_at: float = 0
        self._lock = asyncio.Lock()

    async def get_token(self) -> str:
        """Get a valid Bearer Token, refreshing if expired."""
        async with self._lock:
            if self._cached_token and time.time() < self._token_expire_at:
                return self._cached_token
            return await self._refresh_token()

    def invalidate(self) -> None:
        """Force clear the cached token."""
        self._cached_token = ""
        self._token_expire_at = 0

    async def _refresh_token(self) -> str:
        if not self._ak or not self._sk:
            raise RuntimeError(
                "ALIBABA_CLOUD_ACCESS_KEY_ID / SECRET not configured",
            )

        cmd = [
            "aliyun",
            "ramoauth",
            "GenerateAccessToken",
            "--ClientId",
            self._client_id,
            "--endpoint",
            self._endpoint,
            "--version",
            "2026-04-21",
            "--access-key-id",
            self._ak,
            "--access-key-secret",
            self._sk,
            "--method",
            "POST",
            "--force",
            "--Scope",
            self._scope,
        ]

        logger.info("Refreshing gateway token via aliyun CLI...")
        proc = await asyncio.create_subprocess_exec(
            *cmd,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE,
        )
        stdout, stderr = await proc.communicate()

        if proc.returncode != 0:
            err_msg = (stderr or stdout).decode().strip()
            raise RuntimeError(
                f"Token refresh failed (exit={proc.returncode}): {err_msg}",
            )

        data = json.loads(stdout.decode())
        d = data.get("Data") or data
        token = d.get("AccessToken", d.get("access_token", ""))
        if not token:
            raise RuntimeError(
                f"No AccessToken in response: {stdout.decode()[:500]}",
            )

        expires_in = int(d.get("ExpiresIn", 3600))
        self._cached_token = token
        self._token_expire_at = (
            time.time() + expires_in - _TOKEN_REFRESH_MARGIN_SECONDS
        )

        logger.info(
            "Gateway token refreshed (length=%d, expires_in=%ds)",
            len(token),
            expires_in,
        )
        return token
