#!/bin/bash
set -e

PTERO_DIR="/var/www/pterodactyl"
NGINX_CONF="/etc/nginx/sites-available/pterodactyl"
ADMIN_PASS_FILE="/root/.panel_admin_pass"
DB_NAME="panel"
DB_USER="pterodactyl"

GREEN='\033[32m'
BLUE='\033[34m'
YELLOW='\033[33m'
RED='\033[31m'
CYAN='\033[36m'
MAGENTA='\033[35m'
NC='\033[0m'
W='\033[97m'
BR='\033[1;31m'; BG='\033[1;32m'; BY='\033[1;33m'
BM='\033[1;35m'; BC='\033[1;36m'; BW='\033[1;97m'

msg()  { echo -e "${BLUE}[*]${NC} $1"; }
ok()   { echo -e "${GREEN}[✓]${NC} $1"; }
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
err()  { echo -e "${RED}[✗]${NC} $1"; }

[ "$EUID" -ne 0 ] && err "Run as root." && exit 1

# ─── Helpers ──────────────────────────────────────
install_deps() {
  msg "Installing system dependencies..."
  apt-get update -y
  apt-get install -y software-properties-common curl wget gnupg2 ca-certificates lsb-release ubuntu-keyring 2>/dev/null
  mkdir -p /etc/apt/keyrings
  curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
  echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" > /etc/apt/sources.list.d/nodesource.list
  apt-get update -y
  apt-get install -y php8.3 php8.3-{cli,common,gd,mysql,mbstring,bcmath,xml,fpm,curl,zip,intl} \
    composer mariadb-server mariadb-client nginx redis-server nodejs certbot python3-certbot-nginx 2>/dev/null
  npm i -g yarn 2>/dev/null
  systemctl enable --now mariadb nginx redis-server php8.3-fpm 2>/dev/null
  ok "Dependencies installed."
}

install_node20() {
  msg "Installing Node.js v20 for Blueprint compatibility..."
  mkdir -p /etc/apt/keyrings
  curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
  echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" > /etc/apt/sources.list.d/nodesource.list
  apt-get update -y
  apt-get install -y nodejs 2>/dev/null
  npm i -g yarn 2>/dev/null
  ok "Node.js $(node -v) ready."
}

install_node22() {
  msg "Installing Node.js v22..."
  mkdir -p /etc/apt/keyrings
  curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
  echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" > /etc/apt/sources.list.d/nodesource.list
  apt-get update -y
  apt-get install -y nodejs 2>/dev/null
  npm i -g yarn 2>/dev/null
  ok "Node.js $(node -v) ready."
}

