import json, os, sys, urllib.parse, urllib.request, urllib.error


def _cfg():
    return json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))


def _inputs():
    return json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))


def _token(cfg):
    auth_url = str(cfg.get("auth_url") or "https://auth.app.wiz.io/oauth/token")
    form = urllib.parse.urlencode({
        "grant_type": "client_credentials",
        "client_id": str(cfg.get("client_id", "")),
        "client_secret": str(cfg.get("client_secret", "")),
        "audience": "wiz-api",
    }).encode("utf-8")
    req = urllib.request.Request(auth_url, data=form,
                                 headers={"Content-Type": "application/x-www-form-urlencoded",
                                          "Accept": "application/json"}, method="POST")
    with urllib.request.urlopen(req, timeout=60) as r:
        tok = json.loads(r.read())
    if not tok.get("access_token"):
        raise Exception("Token request failed: " + json.dumps(tok))
    return tok["access_token"]


def graphql(cfg, token, query, variables):
    body = json.dumps({"query": query, "variables": variables}).encode("utf-8")
    req = urllib.request.Request(str(cfg.get("api_url", "")), data=body, headers={
        "Authorization": "Bearer " + token,
        "Content-Type": "application/json",
        "Accept": "application/json",
    }, method="POST")
    with urllib.request.urlopen(req, timeout=90) as r:
        raw = r.read()
        resp = json.loads(raw) if raw else {}
    if resp.get("errors"):
        raise Exception("GraphQL error: " + json.dumps(resp["errors"]))
    return resp.get("data", resp)


def _run(fn):
    try:
        cfg = _cfg()
        inputs = _inputs()
        token = _token(cfg)
        print(json.dumps(fn(cfg, token, inputs)))
    except urllib.error.HTTPError as e:
        print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
        sys.exit(1)
    except Exception as e:
        print(json.dumps({"error": str(e)}))
        sys.exit(1)


QUERY = """
query Vulns($first: Int, $filterBy: VulnerabilityFindingFilters) {
  vulnerabilityFindings(first: $first, filterBy: $filterBy) {
    nodes { id name severity cvssSeverity vendorSeverity firstDetectedAt }
    pageInfo { hasNextPage endCursor }
  }
}
"""


def main(cfg, token, inputs):
    severity = inputs.get("severity")
    first = inputs.get("first")

    filter_by = {}
    if severity:
        filter_by["severity"] = [severity]

    variables = {"first": int(first or 20), "filterBy": filter_by}
    return graphql(cfg, token, QUERY, variables)


_run(main)
