import time

import logging
import requests
from requests.adapters import HTTPAdapter
from .utils import CachedToken

logger = logging.getLogger(__name__)

COMPUTE_INSTANCE_METADATA_URL = 'http://169.254.169.254/computeMetadata/v1/instance/?recursive=true'
COMPUTE_INSTANCE_SA_TOKEN_URL = 'http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token'


class SaTokenError(Exception):
    ...


def get_instance_metadata():
    url = COMPUTE_INSTANCE_METADATA_URL
    with requests.Session() as session:
        session.mount(url, HTTPAdapter(max_retries=2))
        try:
            # TODO: таймаут выставлен, чтобы проходили локальные тесты.
            response = session.get(url, headers={"Metadata-Flavor": "Google"}, timeout=1).json()
            logger.debug(f"Instance metadata {response}")
            return response
        except Exception as e:
            logger.error(f"Couldn't get instance metadata of current vm: {e}")
            return  # raise Exception(f"Couldn't get instance metadata of current vm: {e}")


def get_current_instance_id():
    if response := get_instance_metadata():
        return response.get('id')
    return


def get_current_instance_name():
    return (get_instance_metadata() or {}).get('name', 'Unknown')


def get_instance_attributes():
    if response := get_instance_metadata():
        return response.get('attributes')
    return {}


class SaToken(CachedToken):

    @staticmethod
    def _get_with_no_cache():
        url = COMPUTE_INSTANCE_SA_TOKEN_URL
        with requests.Session() as session:
            session.mount(url, HTTPAdapter(max_retries=5))
            try:
                # TODO: таймаут выставлен, чтобы проходили локальные тесты.
                token_request_time = time.time()
                raw_response = session.get(url, headers={"Metadata-Flavor": "Google"}, timeout=2)
                token_data = raw_response.json()
                logger.debug("IAM token was got")
                expire_at = token_request_time + min(float(token_data['expires_in']), 60 * 60)
                return token_data['access_token'], expire_at
            except Exception as e:
                logger.error(f"Couldn't get iam token for instance service account: {e}")
                raise SaTokenError("Couldn't get iam token for instance service account.") from e