# ─── Panel Install ────────────────────────────────
panel_install() {
  local VERSION=$1
  local DOMAIN

  read -p "Enter domain (e.g. panel.example.com): " DOMAIN
  [ -z "$DOMAIN" ] && err "Domain required." && return 1

  install_deps
  install_node22

  # Download
  if [ "$VERSION" = "latest" ]; then
    msg "Fetching latest Panel version..."
    LATEST=$(curl -s https://api.github.com/repos/pterodactyl/panel/releases/latest | grep '"tag_name"' | cut -d'"' -f4)
    [ -z "$LATEST" ] && err "Could not fetch latest version." && return 1
    msg "Latest: $LATEST"
    DL_URL="https://github.com/pterodactyl/panel/releases/download/${LATEST}/panel.tar.gz"
  else
    DL_URL="https://github.com/pterodactyl/panel/releases/download/v1.11.11/panel.tar.gz"
  fi

  mkdir -p "$PTERO_DIR"
  curl -Lo "$PTERO_DIR/panel.tar.gz" "$DL_URL"
  cd "$PTERO_DIR"
  tar -xzf panel.tar.gz && rm panel.tar.gz
  chown -R www-data:www-data .
  ok "Panel downloaded."

  # Composer
  msg "Installing PHP dependencies..."
  COMPOSER_ALLOW_SUPERUSER=1 php8.3 /usr/bin/composer install --no-dev --no-interaction --optimize-autoloader

  # DB
  DB_PASS=$(openssl rand -hex 16)
  mysql -e "CREATE DATABASE IF NOT EXISTS ${DB_NAME} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
  mysql -e "DROP USER IF EXISTS '${DB_USER}'@'127.0.0.1';"
  mysql -e "DROP USER IF EXISTS '${DB_USER}'@'localhost';"
  mysql -e "CREATE USER '${DB_USER}'@'127.0.0.1' IDENTIFIED BY '${DB_PASS}';"
  mysql -e "GRANT ALL PRIVILEGES ON ${DB_NAME}.* TO '${DB_USER}'@'127.0.0.1';"
  mysql -e "CREATE USER '${DB_USER}'@'localhost' IDENTIFIED BY '${DB_PASS}';"
  mysql -e "GRANT ALL PRIVILEGES ON ${DB_NAME}.* TO '${DB_USER}'@'localhost';"
  mysql -e "FLUSH PRIVILEGES;"

  # Env
  cd "$PTERO_DIR"
  cp .env.example .env
  php8.3 artisan key:generate --force
  sed -i "s|APP_URL=.*|APP_URL=\"https://${DOMAIN}\"|" .env
  sed -i "s|DB_DATABASE=.*|DB_DATABASE=${DB_NAME}|" .env
  sed -i "s|DB_USERNAME=.*|DB_USERNAME=${DB_USER}|" .env
  sed -i "s|DB_PASSWORD=.*|DB_PASSWORD=${DB_PASS}|" .env
  sed -i "s|QUEUE_CONNECTION=.*|QUEUE_CONNECTION=database|" .env
  sed -i "s|CACHE_DRIVER=.*|CACHE_DRIVER=file|" .env
  sed -i "s|SESSION_DRIVER=.*|SESSION_DRIVER=file|" .env
  sed -i "s|APP_TIMEZONE=.*|APP_TIMEZONE=Asia/Kolkata|" .env
  sed -i "s|APP_ENVIRONMENT_ONLY=.*|APP_ENVIRONMENT_ONLY=false|" .env
  chown www-data:www-data .env

  # Migrate
  msg "Running migrations..."
  php8.3 artisan migrate --seed --force

  # Admin user
  ADMIN_PASS=$(openssl rand -base64 12)
  php8.3 artisan p:user:make --email="admin@${DOMAIN}" --username="admin" \
    --name-first="Admin" --name-last="User" \
    --password="${ADMIN_PASS}" --admin=1 2>/dev/null
  echo "$ADMIN_PASS" > "$ADMIN_PASS_FILE"
  chmod 600 "$ADMIN_PASS_FILE"

  # Permissions & cron
  chown -R www-data:www-data "$PTERO_DIR"
  chmod -R 755 "$PTERO_DIR/storage" "$PTERO_DIR/bootstrap/cache"
  crontab -u www-data -l 2>/dev/null | { cat; echo "* * * * * php8.3 $PTERO_DIR/artisan schedule:run >> /dev/null 2>&1"; } | crontab -u www-data -

  # Nginx
  cat > "$NGINX_CONF" <<'NGX'
server {
    listen 80;
    server_name __DOMAIN__;
    root __PTERO__/public;
    index index.php;
    access_log /var/log/nginx/pterodactyl.access.log;
    error_log  /var/log/nginx/pterodactyl.error.log;
    location / { try_files $uri $uri/ /index.php?$query_string; }
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
    location ~ /\.ht { deny all; }
    location ~ /\.env { deny all; }
    location = /favicon.ico { log_not_found off; access_log off; }
    location = /robots.txt { allow all; log_not_found off; access_log off; }
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
        expires 365d;
        add_header Cache-Control "public, immutable";
    }
}
NGX
  sed -i "s|__DOMAIN__|${DOMAIN}|g; s|__PTERO__|${PTERO_DIR}|g" "$NGINX_CONF"
  ln -sf "$NGINX_CONF" /etc/nginx/sites-enabled/
  rm -f /etc/nginx/sites-enabled/default
  nginx -t && systemctl reload nginx

  # SSL
  certbot --nginx -d "${DOMAIN}" --non-interactive --agree-tos --email "admin@${DOMAIN}" --redirect 2>/dev/null || warn "SSL skipped (check DNS)."

  clear
  echo "╔═══════════════════════════════════════╗"
  echo "║    Panel Installed Successfully!      ║"
  echo "╚═══════════════════════════════════════╝"
  echo ""
  echo "  URL:      https://${DOMAIN}"
  echo "  Email:    admin@${DOMAIN}"
  echo "  Username: admin"
  echo "  Password: ${ADMIN_PASS}"
  echo "  DB_Pass:  ${DB_PASS}"
  echo ""
}

