#!/usr/bin/env bash
# ai-consultants - npm/npx entry point
# Resolves symlinks (created by npm) and delegates to the real scripts.
set -euo pipefail

# --- Resolve symlinks to find the real project root ---
SOURCE="${BASH_SOURCE[0]}"
while [ -L "$SOURCE" ]; do
  DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
  SOURCE="$(readlink "$SOURCE")"
  # Resolve relative symlink
  [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE"
done
BIN_DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
PROJECT_ROOT="$(cd -P "$BIN_DIR/.." && pwd)"
SCRIPTS_DIR="$PROJECT_ROOT/scripts"

load_public_registry() {
  # Keep `version` and the lightweight malformed-install diagnostic usable even
  # when a partial installation lacks the optional public registry file.
  if [ ! -f "$SCRIPTS_DIR/public_registry.sh" ]; then
    echo "Error: public registry missing at $SCRIPTS_DIR/public_registry.sh" >&2
    return 1
  fi
  # shellcheck source=../scripts/public_registry.sh
  source "$SCRIPTS_DIR/public_registry.sh"
}

# --- Ensure execute permissions (npm can strip them) ---
ensure_permissions() {
  local needs_fix=false
  for f in "$SCRIPTS_DIR"/*.sh "$SCRIPTS_DIR"/lib/*.sh; do
    [ -f "$f" ] && [ ! -x "$f" ] && needs_fix=true && break
  done
  if [ "$needs_fix" = true ]; then
    chmod +x "$SCRIPTS_DIR"/*.sh 2>/dev/null || true
    chmod +x "$SCRIPTS_DIR"/lib/*.sh 2>/dev/null || true
  fi
}
ensure_permissions

# --- Version ---
# Single source of truth: scripts/config.sh AI_CONSULTANTS_VERSION.
# We grep instead of sourcing to avoid pulling in the full config (cost).
# The sed pipeline succeeds even when its regex doesn't match (it returns
# the input verbatim), so we explicitly validate the result is semver — else
# the help banner would print garbage like "vAI_CONSULTANTS_VERSION=2.12.0".
VERSION=$(grep -E '^AI_CONSULTANTS_VERSION=' "$SCRIPTS_DIR/config.sh" 2>/dev/null \
    | head -1 | sed -E 's/.*"([^"]+)".*/\1/' || true)
if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+ ]]; then
    VERSION="unknown"
fi

# --- Subcommand routing ---
case "${1:-}" in
  version|--version|-v)
    echo "ai-consultants v$VERSION"
    exit 0
    ;;
  help|--help|-h)
    load_public_registry || exit 1
    cat <<EOF
ai-consultants v$VERSION - Cross-vendor AI coverage panel

Usage:
  ai-consultants "question" [files...]        Consult AI experts
  ai-consultants --mode <name> "question"     Use a public mode
  ai-consultants --preset <name> "question"   Use a configuration preset
  ai-consultants --strategy <name> "question" Use a synthesis strategy
  ai-consultants doctor [--fix] [--json]      Run diagnostics
  ai-consultants configure [options]          Auto-configure all persistent settings
  ai-consultants update-clis [--dry-run]      Check & update installed consultant CLIs
  ai-consultants init [--force]               Scaffold ~/.config/ai-consultants/{config.sh,.env}
  ai-consultants install                      Install slash commands to ~/.claude/commands/
  ai-consultants version                      Show version
  ai-consultants help                         Show this help

Modes:      $(registry_mode_rows | cut -d'|' -f1 | tr '\n' ' ' | sed 's/ $//')
Presets:    $(registry_preset_rows | cut -d'|' -f1 | tr '\n' ' ' | sed 's/ $//')
Strategies: $(registry_strategy_rows | cut -d'|' -f1 | tr '\n' ' ' | sed 's/ $//')

Examples:
  npx ai-consultants "How to optimize this SQL query?"
  npx ai-consultants --preset balanced "Redis or Memcached?"
  npx ai-consultants doctor --fix
  npx ai-consultants configure --set DEFAULT_PRESET=balanced

