import json
import os
import pathlib
import sys
import threading
import time
import uuid
from datetime import datetime, timedelta
from queue import Queue
from typing import Dict

import requests

from inspec_ai.config import TRACKING_DISABLED

ANONYMOUS_TRACKING_IDENTIFIER_KEY = "anonymous_tracking_identifier"

telemetry_queue: Queue = Queue()

previously_tracked_events: Dict = {}

_anonymous_tracking_identifier = ""


def track_function_executed(function_name, *args, **kwargs):
    def decorate(func):
        def call(*args, **kwargs):
            _track_function_executed_internal(function_name)
            result = func(*args, **kwargs)
            return result

        return call

    return decorate


def _track_function_executed_internal(function_name: str) -> None:
    if TRACKING_DISABLED:
        return

    utc_now = datetime.utcnow()

    if function_name in previously_tracked_events:
        last_track = previously_tracked_events[function_name]

        previously_tracked_events[function_name] = utc_now

        if utc_now < last_track + timedelta(minutes=5):
            return

    else:
        previously_tracked_events[function_name] = utc_now

    telemetryEvent = {
        "eventDate": str(utc_now),
        "functionName": str(function_name),
    }

    telemetry_queue.put(telemetryEvent)


def _get_anonymous_tracking_identifier() -> str:
    global _anonymous_tracking_identifier

    if _anonymous_tracking_identifier and _anonymous_tracking_identifier != "":
        return _anonymous_tracking_identifier

    data_dir = _get_datadir()
    directory = os.path.join(data_dir, ".inspec")
    file_name = "config.json"

    full_path = os.path.join(directory, file_name)

    if os.path.isfile(full_path):
        with open(full_path, "r") as file:
            config = json.load(file)

    else:
        if not os.path.exists(directory):
            os.mkdir(directory)

        anonymous_tracking_identifier = uuid.uuid4()

        config = {ANONYMOUS_TRACKING_IDENTIFIER_KEY: str(anonymous_tracking_identifier)}

        with open(full_path, "w") as file:
            json.dump(config, file)

    _anonymous_tracking_identifier = config[ANONYMOUS_TRACKING_IDENTIFIER_KEY]

    return _anonymous_tracking_identifier


def _get_datadir() -> pathlib.Path:
    home = pathlib.Path.home()

    if sys.platform == "win32":
        return home / "AppData/Roaming"
    elif sys.platform == "linux":
        return home / ".local/share"
    elif sys.platform == "darwin":
        return home / "Library/Application Support"


def _telemetry_daemon():
    main_process_alive = True
    while main_process_alive:
        mt = threading.main_thread()
        main_process_alive = mt.is_alive()

        while not telemetry_queue.empty():
            event = telemetry_queue.get()

            anonymous_tracking_identifier = _get_anonymous_tracking_identifier()

            event["anonymousTelemetryIdentifier"] = str(anonymous_tracking_identifier)

            try:
                requests.post(
                    "https://inspec-dev-api.azurewebsites.net/telemetry/track-function-executed",
                    json=event,
                    headers={"Authorization": "Bearer NDk5MDYxRjctQjM4Mi00MkRBLTlFNUMtNjdCOTBBMTBDM0VD"},
                )
            except:  # noqa: E722 - we want to swallow the error and not act on it.
                pass

        time.sleep(0.1)


telemetry_thread = threading.Thread(target=_telemetry_daemon, name="Telemetry Thread")
telemetry_thread.start()