# ─── Blueprint Install ────────────────────────────
blueprint_install() {
  local BP_VERSION=$1

  if [ ! -f "$PTERO_DIR/artisan" ]; then
    err "Panel not installed. Install panel first."
    return 1
  fi

  cd "$PTERO_DIR"

  # Node version for blueprint
  if [ "$BP_VERSION" = "beta-A428-2" ]; then
    install_node20
  else
    install_node22
  fi

  msg "Installing Yarn dependencies..."
  yarn install --frozen-lockfile

  if [ "$BP_VERSION" = "beta-A428-2" ]; then
    BP_URL="https://github.com/BlueprintFramework/framework/archive/refs/tags/beta-A428-2.zip"
    BP_DIR="framework-beta-A428-2"
  else
    msg "Fetching latest Blueprint release..."
    BP_URL=$(curl -s https://api.github.com/repos/BlueprintFramework/framework/releases/latest \
      | grep "browser_download_url.*release.zip" | cut -d'"' -f4)
    [ -z "$BP_URL" ] && err "Could not fetch latest Blueprint." && return 1
  fi

  msg "Downloading Blueprint..."
  curl -Lo /tmp/bp.zip "$BP_URL"
  unzip -o /tmp/bp.zip -d /tmp/bp_extract

  if [ "$BP_VERSION" = "beta-A428-2" ]; then
    rsync -a "/tmp/bp_extract/$BP_DIR/" ./
  else
    rsync -a /tmp/bp_extract/ ./
  fi
  rm -rf /tmp/bp.zip /tmp/bp_extract

  echo 'WEBUSER="www-data"; OWNERSHIP="www-data:www-data"; USERSHELL="/bin/bash";' > .blueprintrc
  chown www-data:www-data .blueprintrc
  chmod +x blueprint.sh

  # Patch for Node v22 if old Blueprint
  if [ "$BP_VERSION" = "beta-A428-2" ]; then
    python3 << 'PYEOF'
import os
path = 'blueprint.sh'
with open(path) as f:
    content = f.read()
old = '&& [[ $nodeVer != "v21."* ]]; then'
new = '&& [[ $nodeVer != "v21."* ]] && [[ $nodeVer != "v22."* ]]; then'
content = content.replace(old, new)
with open(path, 'w') as f:
    f.write(content)
PYEOF
  fi

  WEBUSER="www-data" bash blueprint.sh

  chown -R www-data:www-data .
  ok "Blueprint ${BP_VERSION} installed."

  # Nebula auto-install
  if [ -f /root/nebula.blueprint ]; then
    read -p "Nebula .blueprint found in /root/. Install now? (y/N): " INSTALL_NEB
    if [[ "$INSTALL_NEB" =~ ^[Yy]$ ]]; then
      cp /root/nebula.blueprint "$PTERO_DIR/"
      chown www-data:www-data "$PTERO_DIR/nebula.blueprint"
      cd "$PTERO_DIR" && blueprint -install nebula
      ok "Nebula installed."
    fi
  fi
}

# ─── Uninstall Panel ──────────────────────────────
uninstall_panel() {
  warn "This will DELETE all panel files, database, and SSL certs."
  read -p "Confirm? (y/N): " CONFIRM
  [[ ! "$CONFIRM" =~ ^[Yy]$ ]] && msg "Cancelled." && return

  msg "Stopping services..."
  systemctl stop nginx php8.3-fpm 2>/dev/null || true

  msg "Removing files..."
  rm -rf "$PTERO_DIR"

  msg "Dropping database..."
  mysql -e "DROP DATABASE IF EXISTS ${DB_NAME};" 2>/dev/null || true
  mysql -e "DROP USER IF EXISTS '${DB_USER}'@'127.0.0.1';" 2>/dev/null || true
  mysql -e "DROP USER IF EXISTS '${DB_USER}'@'localhost';" 2>/dev/null || true

  msg "Removing Nginx config..."
  rm -f "$NGINX_CONF"
  rm -f /etc/nginx/sites-enabled/pterodactyl
  nginx -t 2>/dev/null && systemctl start nginx || true

  msg "Removing SSL certificate..."
  certbot delete --cert-name "$(cat /etc/nginx/sites-available/pterodactyl 2>/dev/null | grep server_name | head -1 | awk '{print $2}' | tr -d ';')" --non-interactive 2>/dev/null || true

  msg "Removing cron..."
  crontab -u www-data -l 2>/dev/null | grep -v "artisan schedule:run" | crontab -u www-data - 2>/dev/null || true

  rm -f "$ADMIN_PASS_FILE"
  ok "Panel uninstalled."
}

