# function to get the external interface address on a development machine, not
# the public internet address but the LAN address accessible by other devices
# on the same network
function _get_ext_ip() {
    if which ip 2>/dev/null 1>/dev/null; then
        ip route get 1.1.1.1 | grep -oP 'src \K\S+'
    else
        # MacOS does not have ip, so we use route and ifconfig instead
        INTERFACE=$(route get 1.1.1.1 | grep interface | awk '{print $2}')
        ifconfig | grep $INTERFACE -A 10 | grep "inet " | grep -Fv 127.0.0.1 | awk '{print $2}' | head -n 1
    fi
}

function get_ext_ip() {
    IP=${IP:-$(_get_ext_ip)}
    echo $IP
}


# Function to save images to kind, with workaround for github CI and other environment issues
# In github CI, kind gets confused and tries to pull the image from docker instead
# of podman, so if regular docker-image fails we need to:
#   * save it to OCI image format
#   * then load it into kind
kind_load_image() {
  local image=$1
  local keep_tar=${2:-"do-not-keep-tar"}
  local tar_filename=$(echo $image.tar | sed 's/[:\/]/_/g')

  # First, try to load the image directly
  if kind load docker-image "${image}"; then
    echo "Image ${image} loaded successfully."
    return
  fi

  # If that fails, we have the workaround in place
  if [ -f "${tar_filename}" ] && [ "${keep_tar}" == "keep-tar" ]; then
    echo "File ${tar_filename} already exists. Skipping save."
  else
    echo "Saving ${image} to ${tar_filename}..."

    # If the image is not local we may need to pull it first
    if [[ "${image}" != localhost* ]]; then
      podman pull "${image}"
    fi

    # Save to tar file
    rm -f "${tar_filename}"
    podman save "${image}" -o "${tar_filename}"
    if [ $? -eq 0 ]; then
      echo "Image saved successfully to ${tar_filename}."
    else
      echo "Failed to save image to ${tar_filename}."
      exit 1
    fi
  fi

  kind load image-archive "${tar_filename}"
  if [ "${keep_tar}" != "keep-tar" ]; then
    rm -f "${tar_filename}"
  fi
}

function registry_address() {

    KUBECONTEXT=${KUBECONTEXT:-$(kubectl config current-context)}

    if [[ $KUBECONTEXT == *"kind"* ]]; then
        REPOADDR=$(get_ext_ip):5000
    else
        REPOADDR="e2eregistry.$(kubectl get ingresses.config/cluster -o jsonpath={.spec.domain})"
    fi
    echo $REPOADDR
}


function in_kind() {
    KUBECONTEXT=${KUBECONTEXT:-$(kubectl config current-context)}
    if [[ $KUBECONTEXT == *"kind"* ]]; then
        return 0 # true
    else
        return 1 # false
    fi
}


# This script is used to generate the list of endpoints necessary for E2E testing
#
# inputs:
#
# - FLIGHTCTL_NS = namespace where flightctl external services are installed
# - KUBECONFIG = path to kubeconfig file, otherwise the default is used
# - KUBETCL_ARGS = extra arguments to kubectl (i.e. context selection, etc.)

FLIGHTCTL_NS=${FLIGHTCTL_NS:-flightctl}
KUBECTL_ARGS=${KUBECTL_ARGS:-}

SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"

IP=$(get_ext_ip)

function get_endpoint_host() {
    local name=$1
    kubectl get route "${name}" -n "${FLIGHTCTL_NS}" -o jsonpath='{.spec.host}' ${KUBECTL_ARGS} 2>/dev/null || \
    kubectl get ingress "${name}" -n "${FLIGHTCTL_NS}" -o jsonpath='{.items[0].spec.rules[0].host}' ${KUBECTL_ARGS} 2>/dev/null || \

    # if we cannot find the route or ingress, we assume this is a kind based deployment, and we use the
    # nodeport services instead pointing to our local IP address
    case "${name}" in
        flightctl-api-route)
            echo "api.${IP}.nip.io:3443"
            ;;
        flightctl-api-route-agent)
            echo "agent-api.${IP}.nip.io:7443"
            ;;
        flightctl-ui)
            echo "ui.${IP}.nip.io:9000"
            ;;
        *)
            echo "Unable to find endpoint for ${name}" >&2
            exit 1
            ;;
    esac
}