Documentation: https://github.com/reasance/ai-consultants
EOF
    exit 0
    ;;
  doctor)
    shift
    exec "$SCRIPTS_DIR/doctor.sh" "$@"
    ;;
  configure|config)
    shift
    exec "$SCRIPTS_DIR/configure.sh" "$@"
    ;;
  update-clis|update)
    shift
    exec "$SCRIPTS_DIR/update_clis.sh" "$@"
    ;;
  init)
    shift
    FORCE=false
    for arg in "$@"; do
      [ "$arg" = "--force" ] && FORCE=true
    done

    # Reuse the canonical resolution from lib/user_config.sh.
    # shellcheck source=../scripts/lib/user_config.sh
    source "$SCRIPTS_DIR/lib/user_config.sh"
    USER_DIR=$(get_user_config_dir)
    if [ -z "$USER_DIR" ]; then
      echo "Error: cannot resolve user config dir (HOME and XDG_CONFIG_HOME both unset)" >&2
      echo "       export AI_CONSULTANTS_CONFIG_DIR=/path/to/your/config to override" >&2
      exit 1
    fi

    # Refuse to write through a symlinked dir — protects against root running
    # init when ~/.config/ai-consultants is a symlink to a sensitive path.
    if [ -L "$USER_DIR" ]; then
      echo "Error: $USER_DIR is a symlink. Refusing to scaffold into it." >&2
      echo "       Remove the symlink, or point AI_CONSULTANTS_CONFIG_DIR elsewhere." >&2
      exit 1
    fi

    # Pre-flight a write check so the user gets a friendly error instead of a
    # mid-scaffold mkdir/cp failure.
    parent="$(dirname "$USER_DIR")"
    if [ ! -w "$parent" ] && [ ! -d "$USER_DIR" ]; then
      echo "Error: cannot write to $parent" >&2
      echo "       export AI_CONSULTANTS_CONFIG_DIR=/path/you/can/write to override" >&2
      exit 1
    fi

    mkdir -p "$USER_DIR"
    echo "User config dir: $USER_DIR"

    # .env: copy from .env.example if present
    DEST_ENV="$USER_DIR/.env"
    SRC_ENV="$PROJECT_ROOT/.env.example"
    if [ -f "$DEST_ENV" ] && [ "$FORCE" != true ]; then
      echo "  ○ .env already exists (use --force to overwrite)"
    elif [ -f "$SRC_ENV" ]; then
      cp "$SRC_ENV" "$DEST_ENV"
      chmod 600 "$DEST_ENV"
      echo "  ✓ .env created from .env.example (chmod 600 — contains API keys)"
    else
      cat > "$DEST_ENV" <<'EOF'
# AI Consultants user environment
# KEY=value lines. Existing env vars take precedence.
# Uncomment what you want to override.

# DEFAULT_PRESET=balanced
# DEFAULT_STRATEGY=coverage
# MAX_SESSION_COST=2.00
# ENABLE_BUDGET_LIMIT=true
EOF
      chmod 600 "$DEST_ENV"
      echo "  ✓ .env created (minimal template)"
    fi

    # config.sh: minimal sourceable bash starter
    DEST_CFG="$USER_DIR/config.sh"
    if [ -f "$DEST_CFG" ] && [ "$FORCE" != true ]; then
      echo "  ○ config.sh already exists (use --force to overwrite)"
    else
      cat > "$DEST_CFG" <<'EOF'
