#!/usr/bin/env bash
# =============================================================================
# BLOOM LIMS - Environment Activation Script (TapDB runtime)
# =============================================================================

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    echo "Error: This script must be sourced, not executed."
    echo "Usage: source ./activate <deploy-name>"
    exit 1
fi

_bloom_script_path() {
    if [[ -n "${ZSH_VERSION:-}" ]]; then
        printf '%s\n' "${(%):-%x}"
    elif [[ -n "${BASH_SOURCE[0]:-}" ]]; then
        printf '%s\n' "${BASH_SOURCE[0]}"
    else
        printf '%s\n' "$0"
    fi
}

_BLOOM_SCRIPT_PATH="$(_bloom_script_path)"
BLOOM_ROOT="$(cd "$(dirname "${_BLOOM_SCRIPT_PATH}")" && pwd)"
unset -f _bloom_script_path
unset _BLOOM_SCRIPT_PATH

_GREEN='\033[0;32m'
_YELLOW='\033[1;33m'
_BLUE='\033[0;34m'
_CYAN='\033[0;36m'
_NC='\033[0m'
_BLOOM_PYTHON=""
_BLOOM_CONDA_ENV_BASE="BLOOM"
_BLOOM_LEGACY_REBIND_VARS=(
    USE_LOCAL_DAYLILY_TAPDB
    USE_LOCAL_DAYLILY_COGNITO
    USE_LOCAL_CLI_CORE_YO
)

_bloom_reject_legacy_local_rebind_env() {
    local var_name=""
    local var_value=""
    for var_name in "${_BLOOM_LEGACY_REBIND_VARS[@]}"; do
        if [[ -n "${ZSH_VERSION:-}" ]]; then
            eval 'var_value="${(P)var_name-}"'
        else
            eval 'var_value="${!var_name-}"'
        fi
        if [[ -n "$var_value" ]]; then
            echo -e "  ${_YELLOW}⚠${_NC} ${var_name} is no longer supported."
            echo -e "  ${_CYAN}→${_NC} Bloom activation now requires packaged dependencies from ${_BLOOM_CONDA_ENV_NAME:-the active conda environment}."
            return 1
        fi
    done
}

_bloom_require_python_import() {
    local module_name="$1"
    local package_name="$2"
    if ! "${_BLOOM_PYTHON:-python}" - "$module_name" <<'PY' >/dev/null 2>&1
import importlib
import sys

importlib.import_module(sys.argv[1])
PY
    then
        echo -e "  ${_YELLOW}⚠${_NC} Missing packaged dependency: ${package_name}"
        return 1
    fi
}

_bloom_default_web_port() {
    python -c 'from bloom_lims.config import DEFAULT_BLOOM_WEB_PORT; print(DEFAULT_BLOOM_WEB_PORT)'
}

_bloom_default_tapdb_local_pg_port() {
    python -c 'from bloom_lims.config import DEFAULT_BLOOM_TAPDB_LOCAL_PG_PORT; print(DEFAULT_BLOOM_TAPDB_LOCAL_PG_PORT)'
}

_bloom_sanitize_deployment_code() {
    local raw_value="$1"
    local sanitized=""
    sanitized="$(printf '%s' "$raw_value" | LC_ALL=C sed -E 's/[^A-Za-z0-9-]+/-/g; s/^-+//; s/-+$//')"
    if [[ -z "$sanitized" ]]; then
        sanitized="local"
    fi
    printf '%s\n' "$sanitized"
}

_bloom_validate_deploy_name() {
    local deploy_name="$1"
    if [[ ! "$deploy_name" =~ ^[A-Za-z0-9-]{2,8}$ ]]; then
        echo -e "  ${_YELLOW}⚠${_NC} deploy-name must match ^[A-Za-z0-9-]{2,8}$"
        return 1
    fi
}

_bloom_prepare_tapdb_config_path() {
    local client_id="$1"
    local namespace="$2"
    local xdg_config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
    local deployment_code="${BLOOM_DEPLOYMENT_CODE:-${DEPLOYMENT_CODE:-${LSMC_DEPLOYMENT_CODE:-local}}}"
    local scoped_namespace=""
    deployment_code="$(_bloom_sanitize_deployment_code "${deployment_code}")"
    scoped_namespace="${namespace}-${deployment_code}"
    local user_dir="${xdg_config_home}/tapdb/${client_id}/${scoped_namespace}"
    local user_path="${user_dir}/tapdb-config.yaml"
    local repo_template="$BLOOM_ROOT/config/tapdb-config-${namespace}.yaml"

    if [[ -f "$user_path" ]]; then
        chmod 600 "$user_path" 2>/dev/null || true
        printf '%s\n' "$user_path"
        return 0
    fi
    if [[ ! -f "$repo_template" ]]; then
        printf '%s\n' "$user_path"
        return 0
    fi
    mkdir -p "$user_dir" || return 1
    cp "$repo_template" "$user_path" || return 1
    chmod 600 "$user_path" || return 1
    printf '%s\n' "$user_path"
}

