#!/bin/bash
# ============================================================================
# TITAN AI - ONE-CLICK SMART RUNNER (Linux / macOS)
# Copyright (c) 2026 TITAN AI LLC - All Rights Reserved
# Patent Pending - USPTO App# 19/645,524
# ============================================================================
#
# ONE COMMAND. Auto-installs EVERYTHING missing (Python, cloud CLIs), auths
# you into your clouds, validates license, downloads signed bundle, runs
# CONDUCTOR. No manual steps. Works on Ubuntu / Debian / Fedora / RHEL /
# Oracle Linux / Arch / macOS / WSL2.
#
#   curl -fsSL https://titanaisec.com/titanai-run.sh | bash
#
# With license preset:
#   curl -fsSL https://titanaisec.com/titanai-run.sh | \
#     TITAN_LICENSE=TITAN-XXX-XXX-XXX bash
#
# Non-interactive (CI/CD):
#   TITAN_LICENSE=... TITAN_NON_INTERACTIVE=1 TITAN_CLOUDS=azure,aws \
#     bash -c "$(curl -fsSL https://titanaisec.com/titanai-run.sh)"
# ============================================================================

set -u

INSTALL_DIR="${TITAN_INSTALL_DIR:-$HOME/.titanai}"
CONFIG_DIR="${TITAN_CONFIG_DIR:-$HOME/.titan-ai}"
# Channel / version selection. The installer resolves the concrete bundle URL
# via /api/bundle?channel= unless TITAN_BUNDLE_URL / TITAN_VERSION is set
# explicitly (pinning to a known-good for rollback scenarios).
CHANNEL="${TITAN_CHANNEL:-stable}"          # stable | canary | edge
VERSION="${TITAN_VERSION:-}"                # e.g. "v1.0.0" — pins exactly
CHANNEL_URL="${TITAN_CHANNEL_URL:-https://titanaisec.com/api/bundle}"
BUNDLE_URL="${TITAN_BUNDLE_URL:-}"          # blank = resolve via CHANNEL_URL
VERIFY_URL="${TITAN_VERIFY_URL:-https://titanaisec.com/api/license/verify}"
NON_INTERACTIVE="${TITAN_NON_INTERACTIVE:-0}"
LICENSE="${TITAN_LICENSE:-${TITAN_LICENSE_KEY:-}}"
# Comma-separated: which clouds to auto-install CLIs for. Default: all 3.
CLOUDS="${TITAN_CLOUDS:-azure,aws,gcp}"

# --flag parsing for rollback / channel pinning. Kept simple — no getopt
# dependency — since this script may run via `curl | bash` without args being
# passed through the usual channel.
while [ "${1:-}" != "" ]; do
  case "$1" in
    --version=*)  VERSION="${1#*=}"; shift ;;
    --version)    VERSION="${2:-}";  shift 2 ;;
    --channel=*)  CHANNEL="${1#*=}"; shift ;;
    --channel)    CHANNEL="${2:-}";  shift 2 ;;
    --license=*)  LICENSE="${1#*=}"; shift ;;
    --license)    LICENSE="${2:-}";  shift 2 ;;
    *) shift ;;
  esac
done

# Resolve bundle URL if not explicitly overridden.
if [ -z "$BUNDLE_URL" ]; then
  if [ -n "$VERSION" ]; then
    BUNDLE_URL="https://titanaisec.com/bundles/titanai-${VERSION}.tar.gz"
  else
    # Ask the license server which version this channel points to.
    resolved=$(curl -fsSL "${CHANNEL_URL}?channel=${CHANNEL}" 2>/dev/null || true)
    BUNDLE_URL=$(printf '%s' "$resolved" | grep -oE '"bundle_url":[[:space:]]*"[^"]+"' | head -1 | sed 's/.*"\(https:[^"]*\)"/\1/')
    if [ -z "$BUNDLE_URL" ]; then
      # Fallback: legacy "latest" artifact
      BUNDLE_URL="https://titanaisec.com/bundles/titanai-latest.tar.gz"
    fi
  fi
fi

say()  { printf "\033[1;36m[TITAN]\033[0m %s\n" "$*"; }
ok()   { printf "\033[1;32m  [OK]\033[0m %s\n" "$*"; }
warn() { printf "\033[1;33m  [..]\033[0m %s\n" "$*"; }
err()  { printf "\033[1;31m  [XX]\033[0m %s\n" "$*"; exit 1; }
run()  { warn "$ $*"; "$@" || err "Command failed: $*"; }

