#!/usr/bin/env python3
"""
Kuhn & Rueß GmbH
Consulting and Development
https://kuhn-ruess.de
"""
import argparse
import requests
from requests.auth import HTTPBasicAuth
from json import JSONDecodeError
from urllib.parse import unquote, quote, urlencode


class AgentSapALM():
    """
    Agent SAP ALM
    """
    instance_name = None
    client_id = None
    client_secret = None
    debug = False
    filter = None
    proxy = None

    access_token = False

    def get_token(self):
        """
        Get Oauth Client Token
        """
        access_token_url = \
            f"https://{self.instance_name}.authentication.eu10.hana.ondemand.com/oauth/token"
        if not self.access_token:
            auth = HTTPBasicAuth(self.client_id, self.client_secret)
            data = {"grant_type": "client_credentials"}

            if self.debug:
                print(f"DEBUG: POST request to {access_token_url}")
                print(f"DEBUG: Request data: {data}")
                print(f"DEBUG: Request auth: Basic (client_id: {self.client_id})")
                print(f"DEBUG: Request auth: Basic (client_secret: {self.client_secret})")

            resp = requests.post(access_token_url, data=data, auth=auth, proxies=self.proxy)

            if self.debug:
                print(f"DEBUG: Response status: {resp.status_code}")
                print(f"DEBUG: Response headers: {dict(resp.headers)}")
                print(f"DEBUG: Response content: {resp.text}")

            try:
                self.access_token = resp.json()['access_token']
            except (KeyError, JSONDecodeError):
                print(resp.text)
                raise Exception("Cant fetch token")
        return self.access_token

    def get_metric(self):
        access_token = self.get_token()
        service_id_filter = {
            '$filter' : unquote(self.filter).replace('+', ' '),
        }
        query = urlencode(service_id_filter, quote_via=quote)
        metric_url = \
            f"https://{self.instance_name}.eu10.alm.cloud.sap/api/calm-analytics/v1/odata/v4/analytics/Metrics?{query}"
        headers = {
            "Authorization": f"Bearer {access_token}"
        }

        if self.debug:
            print(f"DEBUG: GET request to {metric_url}")
            print(f"DEBUG: Request params: {service_id_filter}")
            print(f"DEBUG: Request headers: {headers}")

        resp = requests.get(metric_url, headers=headers, proxies=self.proxy)

        if self.debug:
            print(f"DEBUG: Response status: {resp.status_code}")
            print(f"DEBUG: Response headers: {dict(resp.headers)}")
            print(f"DEBUG: Response content: {resp.text}")

        print("<<<sap_cloud_alm_metrics:sep(0)>>>")
        for metric in resp.json()['value']:
            print(f"[[[{metric['metricName']}]]]")
            print(metric)


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="SAP ALM Cloud Agent")
    parser.add_argument(
        '--instance',
        dest='instance_name',
        required=True,
        help=(
            "Instance name can be found in the URL subdomains part"
        ),
    )
    parser.add_argument('--client-id', dest='client_id', required=True, help="oAuth Client ID")
    parser.add_argument(
        '--client-secret',
        dest='client_secret',
        required=True,
        help="oAuth Client Secret",
    )
    parser.add_argument('--proxy', dest='proxy', help="Proxy to use")
    parser.add_argument('--filter', dest='filter', required=True, help="Filter to use")
    parser.add_argument(
        '--debug',
        action='store_true',
        help=(
            "Enable debug mode to show web "
            "requests and responses"
        ),
    )

    args = parser.parse_args()

    agent = AgentSapALM()
    agent.instance_name = args.instance_name
    agent.client_id = args.client_id
    agent.client_secret = args.client_secret
    proxy = {}
    if args.proxy:
        proxy['https'] = args.proxy
    agent.proxy = proxy
    agent.filter = args.filter
    agent.debug = args.debug
    agent.get_metric()