if [[ "$#" -ne 1 ]]; then
    echo -e "  ${_YELLOW}⚠${_NC} Bloom activation requires exactly one positional deploy-name."
    echo "Usage: source ./activate <deploy-name>"
    return 1
fi

_bloom_deployment_code="$1"
if ! _bloom_validate_deploy_name "${_bloom_deployment_code}"; then
    return 1
fi
export BLOOM_DEPLOYMENT_CODE="${_bloom_deployment_code}"
export DEPLOYMENT_CODE="${_bloom_deployment_code}"
export LSMC_DEPLOYMENT_CODE="${_bloom_deployment_code}"
_BLOOM_CONDA_ENV_NAME="${_BLOOM_CONDA_ENV_BASE}-${_bloom_deployment_code}"
unset _bloom_deployment_code

if ! _bloom_reject_legacy_local_rebind_env; then
    return 1
fi

_bloom_module_is_from_repo() {
    local module_name="$1"
    local repo_root="$2"
    "${_BLOOM_PYTHON:-python}" - "$module_name" "$repo_root" <<'PY' >/dev/null 2>&1
import importlib
import pathlib
import sys

module = importlib.import_module(sys.argv[1])
repo_root = pathlib.Path(sys.argv[2]).resolve()
module_file = getattr(module, "__file__", "")
if not module_file:
    raise SystemExit(1)
module_path = pathlib.Path(module_file).resolve()
raise SystemExit(0 if module_path == repo_root or repo_root in module_path.parents else 1)
PY
}

_bloom_distribution_is_editable_from_repo() {
    local dist_name="$1"
    local repo_root="$2"
    local editable_location=""

    editable_location="$("${_BLOOM_PYTHON:-python}" -m pip show "$dist_name" 2>/dev/null | awk -F': ' '/^Editable project location:/ {print $2; exit}')"
    [[ -n "$editable_location" ]] || return 1

    editable_location="$(cd "$editable_location" 2>/dev/null && pwd)"
    [[ -n "$editable_location" ]] || return 1
    [[ "$editable_location" == "$repo_root" ]]
}

_bloom_ensure_editable_repo() {
    local label="$1"
    local module_name="$2"
    local repo_root="$3"
    local extras="${4:-}"
    local dist_name="${5:-}"
    local install_target=""
    if [[ -z "$repo_root" ]]; then
        return 0
    fi
    if [[ -n "$dist_name" ]]; then
        if _bloom_distribution_is_editable_from_repo "$dist_name" "$repo_root"; then
            echo -e "  ${_GREEN}✓${_NC} Using local ${label} checkout: ${repo_root}"
            return 0
        fi
    elif _bloom_module_is_from_repo "$module_name" "$repo_root"; then
        echo -e "  ${_GREEN}✓${_NC} Using local ${label} checkout: ${repo_root}"
        return 0
    fi
    install_target="${repo_root}${extras}"
    echo -e "  ${_CYAN}→${_NC} Installing local ${label} checkout..."
    if ! "${_BLOOM_PYTHON:-python}" -m pip install --no-deps -e "$install_target" -q; then
        echo -e "  ${_YELLOW}⚠${_NC} Failed to install local ${label} checkout from ${repo_root}"
        return 1
    fi
    if [[ -n "$dist_name" ]]; then
        if ! _bloom_distribution_is_editable_from_repo "$dist_name" "$repo_root"; then
            echo -e "  ${_YELLOW}⚠${_NC} ${label} is not installed editable from ${repo_root}"
            return 1
        fi
    elif ! _bloom_module_is_from_repo "$module_name" "$repo_root"; then
        echo -e "  ${_YELLOW}⚠${_NC} ${label} still resolves outside ${repo_root}"
        return 1
    fi
    echo -e "  ${_GREEN}✓${_NC} Using local ${label} checkout: ${repo_root}"
}

echo -e "${_BLUE}Activating BLOOM LIMS environment (${_BLOOM_CONDA_ENV_NAME})...${_NC}"