# ---------------------------------------------------------------------------
echo ""
echo "================================================================"
echo "  TITAN AI - ONE-CLICK SMART RUNNER"
echo "  Auto-installs Python + cloud CLIs + runs CONDUCTOR"
echo "================================================================"
echo ""

# ---------------------------------------------------------------------------
# 1. Detect OS + package manager
# ---------------------------------------------------------------------------
say "[1/8] Detecting environment..."
OS="$(uname -s)"
ARCH="$(uname -m)"
SUDO=""
if command -v sudo >/dev/null 2>&1 && [ "$(id -u)" != "0" ]; then SUDO="sudo"; fi

if [ "$OS" = "Linux" ]; then
  if [ -f /etc/os-release ]; then
    DISTRO=$(. /etc/os-release && echo "${ID:-linux}")
  else
    DISTRO="linux"
  fi
  case "$DISTRO" in
    ubuntu|debian|kali|raspbian)                     PKG="apt" ;;
    fedora|rhel|centos|ol|rocky|almalinux|oracle)    PKG="dnf" ;;
    arch|manjaro|artix|endeavouros)                  PKG="pacman" ;;
    alpine)                                          PKG="apk" ;;
    opensuse*|sles)                                  PKG="zypper" ;;
    *) warn "Unknown distro: $DISTRO - best-effort install"; PKG="apt" ;;
  esac
elif [ "$OS" = "Darwin" ]; then
  DISTRO="macos"
  PKG="brew"
else
  err "Unsupported OS: $OS - use titanai-run.ps1 on Windows"
fi
ok "OS=$OS  distro=$DISTRO  arch=$ARCH  package-manager=$PKG"

apt_install()    { $SUDO apt-get update -y >/dev/null 2>&1 && $SUDO apt-get install -y "$@" >/dev/null 2>&1; }
dnf_install()    { $SUDO dnf install -y "$@" >/dev/null 2>&1; }
pacman_install() { $SUDO pacman -Sy --noconfirm "$@" >/dev/null 2>&1; }
apk_install()    { $SUDO apk add --no-cache "$@" >/dev/null 2>&1; }
zypper_install() { $SUDO zypper install -y "$@" >/dev/null 2>&1; }
brew_install()   { brew install "$@" >/dev/null 2>&1; }
pkg_install() {
  case "$PKG" in
    apt)    apt_install "$@" ;;
    dnf)    dnf_install "$@" ;;
    pacman) pacman_install "$@" ;;
    apk)    apk_install "$@" ;;
    zypper) zypper_install "$@" ;;
    brew)   brew_install "$@" ;;
  esac
}

# ---------------------------------------------------------------------------
# 2. Auto-install core tools (python3, pip, curl, unzip, tar)
# ---------------------------------------------------------------------------
say "[2/8] Ensuring core tools are installed..."
NEEDS_CORE=""
command -v python3 >/dev/null 2>&1 || NEEDS_CORE="$NEEDS_CORE python3"
command -v pip3    >/dev/null 2>&1 || command -v pip >/dev/null 2>&1 || NEEDS_CORE="$NEEDS_CORE pip"
command -v curl    >/dev/null 2>&1 || NEEDS_CORE="$NEEDS_CORE curl"
command -v unzip   >/dev/null 2>&1 || NEEDS_CORE="$NEEDS_CORE unzip"
command -v tar     >/dev/null 2>&1 || NEEDS_CORE="$NEEDS_CORE tar"

if [ -n "$NEEDS_CORE" ]; then
  warn "Installing missing: $NEEDS_CORE"
  if [ "$PKG" = "brew" ] && ! command -v brew >/dev/null 2>&1; then
    warn "Homebrew missing - installing (macOS)"
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  fi
  case "$PKG" in
    apt)    pkg_install python3 python3-venv python3-pip curl unzip tar ;;
    dnf)    pkg_install python3 python3-pip curl unzip tar ;;
    pacman) pkg_install python python-pip curl unzip tar ;;
    apk)    pkg_install python3 py3-pip curl unzip tar bash ;;
    zypper) pkg_install python3 python3-pip curl unzip tar ;;
    brew)   pkg_install python curl unzip ;;
  esac
fi
ok "python3: $(python3 --version 2>&1)"
ok "pip / curl / tar / unzip: OK"

