#!/usr/bin/env bash
set -euo pipefail

# -----------------------------
# Global Variables & Cleanup
# -----------------------------
tmp_file=$(mktemp)        # failure-only (legacy)
job_log=$(mktemp)         # GNU parallel job log
results_log=$(mktemp)     # unified results: service:connector:status:duration

cleanup() {
  local exit_code=$?
  [[ -f "$tmp_file" ]] && rm -f "$tmp_file"
  [[ -f "$job_log" ]] && rm -f "$job_log"
  [[ -f "$results_log" ]] && rm -f "$results_log"

  # Kill any stray Xvfb processes owned by this script
  pkill -P $$ Xvfb 2>/dev/null || true
  exit "$exit_code"
}
trap cleanup EXIT

# -----------------------------
# Helper Functions
# -----------------------------
print_color() {
  local color_name="$1"
  local message="$2"
  local reset='\033[0m'
  local red='\033[0;31m'
  local green='\033[0;32m'
  local yellow='\033[0;33m'
  local blue='\033[0;34m'

  case "$color_name" in
    red) echo -e "${red}${message}${reset}" ;;
    green) echo -e "${green}${message}${reset}" ;;
    yellow) echo -e "${yellow}${message}${reset}" ;;
    blue) echo -e "${blue}${message}${reset}" ;;
    *) echo -e "${message}" ;;
  esac
}
export -f print_color

command_exists() {
  command -v "$1" >/dev/null 2>&1
}

# -----------------------------
# Dependency Check
# -----------------------------
check_dependencies() {
  local dependencies=("parallel" "npm")
  for cmd in "${dependencies[@]}"; do
    if ! command_exists "$cmd"; then
      print_color red "ERROR: ${cmd} is not installed!"
      exit 1
    fi
  done

  if [[ ! -d "node_modules" ]]; then
    print_color yellow "Installing NPM dependencies..."
    npm ci
  fi

  print_color blue "Verifying Cypress binary..."
  if command_exists "xvfb-run"; then
    xvfb-run --auto-servernum npm exec cypress verify
  else
    export DISPLAY=:99
    Xvfb :99 &
    local xvfb_pid=$!
    npm exec cypress verify
    kill "$xvfb_pid" 2>/dev/null || true
  fi
  print_color green "Cypress verified."
}

# -----------------------------
# Test Execution Logic
# -----------------------------
execute_test() {
  local connector="$1"
  local service="$2"
  local failure_log="$3"
  local job_slot="${4:-1}"

  local start_ts=$(date +%s)
  local start_fmt=$(date '+%H:%M:%S')

  echo "----------------------------------------------------"
  print_color blue "[START] $service:$connector (Slot: $job_slot) at $start_fmt"
  echo "----------------------------------------------------"

  export REPORT_NAME="${service}_${connector}_report"

  # -----------------------------
  # XVFB
  # -----------------------------
  local unique_display=$((100 + job_slot))
  export DISPLAY=":${unique_display}"

  Xvfb "$DISPLAY" &
  local xvfb_pid=$!
  trap "kill $xvfb_pid 2>/dev/null || true" RETURN
  sleep 1

  # -----------------------------
  # EXECUTE TEST
  # -----------------------------
  local exit_code=0
  if ! bash -c '
        export CYPRESS_CONNECTOR="'"$connector"'"
        npm run "cypress:'"$service"'"
      '
  then
    exit_code=1
  fi

  local end_ts=$(date +%s)
  local duration=$((end_ts - start_ts))

  local status
  if [[ $exit_code -eq 0 ]]; then
    status="PASS"
    print_color green "[PASS] $service:$connector | ${duration}s"
  else
    status="FAIL"
    print_color red "[FAIL] $service:$connector | ${duration}s"
  fi

  # Always record result
  echo "${service}:${connector}:${status}:${duration}" >> "$results_log"

  # Keep legacy failure list (used for exit code)
  if [[ "$status" == "FAIL" ]]; then
    echo "${service}:${connector}" >> "$failure_log"
    return 1
  fi

  return 0
}

export -f execute_test
export -f command_exists
export -f print_color
export results_log

# -----------------------------
# Runner
# -----------------------------
run_tests() {
  local jobs="${1:-1}"

  read -r -a payments <<< "${PAYMENTS_CONNECTORS:-}"
  read -r -a payouts <<< "${PAYOUTS_CONNECTORS:-}"
  read -r -a payment_method_list <<< "${PAYMENT_METHOD_LIST:-}"
  read -r -a routing <<< "${ROUTING:-}"
  read -r -a platform <<< "${PLATFORM_CONNECTORS:-}"

  declare -A env_to_service=(
    ["PAYMENTS_CONNECTORS"]="payments"
    ["PAYOUTS_CONNECTORS"]="payouts"
    ["PAYMENT_METHOD_LIST"]="payment_method_list"
    ["ROUTING"]="routing"
    ["PLATFORM_CONNECTORS"]="platform"
  )

  local active_services=()
  for env_var in "${!env_to_service[@]}"; do
    [[ -n "${!env_var:-}" ]] && active_services+=("${env_to_service[$env_var]}")
  done

  for service in "${active_services[@]}"; do
    declare -n connectors="$service"

    if [[ ${#connectors[@]} -gt 0 ]]; then
      print_color yellow " Starting Parallel Execution for '$service' (Jobs: $jobs)"

      parallel --jobs "$jobs" \
               --delay 10 \
               --group \
               --joblog "$job_log" \
               execute_test {} "$service" "$tmp_file" {%} \
               ::: "${connectors[@]}" || true
    fi
  done

  # -----------------------------
  # Final Summary
  # -----------------------------
  if [[ -s "$results_log" ]]; then

    print_color green "\n========================================"
    print_color green " SUCCESSFUL CONNECTORS"
    print_color green "========================================"
    awk -F: '$3=="PASS" {
      printf "  • %-30s | %5ss\n", $1 ":" $2, $4
    }' "$results_log"
    print_color green "\n========================================"

    print_color red "\n========================================"
    print_color red " FAILED CONNECTORS"
    print_color red "========================================"
    awk -F: '$3=="FAIL" {
      printf "  • %-30s | %5ss\n", $1 ":" $2, $4
    }' "$results_log"
    print_color red "\n========================================"

    print_color blue "\n========================================"
    print_color blue " EXECUTION STATS"
    print_color blue "========================================"
    awk -F: '
    {
      total += $4
      count++
      if ($3=="PASS") pass++
      if ($3=="FAIL") fail++
    }
    END {
      printf "  ➜ Total connectors run: %d\n", count
      printf "  ➜ Successful: %d\n", pass
      printf "  ➜ Failed: %d\n", fail
    }' "$results_log"
  fi

  [[ -s "$tmp_file" ]] && return 1 || return 0
}

# -----------------------------
# Main
# -----------------------------
main() {
  local command="${1:-}"
  local jobs="${2:-3}"
  local test_dir="${3:-cypress-tests}"

  if [[ "$(basename "$PWD")" != "$(basename "$test_dir")" && -d "$test_dir" ]]; then
    cd "$test_dir"
  fi

  check_dependencies

  case "$command" in
    --parallel|-p) run_tests "$jobs" ;;
    *) run_tests 1 ;;
  esac
}

main "$@"