if command -v conda &> /dev/null; then
    if [[ -n "${ZSH_VERSION:-}" ]]; then
        eval "$(conda shell.zsh hook)" 2>/dev/null || true
    elif [[ -n "${BASH_VERSION:-}" ]]; then
        eval "$(conda shell.bash hook)" 2>/dev/null || true
    else
        source "$(conda info --base)/etc/profile.d/conda.sh" 2>/dev/null || true
    fi

    if conda info --envs | grep -Eq "(^|[[:space:]])${_BLOOM_CONDA_ENV_NAME}([[:space:]]|$)"; then
        echo -e "  ${_GREEN}✓${_NC} Activating conda environment: ${_BLOOM_CONDA_ENV_NAME}"
        conda activate "${_BLOOM_CONDA_ENV_NAME}"
        if [[ -n "$CONDA_PREFIX" ]] && [[ -d "$CONDA_PREFIX/bin" ]]; then
            export PATH="$CONDA_PREFIX/bin:$PATH"
        fi
    else
        echo -e "  ${_YELLOW}⚠${_NC} Conda environment '${_BLOOM_CONDA_ENV_NAME}' not found."
        if [[ -f "$BLOOM_ROOT/environment.yaml" ]]; then
            echo -e "  ${_CYAN}→${_NC} Installing conda environment from environment.yaml..."
            if conda env create -n "${_BLOOM_CONDA_ENV_NAME}" -f "$BLOOM_ROOT/environment.yaml"; then
                echo -e "  ${_GREEN}✓${_NC} Conda environment created successfully"
                conda activate "${_BLOOM_CONDA_ENV_NAME}"
                if [[ -n "$CONDA_PREFIX" ]] && [[ -d "$CONDA_PREFIX/bin" ]]; then
                    export PATH="$CONDA_PREFIX/bin:$PATH"
                fi
            else
                echo -e "  ${_YELLOW}⚠${_NC} Failed to create conda environment."
            fi
        else
            echo -e "  ${_YELLOW}⚠${_NC} environment.yaml not found."
        fi
    fi
else
    echo -e "  ${_YELLOW}⚠${_NC} Conda not found."
    return 1
fi

if [[ "${CONDA_DEFAULT_ENV:-}" != "${_BLOOM_CONDA_ENV_NAME}" ]] || [[ -z "${CONDA_PREFIX:-}" ]] || [[ ! -x "${CONDA_PREFIX}/bin/python" ]]; then
    echo -e "  ${_YELLOW}⚠${_NC} ${_BLOOM_CONDA_ENV_NAME} conda environment is required."
    echo -e "  ${_CYAN}→${_NC} Run 'conda env create -n ${_BLOOM_CONDA_ENV_NAME} -f environment.yaml' if needed, then retry 'source ./activate <deploy-name>'."
    return 1
fi

_BLOOM_PYTHON="${CONDA_PREFIX}/bin/python"
_BLOOM_PYTHON_BIN="$(dirname "${_BLOOM_PYTHON}")"
export PATH="${_BLOOM_PYTHON_BIN}:$PATH"

if ! _bloom_ensure_editable_repo "Bloom" "bloom_lims" "$BLOOM_ROOT" "" "bloom_lims"; then
    return 1
fi

echo -e "  ${_GREEN}✓${_NC} Using packaged daylily-tapdb from ${_BLOOM_CONDA_ENV_NAME}"
echo -e "  ${_GREEN}✓${_NC} Using packaged daylily-cognito from ${_BLOOM_CONDA_ENV_NAME}"
echo -e "  ${_GREEN}✓${_NC} Using packaged cli-core-yo from ${_BLOOM_CONDA_ENV_NAME}"

_bloom_require_python_import "daylily_tapdb" "daylily-tapdb" || return 1
_bloom_require_python_import "daylily_cognito" "daylily-cognito" || return 1
_bloom_require_python_import "cli_core_yo" "cli-core-yo" || return 1

if command -v rehash >/dev/null 2>&1; then
    rehash
elif command -v hash >/dev/null 2>&1; then
    hash -r 2>/dev/null || true
fi

if [[ "$-" == *i* ]]; then
    if [[ -n "${ZSH_VERSION:-}" ]]; then
        if eval "$(_BLOOM_COMPLETE=zsh_source bloom 2>/dev/null)" 2>/dev/null; then
            echo -e "  ${_GREEN}✓${_NC} Enabled tab completion for 'bloom' (zsh)"
        fi
    elif [[ -n "${BASH_VERSION:-}" ]]; then
        if eval "$(_BLOOM_COMPLETE=bash_source bloom 2>/dev/null)" 2>/dev/null; then
            echo -e "  ${_GREEN}✓${_NC} Enabled tab completion for 'bloom' (bash)"
        fi
    fi
fi