# ---------------------------------------------------------------------------
# 3. Auto-install cloud CLIs (if not present and if client wants them)
# ---------------------------------------------------------------------------
say "[3/8] Auto-installing cloud CLIs..."
install_azure_cli() {
  command -v az >/dev/null 2>&1 && { ok "Azure CLI already installed"; return 0; }
  case "$PKG" in
    apt)    curl -sL https://aka.ms/InstallAzureCLIDeb | $SUDO bash >/dev/null 2>&1 ;;
    dnf)    $SUDO rpm --import https://packages.microsoft.com/keys/microsoft.asc
            $SUDO dnf install -y https://packages.microsoft.com/config/rhel/8/packages-microsoft-prod.rpm >/dev/null 2>&1
            pkg_install azure-cli ;;
    pacman) warn "az: install from AUR manually if needed"; return 1 ;;
    apk)    apk_install py3-pip && pip3 install --break-system-packages azure-cli >/dev/null 2>&1 ;;
    brew)   pkg_install azure-cli ;;
    *)      warn "Cannot auto-install az on $PKG"; return 1 ;;
  esac
  command -v az >/dev/null 2>&1 && ok "Azure CLI installed" || warn "Azure CLI install may have failed - verify manually"
}
install_aws_cli() {
  command -v aws >/dev/null 2>&1 && { ok "AWS CLI already installed"; return 0; }
  ARCH_AWS="x86_64"; [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ] && ARCH_AWS="aarch64"
  case "$OS" in
    Linux)
      curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-${ARCH_AWS}.zip" -o /tmp/aws.zip
      unzip -oq /tmp/aws.zip -d /tmp/aws-install
      $SUDO /tmp/aws-install/aws/install >/dev/null 2>&1 || /tmp/aws-install/aws/install --install-dir "$HOME/.aws-cli" --bin-dir "$HOME/.local/bin" >/dev/null 2>&1
      rm -rf /tmp/aws.zip /tmp/aws-install ;;
    Darwin)
      pkg_install awscli ;;
  esac
  command -v aws >/dev/null 2>&1 && ok "AWS CLI installed" || warn "AWS CLI install may have failed"
}
install_gcp_cli() {
  command -v gcloud >/dev/null 2>&1 && { ok "GCP CLI already installed"; return 0; }
  case "$PKG" in
    apt|dnf|pacman|zypper|apk)
      curl -fsSL https://sdk.cloud.google.com -o /tmp/gcp-install.sh
      CLOUDSDK_CORE_DISABLE_PROMPTS=1 bash /tmp/gcp-install.sh --disable-prompts --install-dir="$HOME" >/dev/null 2>&1
      export PATH="$HOME/google-cloud-sdk/bin:$PATH" ;;
    brew)   pkg_install --cask google-cloud-sdk ;;
  esac
  command -v gcloud >/dev/null 2>&1 && ok "GCP CLI installed" || warn "GCP CLI install may have failed"
}

# Install each cloud CLI if it's in the user's TITAN_CLOUDS list
case ",$CLOUDS," in *,azure,*) install_azure_cli ;; esac
case ",$CLOUDS," in *,aws,*)   install_aws_cli ;; esac
case ",$CLOUDS," in *,gcp,*)   install_gcp_cli ;; esac

# ---------------------------------------------------------------------------
# 4. License prompt (reuse if cached)
# ---------------------------------------------------------------------------
say "[4/8] License..."
if [ -z "$LICENSE" ] && [ -f "$CONFIG_DIR/license.json" ]; then
  LICENSE=$(python3 -c "import json; print(json.load(open('$CONFIG_DIR/license.json')).get('license_key',''))" 2>/dev/null || echo "")
  [ -n "$LICENSE" ] && ok "Reusing cached license from $CONFIG_DIR/license.json"
fi
if [ -z "$LICENSE" ]; then
  if [ "$NON_INTERACTIVE" = "1" ]; then
    err "TITAN_LICENSE env var required in non-interactive mode"
  fi
  printf "  Paste your TITAN AI license key: "
  read -r LICENSE </dev/tty 2>/dev/null || read -r LICENSE
  [ -z "$LICENSE" ] && err "No license - email info@titanai.tech to request one"
fi

# ---------------------------------------------------------------------------
# 5. Download + install TITAN AI bundle
# ---------------------------------------------------------------------------
say "[5/8] Downloading TITAN AI bundle..."
mkdir -p "$INSTALL_DIR"
cd "$INSTALL_DIR" || err "Cannot cd to $INSTALL_DIR"

# Call license-verify server (soft-fail: continue if server unreachable — bundle is license-keyed anyway)
VERIFY_RESP=$(curl -fsSL -X POST "$VERIFY_URL" \
  -H "Content-Type: application/json" \
  -d "{\"license_key\":\"$LICENSE\",\"host\":\"$(hostname 2>/dev/null || echo unknown)\",\"os\":\"$OS\"}" \
  2>/dev/null || echo '{"valid":true,"tier":"trial-14d","expires_at":"2099-01-01T00:00:00Z"}')
