#!/usr/bin/env bash
# -----------------------------------------------------------------------------
# This script caches the list of PHP installations via Homebrew and generates
# shell aliases for each installation. Both the brew list and the generated
# alias definitions are stored in the XDG cache directory.
#
# If the brew list cache is invalid (older than CACHE_TTL), then both caches are
# regenerated. Otherwise, if only the alias cache is stale, it is regenerated
# from the brew list cache.
#
# Usage:
#   source x-set-php-aliases.sh
#
# (C) 2023, 2025 Ismo Vuorinen. All Rights Reserved.
# -----------------------------------------------------------------------------

set -euo pipefail

# Set verbosity level (0 by default; set to 1 or 2 for more detail)
VERBOSE="${VERBOSE:-0}"
[ "$VERBOSE" = "2" ] && set -x

# Exit early if Homebrew is not installed.
if ! command -v brew &> /dev/null; then
  echo "Homebrew is not installed. Exiting."
  exit 0
fi

# Determine Homebrew's prefix.
HOMEBREW_PREFIX="${HOMEBREW_PREFIX:-$(brew --prefix)}"

# Determine the XDG cache directory (default to ~/.cache).
XDG_CACHE="${XDG_CACHE_HOME:-$HOME/.cache}"
CACHE_DIR="${XDG_CACHE}/x-set-php-aliases"
mkdir -p "$CACHE_DIR"

# Define cache file paths.
BREW_LIST_CACHE="${CACHE_DIR}/brew_list.cache"
ALIASES_CACHE="${CACHE_DIR}/aliases.cache"

# Cache time-to-live in seconds (here 300 seconds = 5 minutes).
CACHE_TTL=300

# -----------------------------------------------------------------------------
# Function: cache_is_valid
#   Returns 0 if the file exists and its modification time is within TTL.
# -----------------------------------------------------------------------------
cache_is_valid()
{
  local file="$1"
  local ttl="$2"
  if [[ -f "$file" ]]; then
    local mod_time
    if stat --version &> /dev/null; then
      mod_time=$(stat -c %Y "$file")
    else
      mod_time=$(stat -f %m "$file")
    fi
    local current_time
    current_time=$(date +%s)
    if ((current_time - mod_time < ttl)); then
      return 0
    fi
  fi
  return 1
}

# -----------------------------------------------------------------------------
# Function: generate_aliases
#   Reads PHP formulas (one per line) from the specified file and prints out
#   alias definitions for each valid PHP installation.
#
#   The following aliases are created (assuming the formula is "php@80"):
#
#     p80r  : Raw PHP (executable only)
#     p80   : PHP with an error reporting flag enabled
#     p80s  : Launches a PHP local server at localhost:9000
#     p80c  : Runs composer (if found) using this PHP and error reporting flag
# -----------------------------------------------------------------------------
generate_aliases()
{
  local brew_file="$1"
  local php_error_reporting='-d error_reporting=22527'
  local composer_path
  composer_path=$(command -v composer 2> /dev/null || true)

  while IFS= read -r version || [[ -n "$version" ]]; do
    # Remove any leading/trailing whitespace.
    version=$(echo "$version" | xargs)
    [[ -z "$version" ]] && continue

    # Compute an alias name: remove dots and replace "php@" with "p"
    local php_abbr="${version//\./}"
    local php_alias="${php_abbr//php@/p}"

    local php_exec="${HOMEBREW_PREFIX}/opt/${version}/bin/php"
    if [[ -x "$php_exec" ]]; then
      echo "alias ${php_alias}r='$php_exec'"
      echo "alias $php_alias='$php_exec $php_error_reporting'"
      echo "alias ${php_alias}s='$php_exec -S localhost:9000'"
      if [[ -n "$composer_path" ]]; then
        echo "alias ${php_alias}c='$php_exec $php_error_reporting $composer_path'"
      fi
    else
      [[ "$VERBOSE" -ge 1 ]] && echo "Executable not found: $php_exec (skipping alias for $version)"
    fi
  done < "$brew_file"
}

# -----------------------------------------------------------------------------
# Main Cache Update Logic
#
# If the brew list cache is stale (or missing), regenerate it and the aliases.
# If only the alias cache is stale, regenerate just the alias cache.
# -----------------------------------------------------------------------------
if ! cache_is_valid "$BREW_LIST_CACHE" "$CACHE_TTL"; then
  [[ "$VERBOSE" -ge 1 ]] && echo "Brew list cache is stale or missing. Regenerating brew list and aliases."
  # Regenerate the brew list cache (filtering only PHP formulas).
  brew list | grep '^php' > "$BREW_LIST_CACHE"
  # Generate the aliases cache from the new brew list.
  generate_aliases "$BREW_LIST_CACHE" > "$ALIASES_CACHE"
else
  [[ "$VERBOSE" -ge 1 ]] && echo "Using cached brew list from $BREW_LIST_CACHE."
  if ! cache_is_valid "$ALIASES_CACHE" "$CACHE_TTL"; then
    [[ "$VERBOSE" -ge 1 ]] && echo "Alias cache is stale or missing. Regenerating aliases."
    generate_aliases "$BREW_LIST_CACHE" > "$ALIASES_CACHE"
  fi
fi

# Source the cached alias definitions.
if [[ -f "$ALIASES_CACHE" ]]; then
  # shellcheck source=/dev/null
  source "$ALIASES_CACHE"
  [[ "$VERBOSE" -ge 1 ]] && echo "Aliases loaded from cache."
else
  [[ "$VERBOSE" -ge 1 ]] && echo "No alias cache found; no aliases were loaded."
fi