# ─── Uninstall Blueprint ──────────────────────────
uninstall_blueprint() {
  if [ ! -f "$PTERO_DIR/blueprint.sh" ]; then
    err "Blueprint not installed in $PTERO_DIR."
    return
  fi

  warn "This will remove Blueprint and all extensions!"
  read -p "Confirm? (y/N): " CONFIRM
  [[ ! "$CONFIRM" =~ ^[Yy]$ ]] && msg "Cancelled." && return

  cd "$PTERO_DIR"
  msg "Running Blueprint uninstall..."
  WEBUSER="www-data" bash blueprint.sh --remove 2>/dev/null || {
    # Manual cleanup
    rm -rf .blueprintrc blueprint.sh blueprint/ app/BlueprintFramework/ 2>/dev/null
    rm -rf resources/scripts/blueprint/ resources/views/blueprint/ 2>/dev/null
    rm -rf routes/blueprint* config/ExtensionFS.php 2>/dev/null
    rm -rf public/extensions/ public/fs/ storage/extensions/ 2>/dev/null
    mysql -e "DROP TABLE IF EXISTS ${DB_NAME}.blueprint;" 2>/dev/null || true
  }

  php8.3 artisan view:cache 2>/dev/null
  php8.3 artisan config:cache 2>/dev/null
  chown -R www-data:www-data "$PTERO_DIR"
  ok "Blueprint removed."
}