# TapDB/AWS runtime defaults for BLOOM
_BLOOM_TAPDB_ENV="dev"
_BLOOM_TAPDB_CLIENT_ID="bloom"
_BLOOM_TAPDB_DATABASE_NAME="bloom"
export MERIDIAN_ENVIRONMENT="${MERIDIAN_ENVIRONMENT:-production}"
export MERIDIAN_SANDBOX_PREFIX="${MERIDIAN_SANDBOX_PREFIX-}"
export BLOOM_UI_PORT="${BLOOM_UI_PORT:-$(_bloom_default_web_port)}"
_BLOOM_TAPDB_LOCAL_PG_PORT="$(_bloom_default_tapdb_local_pg_port)"
_BLOOM_TAPDB_DEV_PORT="${_BLOOM_TAPDB_LOCAL_PG_PORT}"
_BLOOM_TAPDB_TEST_PORT="${_BLOOM_TAPDB_LOCAL_PG_PORT}"
_BLOOM_TAPDB_CONFIG_PATH="$(_bloom_prepare_tapdb_config_path "${_BLOOM_TAPDB_CLIENT_ID}" "${_BLOOM_TAPDB_DATABASE_NAME}")"
export BLOOM_COGNITO_APP_NAME="${BLOOM_COGNITO_APP_NAME:-bloom}"
export AWS_PROFILE="${AWS_PROFILE:-lsmc}"
export AWS_REGION="${AWS_REGION:-us-west-2}"
export AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION:-$AWS_REGION}"

echo -e "  ${_GREEN}✓${_NC} Bloom TapDB env=${_BLOOM_TAPDB_ENV}"
echo -e "  ${_GREEN}✓${_NC} Bloom TapDB client=${_BLOOM_TAPDB_CLIENT_ID}"
echo -e "  ${_GREEN}✓${_NC} Bloom TapDB namespace=${_BLOOM_TAPDB_DATABASE_NAME}"
echo -e "  ${_GREEN}✓${_NC} MERIDIAN_ENVIRONMENT=${MERIDIAN_ENVIRONMENT}"
echo -e "  ${_GREEN}✓${_NC} MERIDIAN_SANDBOX_PREFIX=${MERIDIAN_SANDBOX_PREFIX}"
if [[ -n "${_BLOOM_TAPDB_CONFIG_PATH:-}" ]]; then
    echo -e "  ${_GREEN}✓${_NC} Bloom TapDB config path=${_BLOOM_TAPDB_CONFIG_PATH}"
else
    echo -e "  ${_YELLOW}⚠${_NC} Bloom TapDB config path is not set"
fi
echo -e "  ${_GREEN}✓${_NC} Bloom TapDB dev port=${_BLOOM_TAPDB_DEV_PORT}"
echo -e "  ${_GREEN}✓${_NC} Bloom TapDB test port=${_BLOOM_TAPDB_TEST_PORT}"
echo -e "  ${_GREEN}✓${_NC} BLOOM_COGNITO_APP_NAME=${BLOOM_COGNITO_APP_NAME}"
echo -e "  ${_GREEN}✓${_NC} AWS_PROFILE=${AWS_PROFILE}"
echo -e "  ${_GREEN}✓${_NC} AWS_REGION=${AWS_REGION}"

export BLOOM_ROOT

deactivate_bloom() {
    unset BLOOM_ROOT
    unset BLOOM_DEPLOYMENT_CODE
    unset DEPLOYMENT_CODE
    unset LSMC_DEPLOYMENT_CODE
    unset MERIDIAN_ENVIRONMENT
    unset MERIDIAN_SANDBOX_PREFIX
    unset BLOOM_COGNITO_APP_NAME
    if [[ "${CONDA_DEFAULT_ENV:-}" == "${_BLOOM_CONDA_ENV_NAME}" ]]; then
        conda deactivate 2>/dev/null
    fi
    echo "BLOOM LIMS environment deactivated."
    unset -f deactivate_bloom
}

echo ""
echo -e "${_CYAN}BLOOM LIMS environment activated!${_NC}"
echo ""
echo "Command groups:"
echo ""
echo -e "  ${_CYAN}bloom server${_NC}    start, stop, status, logs"
echo -e "  ${_CYAN}bloom db${_NC}        init, start, stop, status, migrate, seed, shell, reset"
echo -e "  ${_CYAN}bloom config${_NC}    path, init, show, validate, edit, reset, shell, doctor, status"
echo -e "  ${_CYAN}tapdb${_NC}           shared DB/runtime lifecycle"
echo -e "  ${_CYAN}daycog${_NC}          shared Cognito lifecycle where Bloom delegates"
echo -e "  ${_CYAN}bloom info${_NC}      Show environment information"
echo -e "  ${_CYAN}bloom version${_NC}   Show CLI version"
echo ""
echo -e "  ${_GREEN}bloom --help${_NC}          Show all available commands"
echo -e "  ${_GREEN}deactivate_bloom${_NC}      Deactivate this environment"
echo ""

unset _BLOOM_CLI_CORE_REPO
unset _BLOOM_DAYCOG_REPO
unset _BLOOM_TAPDB_REPO