VALID=$(echo "$VERIFY_RESP" | python3 -c 'import sys,json;print(json.load(sys.stdin).get("valid",False))' 2>/dev/null || echo "False")
TIER=$(echo "$VERIFY_RESP"  | python3 -c 'import sys,json;print(json.load(sys.stdin).get("tier","trial-14d"))' 2>/dev/null || echo "trial-14d")
EXPIRES=$(echo "$VERIFY_RESP" | python3 -c 'import sys,json;print(json.load(sys.stdin).get("expires_at","n/a"))' 2>/dev/null || echo "n/a")

if [ "$VALID" != "True" ]; then
  err "License invalid or server unreachable: $VERIFY_RESP"
fi
ok "License valid - tier=$TIER  expires=$EXPIRES"

curl -fsSL "$BUNDLE_URL" -o titanai-bundle.tar.gz || err "Bundle download failed from $BUNDLE_URL"
EXPECTED_SHA=$(curl -fsSL "${BUNDLE_URL}.sha256" 2>/dev/null | tr -d ' \n')
if [ -n "$EXPECTED_SHA" ] && command -v sha256sum >/dev/null 2>&1; then
  GOT_SHA=$(sha256sum titanai-bundle.tar.gz | cut -d' ' -f1)
  [ "$GOT_SHA" != "$EXPECTED_SHA" ] && err "Bundle SHA mismatch (expected $EXPECTED_SHA, got $GOT_SHA)"
  ok "Bundle SHA verified: $EXPECTED_SHA"
fi
tar xzf titanai-bundle.tar.gz --strip-components=1
rm -f titanai-bundle.tar.gz

# ---------------------------------------------------------------------------
# 6. Python venv + deps
# ---------------------------------------------------------------------------
say "[6/8] Installing Python dependencies into isolated venv..."
python3 -m venv .venv
# shellcheck source=/dev/null
. .venv/bin/activate
pip install --quiet --upgrade pip
pip install --quiet -r requirements.txt
ok "Dependencies installed in $INSTALL_DIR/.venv"

# Persist license
mkdir -p "$CONFIG_DIR"
cat > "$CONFIG_DIR/license.json" <<EOF
{"license_key":"$LICENSE","tier":"$TIER","expires_at":"$EXPIRES","installed_at":"$(date -u +%Y-%m-%dT%H:%M:%SZ)"}
EOF
chmod 600 "$CONFIG_DIR/license.json"
ok "License stored: $CONFIG_DIR/license.json (chmod 600)"

[ -f .env.example ] && [ ! -f .env ] && cp .env.example .env && ok "Created .env (edit to add ANTHROPIC_API_KEY if you want AI-enriched reports)"

# ---------------------------------------------------------------------------
# 7. Guided cloud auth
# ---------------------------------------------------------------------------
say "[7/8] Cloud authentication..."
if command -v az >/dev/null 2>&1 && ! az account show >/dev/null 2>&1 && [ "$NON_INTERACTIVE" = "0" ]; then
  warn "Azure: not signed in - opening browser"
  az login 2>&1 | tail -5
fi
if command -v aws >/dev/null 2>&1 && ! aws sts get-caller-identity >/dev/null 2>&1 && [ "$NON_INTERACTIVE" = "0" ]; then
  warn "AWS: not signed in - running aws configure"
  aws configure </dev/tty
fi
if command -v gcloud >/dev/null 2>&1 && ! gcloud auth application-default print-access-token >/dev/null 2>&1 && [ "$NON_INTERACTIVE" = "0" ]; then
  warn "GCP: not signed in - opening browser"
  gcloud auth login 2>&1 | tail -3
  gcloud auth application-default login 2>&1 | tail -3
fi
command -v az     >/dev/null 2>&1 && az account show --query "'Azure: '+name+' ('+id+')'" -o tsv 2>/dev/null | sed 's/^/  /'
command -v aws    >/dev/null 2>&1 && aws sts get-caller-identity --query "'AWS:   '+Account+'  '+Arn" --output text 2>/dev/null | sed 's/^/  /'
command -v gcloud >/dev/null 2>&1 && echo "  GCP:   project=$(gcloud config get-value project 2>/dev/null)"

# ---------------------------------------------------------------------------
# 8. Launch CONDUCTOR
# ---------------------------------------------------------------------------
say "[8/8] Launching CONDUCTOR..."
export TITAN_LICENSE_KEY="$LICENSE"
python3 agents/conductor.py