# ─── Wings Install ────────────────────────────────
install_wings() {
  local DOMAIN TOKEN

  read -p "Enter node domain (e.g. node.example.com): " DOMAIN
  [ -z "$DOMAIN" ] && err "Domain required." && return 1

  msg "Installing Docker..."
  curl -fsSL https://get.docker.com | bash
  systemctl enable --now docker

  mkdir -p /etc/pterodactyl

  msg "Downloading Wings..."
  LATEST=$(curl -s https://api.github.com/repos/pterodactyl/wings/releases/latest | grep '"tag_name"' | cut -d'"' -f4)
  [ -z "$LATEST" ] && err "Could not fetch latest Wings version." && return 1
  curl -Lo /usr/local/bin/wings "https://github.com/pterodactyl/wings/releases/download/${LATEST}/wings_linux_amd64"
  chmod +x /usr/local/bin/wings

  msg "Setting up SSL for ${DOMAIN}..."
  systemctl stop nginx 2>/dev/null || true
  certbot certonly --standalone -d "${DOMAIN}" --non-interactive --agree-tos --email "admin@${DOMAIN}" 2>/dev/null || {
    systemctl start nginx 2>/dev/null || true
    warn "SSL failed. Point DNS to this server and retry, or configure manually."
  }
  systemctl start nginx 2>/dev/null || true

  echo ""
  echo "╔══════════════════════════════════════════════╗"
  echo "║     Node Configuration Required              ║"
  echo "╠══════════════════════════════════════════════╣"
  echo "║ 1. Go to Panel Admin → Nodes → Create New    ║"
  echo "║ 2. Set domain to: ${DOMAIN}                  ║"
  echo "║ 3. Save the node, then click 'Deploy'        ║"
  echo "║ 4. Copy the auto-deploy token                ║"
  echo "╚══════════════════════════════════════════════╝"
  echo ""
  read -p "Paste the auto-deploy token: " TOKEN

  if [ -n "$TOKEN" ]; then
    cd /etc/pterodactyl
    # If they pasted the full deploy command, extract the wings part and run it
    if echo "$TOKEN" | grep -q "wings configure"; then
      WINGS_CMD=$(echo "$TOKEN" | sed 's/.*wings configure/wings configure/')
      $WINGS_CMD
    elif echo "$TOKEN" | grep -q "=ptla_"; then
      # --token=xxx format
      TOKEN_VAL=$(echo "$TOKEN" | sed 's/.*--token=\([^ ]*\).*/\1/')
      wings configure --token="$TOKEN_VAL"
    elif echo "$TOKEN" | grep -q "^ptla_"; then
      # Raw token
      wings configure --token="$TOKEN"
    else
      warn "Could not parse token. Running wings configure interactively..."
      wings configure
    fi

    if [ -f config.yml ] && [ -d "/etc/letsencrypt/live/${DOMAIN}" ]; then
      apt-get install -y python3-yaml 2>/dev/null || true
      python3 -c "
import yaml
with open('/etc/pterodactyl/config.yml') as f:
    config = yaml.safe_load(f)
config.setdefault('system', {})['ssl'] = {
    'enabled': True,
    'certificate': '/etc/letsencrypt/live/${DOMAIN}/fullchain.pem',
    'key': '/etc/letsencrypt/live/${DOMAIN}/privkey.pem'
}
with open('/etc/pterodactyl/config.yml', 'w') as f:
    yaml.dump(config, f)
" 2>/dev/null && ok "SSL configured in Wings config." || warn "Could not auto-configure SSL in config.yml (python3-yaml missing)."
    fi
  else
    warn "No token provided. Run 'wings configure --token=...' and set up manually."
  fi

  cat > /etc/systemd/system/wings.service << 'UNIT'
[Unit]
Description=Wings daemon for Pterodactyl
After=docker.service
Requires=docker.service

[Service]
User=root
WorkingDirectory=/etc/pterodactyl
ExecStart=/usr/local/bin/wings
Restart=on-failure
RestartSec=3

[Install]
WantedBy=multi-user.target
UNIT

  systemctl daemon-reload
  systemctl enable --now wings

  ok "Wings installed and started!"
}

# ─── Uninstall Wings ──────────────────────────────
uninstall_wings() {
  if [ ! -f /usr/local/bin/wings ]; then
    err "Wings not installed."
    return
  fi

  warn "This will stop Wings, remove the binary, config, and SSL cert."
  read -p "Confirm? (y/N): " CONFIRM
  [[ ! "$CONFIRM" =~ ^[Yy]$ ]] && msg "Cancelled." && return

  msg "Stopping Wings..."
  systemctl stop wings 2>/dev/null || true
  systemctl disable wings 2>/dev/null || true

  msg "Removing systemd service..."
  rm -f /etc/systemd/system/wings.service
  systemctl daemon-reload

  msg "Removing wings binary..."
  rm -f /usr/local/bin/wings

  msg "Removing config and data..."
  rm -rf /etc/pterodactyl

  msg "Removing SSL certificate..."
  WINGS_DOMAIN=$(ls /etc/letsencrypt/live/ 2>/dev/null | grep -v panel | head -1)
  [ -n "$WINGS_DOMAIN" ] && certbot delete --cert-name "$WINGS_DOMAIN" --non-interactive 2>/dev/null || true

  ok "Wings uninstalled."
}

# ─── Animation Helpers ─────────────────────────
spinner() {
  local pid=$1
  local delay=0.1
  local spinstr='|/-\'
  while [ -d /proc/"$pid" ]; do
    local temp=${spinstr#?}
    printf " \b[%c]\b" "$spinstr"
    spinstr=$temp${spinstr%"$temp"}
    sleep $delay
  done
  printf " \b[${GREEN}✓${NC}]\b"
}

sci_fi_box() {
  local title=$1
  echo -e "${CYAN}╔══════════════════════════════════════════╗${NC}"
  echo -e "${CYAN}║${MAGENTA}  ░▒▓█ ${title} █▓▒░     ${CYAN}║${NC}"
  echo -e "${CYAN}╚══════════════════════════════════════════╝${NC}"
}

# ─── Themes & Extensions Menu ──────────────────
themes_extensions_menu() {
  local PTERO="$PTERO_DIR"
  local THEME_URL="https://run.shubham-dev.in/mirror/shubham/Shubham-Cloud/main/thame/UI"
  local EXT_URL="https://run.shubham-dev.in/mirror/shubham/Shubham-Cloud/main/thame/Extension"

  local THEMES=(
    "nebula.blueprint" "euphoriatheme.blueprint"
    "BetterAdmin.blueprint" "abysspurple.blueprint"
    "amberabyss.blueprint" "catppuccindactyl.blueprint"
    "crimsonabyss.blueprint" "emeraldabyss.blueprint"
    "nightadmin.blueprint" "refreshtheme.blueprint"
    "slice.blueprint" "darkenate.blueprint"
    "recolor.blueprint" "bluetables.blueprint"
    "ultradarkadmin.blueprint" "xlpaneltheme.blueprint"
    "lememtheme.blueprint" "slate.blueprint"
    "kaelixprime.blueprint" "m3dactyl.blueprint"
  )

  local EXTENSIONS=(
    "adminauditlogs.blueprint" "huxregister.blueprint" "loader.blueprint"
    "lyrdyannounce.blueprint" "mclogs.blueprint" "mcplugins.blueprint"
    "mctools.blueprint" "minecraftplayermanager.blueprint" "playerlisting.blueprint"
    "resourcealerts.blueprint" "resourcemanager.blueprint" "serverbackgrounds.blueprint"
    "serversplitter.blueprint" "simplefavicons.blueprint" "snowflakes.blueprint"
    "sociallogin.blueprint" "startupchanger.blueprint" "subdomains.blueprint"
    "tawkto.blueprint" "versionchanger.blueprint" "pteromonaco.blueprint"
    "urldownloader.blueprint" "consolelogs.blueprint" "laravellogs.blueprint"
    "vanillatweaks.blueprint" "modrinthbrowser.blueprint" "nopagination.blueprint"
    "activitypurges.blueprint" "redirect.blueprint" "simplefooters.blueprint"
    "paneladdressoverride.blueprint" "shownodeids.blueprint" "votifiertester.blueprint"
    "sidebar.blueprint" "translations.blueprint" "monacoeditor.blueprint"
    "minecraftpluginmanager.blueprint" "subdomainmanager.blueprint" "serverimporter.blueprint"
    "pstatistics.blueprint" "pullfiles.blueprint" "serverpropsmanager.blueprint"
    "motdmaker.blueprint" "servericonimporter.blueprint" "sagaautosuspension.blueprint"
    "sagaminecraftmodpackinstaller.blueprint" "blueannoucements.blueprint" "trashbin.blueprint"
    "eggchanger.blueprint" "mysqlautobackup.blueprint" "configeditor.blueprint"
    "customserversort.blueprint" "databaseimportexport.blueprint"
    "minecraftmodmanager.blueprint" "serverid.blueprint" "stats.blueprint"
    "vminfo.blueprint" "customcss.blueprint" "autobackups.blueprint"
    "node.blueprint" "mcp.blueprint" "mcplayer.blueprint"
    "pterodactylramburst.blueprint" "pterodactylpanelban.blueprint" "pterodactylcpuburst.blueprint"
  )

  is_installed() {
    [[ -d "$PTERO/storage/extensions/${1%.blueprint}" ]] && return 0 || return 1
  }

  run_bp() {
    local name="$1" action="$2" url="$3"
    cd "$PTERO" || exit 1
    if [[ "$action" == "install" ]]; then
      echo -e "${GREEN} Downloading & Installing ${name%.blueprint}...${NC}"
      wget -q "$url/$name" -O "$name"
      if [[ -s "$name" ]]; then
        yes | blueprint -i "${name%.blueprint}"
        rm -f "$name"
      else
        echo -e "${RED} Download failed!${NC}"
      fi
    else
      echo -e "${RED} Removing ${name%.blueprint}...${NC}"
      yes | blueprint -r "${name%.blueprint}"
    fi
  }

  te_header() {
    clear
    echo -e "${BC} ╔═════════════════════════════════════════════════════════╗${NC}"
    echo -e "${BC} ║${BW}      SHUBHAM PTERO - THEMES & EXTENSIONS      ${BC}║${NC}"
    echo -e "${BC} ╚═════════════════════════════════════════════════════════╝${NC}"
    echo -e "${CYAN} ─────────────────────────────────────────────────────────${NC}"
  }

  theme_menu() {
    local names=("${THEMES[@]}")
    while true; do
      te_header
      echo -e "${BW} SELECT A THEME:${NC}\n"
      local count=0
      for i in "${!names[@]}"; do
        local num=$((i+1))
        local clean="${names[$i]%.blueprint}"
        is_installed "$clean" && local status="${GREEN}●${NC}" || local status="${RED}○${NC}"
        printf "  ${BG}%2d${NC} %-24s %b   " "$num" "$clean" "$status"
        count=$((count+1))
        (( count % 2 == 0 )) && echo ""
      done
      (( count % 2 != 0 )) && echo ""
      echo -e "\n  ${RED}[0]${NC} Back"
      echo -e "${CYAN} ──────────────────────────────────────────────────────────${NC}"
      read -p "  Enter choice: " opt
      [[ "$opt" == "0" ]] && break
      local idx=$((opt-1))
      local name="${names[$idx]}"
      [[ -z "$name" ]] && echo -e "${RED}Invalid${NC}" && sleep 1 && continue
      local clean="${name%.blueprint}"
      te_header
      is_installed "$clean" && local cur="${GREEN}INSTALLED${NC}" || local cur="${RED}NOT INSTALLED${NC}"
      echo -e " ${BW}Theme:${NC} ${CYAN}$clean${NC}   ${BW}Status:${NC} $cur"
      echo -e "${CYAN} ──────────────────────────────────────────────────────────${NC}"
      echo -e "  ${GREEN}[1] Install    ${RED}[2] Uninstall    ${YELLOW}[0] Back${NC}"
      read -p "  Action: " act
      case $act in 1) run_bp "$name" "install" "$THEME_URL" ;; 2) run_bp "$name" "remove" "$THEME_URL" ;; esac
      read -p "  Press Enter..."
    done
  }

  ext_menu() {
    local names=("${EXTENSIONS[@]}")
    local selected=()
    while true; do
      te_header
      echo -e "${BW} SELECT EXTENSIONS (space-separated IDs, then action):${NC}\n"
      local count=0
      for i in "${!names[@]}"; do
        local num=$((i+1))
        local clean="${names[$i]%.blueprint}"
        is_installed "$clean" && local status="${GREEN}●${NC}" || local status="${RED}○${NC}"
        [[ " ${selected[*]} " =~ " $i " ]] && local sel="${YELLOW}[x]${NC}" || local sel="   "
        local display="${clean:0:22}"
        printf " %b ${BG}%2d${NC} %-22s %b  " "$sel" "$num" "$display" "$status"
        count=$((count+1))
        (( count % 2 == 0 )) && echo ""
      done
      (( count % 2 != 0 )) && echo ""
      echo -e "\n${CYAN} ──────────────────────────────────────────────────────────${NC}"
      echo -e " ${BW}Selected:${NC} ${YELLOW}${#selected[@]}${NC}  ${GREEN}[i]nstall  ${RED}[r]emove  ${YELLOW}[a]ll  ${CYAN}[c]lear  ${RED}[0] Back${NC}"
      read -p "  Enter IDs or action: " choice
      case $choice in
        0) break ;;
        c|C) selected=() ;;
        a|A) selected=(); for i in "${!names[@]}"; do selected+=("$i"); done ;;
        i|I|r|R)
          [[ ${#selected[@]} -eq 0 ]] && echo -e "${RED}Nothing selected!${NC}" && sleep 1 && continue
          local mode="install"; [[ "$choice" =~ [rR] ]] && mode="remove"
          for idx in "${selected[@]}"; do run_bp "${names[$idx]}" "$mode" "$EXT_URL"; done
          selected=(); read -p "Done. Press Enter..."
          ;;
        *)
          for v in $choice; do
            if [[ "$v" =~ ^[0-9]+$ ]] && (( v >= 1 && v <= ${#names[@]} )); then
              local i=$((v-1))
              if [[ " ${selected[*]} " =~ " $i " ]]; then
                local tmp=()
                for s in "${selected[@]}"; do [[ $s -ne $i ]] && tmp+=("$s"); done
                selected=("${tmp[@]}")
              else
                selected+=("$i")
              fi
            fi
          done
          ;;
      esac
    done
  }

  while true; do
    clear
    sci_fi_box "THEMES & EXTENSIONS"
    echo ""
    echo -e "  ${YELLOW}[1]${NC} Install Theme"
    echo -e "  ${YELLOW}[2]${NC} Install Extensions"
    echo -e "  ${YELLOW}[3]${NC} Hyper V1 🚀"
    echo ""
    echo -e "  ${RED}[0]${NC} Back to Main Menu"
    echo ""
    read -p "  ➤ Select : " TM_OPT

    case $TM_OPT in
      1) theme_menu ;;
      2) ext_menu ;;
      3)
        sci_fi_box "HYPER V1 🚀"
        wget -q -O /tmp/hyper_installer.sh https://r2.rolexdev.tech/hyperv1/installer.sh
        chmod +x /tmp/hyper_installer.sh
        sudo /tmp/hyper_installer.sh
        rm -f /tmp/hyper_installer.sh
        cd "$PTERO_DIR"
        php artisan view:clear
        php artisan config:clear
        chown -R www-data:www-data "$PTERO_DIR"
        php artisan queue:restart 2>/dev/null || true
        ok "Hyper V1 installed."
        read -p "Press ENTER to continue..."
        ;;
      0) break ;;
      *) err "Invalid option." && sleep 1 ;;
    esac
  done
}

