import json
import re
import sys
import time
import traceback
from datetime import datetime

import requests
from colorama import Fore


def validate_dict_key(d, k):
    if d.get(k) is None:
        print(f"{Fore.RED}{k} is not set!{Fore.RESET}", file=sys.stderr, flush=True)
        return False
    return True


class TsApi:
    def __init__(self, **kwargs):
        res = validate_dict_key(kwargs, "org")
        res &= validate_dict_key(kwargs, "api_url")
        res &= validate_dict_key(kwargs, "auth_token")
        if not res:
            sys.exit(1)
        self.opts = kwargs

    @property
    def __api_url(self):
        return self.opts.get("api_url")

    @property
    def __request_defaults(self):
        return {
            "verify": self.opts.get("ignore_ssl") != True,
            "headers": self.__get_headers(),
        }

    def __get_headers(self):
        headers = {"x-org-slug": self.opts.get("org")}
        ts_auth = self.opts.get("auth_token")
        if re.compile(r"^([a-z0-9]+-)+[a-z0-9]+$").match(ts_auth, re.IGNORECASE):
            headers["x-api-key"] = ts_auth
        else:
            headers["ts-auth-token"] = ts_auth
        return headers

    def upload_artifact(self, cfg, artifact_bytes):
        type_to_url = {
            "ids": "ids",
            "master-script": "master-scripts",
            "protocol": "master-scripts",
            "task-script": "task-scripts",
        }
        url = f"{self.__api_url}/artifact/{type_to_url[cfg.type]}/{cfg.namespace}/{cfg.slug}/{cfg.version}"
        params = {
            **({"force": "true"} if cfg.force else {}),
        }
        r = requests.post(
            url,
            **self.__request_defaults,
            params=params,
            data=artifact_bytes,
        )
        if r.status_code < 400:
            return r.json()
        else:
            print(r.text, file=sys.stderr, flush=True)
            raise Exception(f"HTTP status: {r.status_code}, url: {r.url}")

    def get_task_script_build_info(self, id: str):
        url = f"{self.__api_url}/artifact/builds/{id}"
        r = requests.get(url, **self.__request_defaults)
        if r.status_code < 400:
            return r.json()
        else:
            print(r.text, file=sys.stderr, flush=True)
            raise Exception(f"HTTP status: {r.status_code}, url: {r.url}")

    def get_task_script_build_logs(self, id: str, params):
        url = f"{self.__api_url}/artifact/build-logs/{id}"
        r = requests.get(
            url,
            **self.__request_defaults,
            params={k: v for k, v in params.items() if v is not None},
        )
        if r.status_code < 400:
            return r.json()
        else:
            print(r.text, file=sys.stderr, flush=True)
            raise Exception(f"HTTP status: {r.status_code}, url: {r.url}")