#!/bin/bash
# ~/.config/ai-consultants/config.sh
# Sourced after .env, before scripts/config.sh defaults are applied.
# Use full bash logic. To defer to env vars, use ${VAR:-value}.
#
# Examples:
# export DEFAULT_PRESET="${DEFAULT_PRESET:-balanced}"
# export DEFAULT_STRATEGY="${DEFAULT_STRATEGY:-coverage}"
# export AFFINITY_FILE="${AFFINITY_FILE:-$HOME/.config/ai-consultants/affinity.json}"
EOF
      echo "  ✓ config.sh created (minimal template)"
    fi

    echo ""
    echo "Next steps:"
    echo "  1. Edit $DEST_ENV to set API keys and overrides"
    echo "  2. Run: ai-consultants doctor          # verify config is loaded"
    echo "  3. Run: ai-consultants \"your question\"  # use the new defaults"
    exit 0
    ;;
  install)
    COMMANDS_SRC="$PROJECT_ROOT/.claude/commands"
    COMMANDS_DST="$HOME/.claude/commands"

    # The commands cd into ${AI_CONSULTANTS_DIR:-$HOME/.claude/skills/ai-consultants}.
    # A curl | bash install lives there and outlasts any npx cache, so when a
    # complete one exists, install its own commands: they stay matched to the
    # scripts they run. Only without one do the commands point at this package.
    DEFAULT_SKILL_ROOT='${AI_CONSULTANTS_DIR:-$HOME/.claude/skills/ai-consultants}'
    default_root="$HOME/.claude/skills/ai-consultants"
    default_root_resolved=$(cd -P "$default_root" 2>/dev/null && pwd || true)
    use_default_root=false
    if [ -n "$default_root_resolved" ] && [ "$PROJECT_ROOT" != "$default_root_resolved" ] \
      && [ -x "$default_root/scripts/consult_all.sh" ] \
      && [ -x "$default_root/scripts/doctor.sh" ] \
      && [ -x "$default_root/scripts/followup.sh" ] \
      && [ -d "$default_root/.claude/commands" ] \
      && grep -q '^name: ai-consultants$' "$default_root/SKILL.md" 2>/dev/null; then
      use_default_root=true
      COMMANDS_SRC="$default_root/.claude/commands"
      default_version=$(grep -E '^AI_CONSULTANTS_VERSION=' "$default_root/scripts/config.sh" 2>/dev/null \
        | head -1 | sed -E 's/.*"([^"]+)".*/\1/' || true)
      echo "Using the existing installation at $default_root (v${default_version:-unknown})"
      if [ "$default_version" != "$VERSION" ]; then
        echo "Note: this package is v$VERSION. To upgrade that installation run:" >&2
        echo "      bash \"$default_root/scripts/install.sh\" --update" >&2
      fi
    fi

    if [ ! -d "$COMMANDS_SRC" ]; then
      echo "Error: slash commands directory not found at $COMMANDS_SRC" >&2
      exit 1
    fi
    mkdir -p "$COMMANDS_DST"

    # Prune commands this project no longer ships, before copying the current
    # set in. Copying alone leaves a removed command installed forever: the
    # v2.10.0 consolidation dropped ten, and config-features among them still
    # tells users to set ENABLE_REFLECTION, which v2.23.0 removed and
    # `configure --set` now rejects. scripts/install.sh does the same for the
    # curl | bash path — both entry points must prune or npx users keep them.
    pruned=0
    for f in "$COMMANDS_DST"/ai-consultants:*.md; do
      [ -e "$f" ] || continue
      if [ ! -f "$COMMANDS_SRC/$(basename "$f")" ]; then
        rm -f "$f"
        pruned=$((pruned + 1))
      fi
    done
    if [ "$pruned" -gt 0 ]; then
      echo "Pruned $pruned slash command(s) removed in a previous release"
    fi

    # Without a usable default install, point the default at this package
    # root so the installed commands can run.
    rewrite_root=""
    if [ "$use_default_root" = false ] && [ "$PROJECT_ROOT" != "$default_root_resolved" ]; then
      # The root lands inside "${AI_CONSULTANTS_DIR:-<root>}", where Bash also
      # treats a single quote as quoting: an unmatched one is a syntax error.
      case "$PROJECT_ROOT" in
        *'"'*|*"'"*|*'$'*|*'`'*|*'\'*)
          echo "Warning: package path contains shell metacharacters; set AI_CONSULTANTS_DIR=$PROJECT_ROOT before using the slash commands" >&2
          ;;
        *)
          rewrite_root="$PROJECT_ROOT"
          ;;
      esac
      case "$PROJECT_ROOT" in
        */_npx/*)
          echo "Warning: this package runs from the npx cache ($PROJECT_ROOT), which npm may delete." >&2
          echo "         For stable slash commands run: npm install -g ai-consultants && ai-consultants install" >&2
          ;;
      esac
    fi

    copied=0
    for f in "$COMMANDS_SRC"/ai-consultants:*.md; do
      [ -f "$f" ] || continue
      dest="$COMMANDS_DST/$(basename "$f")"
      if [ -n "$rewrite_root" ]; then
        # awk index/substr: a literal replacement, independent of Bash
        # version quirks in ${var//pattern/replacement} (e.g. "&" in 5.2).
        awk -v old="$DEFAULT_SKILL_ROOT" -v new="\${AI_CONSULTANTS_DIR:-$rewrite_root}" '
          { out = ""; line = $0
            while ((i = index(line, old)) > 0) {
              out = out substr(line, 1, i - 1) new
              line = substr(line, i + length(old))
            }
            print out line }' "$f" > "$dest"
      else
        cp "$f" "$dest"
      fi
      copied=$((copied + 1))
    done
    if [ "$copied" -eq 0 ]; then
      echo "Warning: no slash command files found in $COMMANDS_SRC" >&2
      exit 1
    fi
    echo "Installed $copied slash commands to $COMMANDS_DST"
    exit 0
    ;;
  *)
    # Pass everything through to consult_all.sh
    exec "$SCRIPTS_DIR/consult_all.sh" "$@"
    ;;
esac
