# *************************************************************************
#
#  Copyright (c) 2026 - Datatailr Inc.
#  All Rights Reserved.
#
#  This file is part of Datatailr and subject to the terms and conditions
#  defined in 'LICENSE.txt'. Unauthorized copying and/or distribution
#  of this file, in parts or full, via any medium is strictly prohibited.
# *************************************************************************

import os
import shutil
from enum import Enum
import subprocess
from pathlib import Path
from typing import Tuple

ENV_VARS_PREFIX = "DATATAILR_JOB_ENV_"
USER_PYTHON_CODE_SITE_PACKAGES_DIR = "/opt/datatailr/usr/lib/python/site-packages"


class Environment(Enum):
    """
    Enum representing different environments for Datatailr jobs.
    """

    DEV = "dev"
    PRE = "pre"
    PROD = "prod"

    def __str__(self):
        return self.value

    def __repr__(self):
        return f"Environment.{self.name}('{self.value}')"


def is_dt_installed() -> bool:
    """
    Check if the native Datatailr CLI is available on PATH.

    Returns:
        True if the resolved dt binary is /opt/datatailr/bin/dt; otherwise False.

    Examples:
        >>> is_dt_installed()
        True
    """
    dt_command = shutil.which("dt")
    if not dt_command:
        return False
    resolved = os.path.realpath(dt_command)
    return resolved == "/opt/datatailr/bin/dt"


def is_remote_cli_dt_installed() -> bool:
    """
    Check if the `dt` command on PATH is the Datatailr remote CLI shim.
    """
    if is_dt_installed():
        return False

    dt_command = shutil.which("dt")
    if not dt_command:
        return False

    candidate = Path(dt_command).resolve()
    if not candidate.exists() or not candidate.is_file():
        return False
    try:
        content = candidate.read_text(encoding="utf-8", errors="ignore")
    except Exception:
        return False
    return "datatailr._remote_client.remote_cli" in content


def run_shell_command(command: str) -> Tuple[str, int]:
    """
    Run a shell command.

    This function executes a shell command and returns the output.

    Args:
        command (str): The shell command to execute.

    Returns:
        str: The output of the executed command.
    """
    result = subprocess.run(command, shell=True, capture_output=True, text=True)
    if result.returncode != 0:
        raise RuntimeError(f"Command '{command}' failed with error: {result.stderr}")
    return result.stdout.strip(), result.returncode


def dict_to_env_vars(env_vars: dict, prefix: str = ENV_VARS_PREFIX) -> list:
    """Convert a dictionary of environment variables to a list format suitable for shell commands.

    Args:
        env_vars (dict): A dictionary where keys are environment variable names and values are their corresponding values.

    Returns:
        list: A list of lists, where each inner list contains a key-value pair representing an environment variable.
    """
    return [{prefix + key: str(value)} for key, value in env_vars.items()]


class BiDict:
    def __init__(self, mapping=None):
        self._fwd = {}
        self._inv = {}
        if mapping:
            for k, v in mapping.items():
                self._fwd[k] = v
                self._inv[v] = k

    def __setitem__(self, key, value):
        if key in self._fwd:
            del self._inv[self._fwd[key]]
        if value in self._inv:
            del self._fwd[self._inv[value]]
        self._fwd[key] = value
        self._inv[value] = key

    def __getitem__(self, key):
        return self._fwd[key]

    def __delitem__(self, key):
        value = self._fwd.pop(key)
        del self._inv[value]

    def __contains__(self, key):
        return key in self._fwd

    def pop(self, key):
        value = self._fwd.pop(key)
        del self._inv[value]
        return value

    @property
    def inverse(self):
        return self._inv