# ─── Startup Animation ────────────────────────
startup_anim() {
  clear
  echo -e "${CYAN}"
  for ((i=0; i<3; i++)); do
    printf "  ░▒▓█ SHUBHAM PTERO MANAGER █▓▒░\r"
    sleep 0.15
    printf "  █▓▒░ SHUBHAM PTERO MANAGER ░▒▓█\r"
    sleep 0.15
  done
  echo -e "${NC}"

  local chars='▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰'
  local empty='▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱'
  echo -ne "  ${GREEN}[${empty}]${NC}  0%%\r"
  for ((p=1; p<=30; p++)); do
    local filled=${chars:0:p}
    local unfilled=${empty:0:$((30-p))}
    local pct=$((p * 100 / 30))
    echo -ne "  ${GREEN}[${filled}${unfilled}]${NC} ${pct}%%\r"
    sleep 0.04
  done
  echo ""
  sleep 0.3
}

# ─── Main Menu ─────────────────────────────────
startup_anim
while true; do
  clear
  echo ""
  sci_fi_box "SHUBHAM PTERO MANAGER"
  echo ""
  echo -e "  ${GREEN}[1]${NC} Install Panel ${YELLOW}v1.11.11${NC}"
  echo -e "  ${GREEN}[2]${NC} Install Panel ${YELLOW}Latest${NC}"
  echo -e "  ${GREEN}[3]${NC} Install Blueprint ${YELLOW}vbeta-A428-2${NC}"
  echo -e "  ${GREEN}[4]${NC} Install Blueprint ${YELLOW}Latest${NC}"
  echo -e "  ${GREEN}[5]${NC} Install ${YELLOW}Wings${NC}"
  echo -e "  ${RED}[6]${NC} Uninstall Panel"
  echo -e "  ${RED}[7]${NC} Uninstall Blueprint"
  echo -e "  ${RED}[8]${NC} Uninstall Wings"
  echo -e "  ${CYAN}[9]${NC} Themes & Extensions"
  echo ""
  echo -e "  ${RED}[0]${NC} Exit"
  echo ""
  read -p "  ➤ Select option : " OPT

  case $OPT in
    1) panel_install "v1.11.11" ;;
    2) panel_install "latest" ;;
    3) blueprint_install "beta-A428-2" ;;
    4) blueprint_install "latest" ;;
    5) install_wings ;;
    6) uninstall_panel ;;
    7) uninstall_blueprint ;;
    8) uninstall_wings ;;
    9) themes_extensions_menu ;;
    0) msg "Exiting." && exit 0 ;;
    *) err "Invalid option." && sleep 1 ;;
  esac

  echo ""
  read -p "  Press ENTER to continue..."
done