function get_endpoints() {
  export FLIGHTCTL_API_ENDPOINT=${FLIGHTCTL_API_ENDPOINT:-https://$(get_endpoint_host "flightctl-api-route")}
  export FLIGHTCTL_AGENT_ENDPOINT=${FLIGHTCTL_AGENT_ENDPOINT:-https://$(get_endpoint_host "flightctl-api-route-agent")}
  export FLIGHTCTL_UI_ENDPOINT=${FLIGHTCTL_UI_ENDPOINT:-https://$(get_endpoint_host "flightctl-ui")}
}

function get_token() {
  if ! oc whoami -t 2>/dev/null; then
    if [ -z "${KUBEADMIN_PASS}" ]; then
      echo "KUBEADMIN_PASS is not set. Please set it to the kubeadmin password, or login as kubeadmin before calling this script" >&2
      exit 1
    fi
    oc login -u kubeadmin -p ${KUBEADMIN_PASS} >/dev/null
    oc whoami -t
  fi
}

function try_login() {
  # if we can list devices, we are good
  bin/flightctl get devices && return 0
  get_endpoints
  echo "Trying no-auth login"
  if ! bin/flightctl login "${FLIGHTCTL_API_ENDPOINT}" --insecure-skip-tls-verify; then
    echo "Trying token login"
    TOKEN=$(get_token)
    if ! bin/flightctl login "${FLIGHTCTL_API_ENDPOINT}" --insecure-skip-tls-verify --token "${TOKEN}"; then
      echo "Trying standalone login"
      PASS=$(kubectl get secret keycloak-demouser-secret -n "${FLIGHTCTL_NS}" -o json | jq -r '.data.password' | base64 -d)
      bin/flightctl login -k "${FLIGHTCTL_API_ENDPOINT}" -u demouser -p ${PASS} 2>/dev/null
      return 0
    fi
  fi
}

# Function to determine the correct COPR repository based on the FLIGHTCTL_RPM variable
function copr_repo() {
    # split FLIGHTCTL_RPM by the '/' character in two variables
    local REPO_NAME=$(echo "${FLIGHTCTL_RPM}" | cut -d'/' -f1)
    if [[ "${REPO_NAME}" == "release" ]]; then
        echo "@redhat-et/flightctl"
    else
        echo "@redhat-et/flightctl-dev"
    fi
}

# Function to append the RPM version to the specified package name based on the FLIGHTCTL_RPM variable
function append_rpm_version() {
    local pkgname="${1}"
    # check if FLIGHTCTL_RPM contains the '/' character
     if [[ "${FLIGHTCTL_RPM}" == *"/"* ]]; then
        echo "${pkgname}-${FLIGHTCTL_RPM##*/}"
    else
        echo "${pkgname}"
    fi
}

# Function to generate the package name for the flightctl agent with the appropriate version
function package_agent() {
    local VERSION=$(echo "${FLIGHTCTL_RPM}" | cut -d'/' -f2)
    append_rpm_version "flightctl-agent"
}

# Function to generate the package name for the flightctl CLI with the appropriate version
function package_cli() {
    local VERSION=$(echo "${FLIGHTCTL_RPM}" | cut -d'/' -f2)
    append_rpm_version "flightctl"
}

# Function to check if acm is installed in the env
function is_acm_installed() {
  local output
  output=$(oc get multiclusterhub -A 2>/dev/null) || return 1
  echo "output=${output}"

  if echo "$output" | grep -qE 'Paused|Running'; then
    return 0
  else
    return 1
  fi
}

# Function to get the ocp nodes network name
function get_ocp_nodes_network() {
  ip=$(/usr/local/bin/oc get node -owide --no-headers | tail -n 1 | awk '{print $6}') || return 1
  if [[ -z "$ip" ]]; then
    echo "No nodes found" >&2
    return 1
  fi
   ip=${ip%.*}
  if [[ -z "$ip" ]]; then
    echo "Invalid IP format" >&2
    return 1
  fi

  # get the network name from the ip
  for net in $(sudo virsh net-list --name); do
    if [[ "$(sudo virsh net-dumpxml $net |grep $ip)" != "" ]];
      then echo $net;
      break;
    fi;
  done
}

# download_brew_rpms downloads RPMs from brew registry to a target directory
# Usage: download_brew_rpms <target_dir> [required_patterns...]
# Environment Variables:
#   BREW_BUILD_URL - Full URL to brew page (required)
# Example: BREW_BUILD_URL="https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=68817381" download_brew_rpms "bin/brew-rpm" "flightctl-agent-*" "flightctl-selinux*"
download_brew_rpms() {
    local target_dir="$1"
    shift 1
    local required_patterns=("$@")

    # Check if BREW_BUILD_URL is set
    if [[ -z "${BREW_BUILD_URL:-}" ]]; then
        echo "ERROR: BREW_BUILD_URL environment variable is required"
        return 1
    fi

    mkdir -p "${target_dir}"
    echo "🧹 Cleaning ${target_dir} directory of old builds..."
    rm -f "${target_dir}"/*.rpm "${target_dir}"/flightctl 2>/dev/null || true

    cd "${target_dir}"

    # Use BREW_BUILD_URL directly
    local brew_url="${BREW_BUILD_URL}"
    echo "Using BREW_BUILD_URL: ${brew_url}"

    # Fetch and validate brew page
    echo "Fetching RPM URLs from brew..."
    local brew_page
    brew_page=$(curl -k -s "${brew_url}")
    if [ $? -ne 0 ]; then
        echo "ERROR: Failed to fetch brew page from URL: ${brew_url}"
        return 1
    fi

    local rpm_urls
    rpm_urls=$(echo "${brew_page}" | grep -oP 'https://[^"]+\.rpm')

    if [[ -z "${rpm_urls}" ]]; then
        echo "ERROR: No RPM URLs found in brew page"
        echo "Brew URL: ${brew_url}"
        echo "Brew page content:"
        echo "${brew_page}" | head -20
        return 1
    fi

    # Download RPMs
    echo "Downloading RPMs..."
    while IFS= read -r url; do
        local filename=$(basename "$url")
        echo "Downloading $filename..."
        if wget --no-check-certificate -O "$filename" "$url"; then
            echo "✅ Successfully downloaded $filename"
        else
            echo "❌ Failed to download $filename"
            return 1
        fi
    done <<< "${rpm_urls}"

    # Verify required patterns
    for pattern in "${required_patterns[@]}"; do
        if ! ls ${pattern} >/dev/null 2>&1; then
            echo "ERROR: Required RPM pattern '${pattern}' not found in brew page"
            echo "Brew URL: ${brew_url}"
            return 1
        fi
    done

    cd - > /dev/null
    return 0
}