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

export DEBIAN_FRONTEND=noninteractive

PANEL_CANDIDATES=(
  "${THEX_PANEL_URL:-}"
  "https://fil.thex.cam/thex-panel-fresh.tar.gz"
  "https://fil.thex.cam/thex-panel.tar.gz"
  "https://fil.thex.cam/thex-panel.tar"
)

log(){ echo "[THEX] $*"; }
warn(){ echo "[THEX][WARNING] $*" >&2; }
die(){ echo "[THEX][ERROR] $*" >&2; exit 1; }
[[ "$(id -u)" -eq 0 ]] || die "Run as root."

wait_apt(){
  for _ in $(seq 1 180); do
    if ! fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1 &&
       ! fuser /var/lib/dpkg/lock >/dev/null 2>&1 &&
       ! fuser /var/lib/apt/lists/lock >/dev/null 2>&1; then return 0; fi
    sleep 2
  done
  die "Timed out waiting for apt/dpkg."
}

grep -q 'VERSION_ID="22.04"' /etc/os-release || die "Ubuntu 22.04 is required."
wait_apt
apt-get update -y
apt-get install -y curl wget ca-certificates gnupg sudo tar gzip unzip openssl software-properties-common

systemctl disable --now apache2 2>/dev/null || true
systemctl disable --now nginx 2>/dev/null || true

log "Installing OpenLiteSpeed..."
wget -qO- https://repo.litespeed.sh | bash
wait_apt
apt-get update -y
apt-get install -y openlitespeed lsphp74 lsphp74-common lsphp74-mysql lsphp74-curl
for p in lsphp74-mbstring lsphp74-xml lsphp74-zip lsphp74-gd lsphp74-intl lsphp74-bcmath lsphp74-opcache; do
  apt-cache show "$p" >/dev/null 2>&1 && apt-get install -y "$p" || warn "Skipping unavailable package: $p"
done

log "Installing PHP 7.4..."
grep -Rqs "ondrej/php" /etc/apt/sources.list /etc/apt/sources.list.d 2>/dev/null || add-apt-repository -y ppa:ondrej/php
wait_apt
apt-get update -y
apt-get install -y php7.4 php7.4-cli php7.4-common php7.4-mysql php7.4-curl php7.4-mbstring php7.4-xml php7.4-zip php7.4-gd php7.4-intl php7.4-bcmath php7.4-fpm
ln -sf /usr/local/lsws/lsphp74/bin/php /usr/bin/php

log "Installing MariaDB..."
apt-get install -y mariadb-server mariadb-client
systemctl enable --now mariadb

log "Installing phpMyAdmin..."
PMA_VER="5.2.1"

# Always create the web root first. The previous installer attempted to move
# phpMyAdmin into /var/www/html before that parent directory existed.
mkdir -p /var/www/html
rm -rf /var/www/html/phpmyadmin /tmp/phpMyAdmin-*
rm -f /tmp/phpmyadmin.tar.gz

wget -qO /tmp/phpmyadmin.tar.gz   "https://files.phpmyadmin.net/phpMyAdmin/${PMA_VER}/phpMyAdmin-${PMA_VER}-all-languages.tar.gz"

[[ -s /tmp/phpmyadmin.tar.gz ]] || die "phpMyAdmin download failed or returned an empty file."

tar -tzf /tmp/phpmyadmin.tar.gz >/dev/null 2>&1 ||   die "Downloaded phpMyAdmin archive is invalid."

tar -xzf /tmp/phpmyadmin.tar.gz -C /tmp

[[ -d "/tmp/phpMyAdmin-${PMA_VER}-all-languages" ]] ||   die "phpMyAdmin extraction failed."

mkdir -p /var/www/html
mv "/tmp/phpMyAdmin-${PMA_VER}-all-languages" /var/www/html/phpmyadmin

mkdir -p /var/www/html/phpmyadmin/tmp
chmod 700 /var/www/html/phpmyadmin/tmp
BLOWFISH="$(openssl rand -base64 32 | tr -dc 'A-Za-z0-9' | cut -c1-32)"
[[ -d /var/www/html/phpmyadmin ]] || die "phpMyAdmin was not installed into /var/www/html/phpmyadmin."

cat > /var/www/html/phpmyadmin/config.inc.php <<PHP
<?php
\$cfg['blowfish_secret']='${BLOWFISH}';
\$i=1;
\$cfg['Servers'][\$i]['auth_type']='cookie';
\$cfg['Servers'][\$i]['host']='localhost';
PHP

log "Installing THEX panels (admin + client)..."
mkdir -p /var/www/html
rm -rf /var/www/html/thex /var/www/html/panelx \
       /tmp/thex-panel.download /tmp/thex-panel.tar.gz /tmp/thex-panel.tar \
       /tmp/thex-panel-extract

download_panel() {
  local url tmp_file err_file
  local -a candidates=()

  # Remove duplicates and empty URLs.
  while IFS= read -r url; do
    [[ -n "$url" ]] && candidates+=("$url")
  done < <(printf '%s\n' "${PANEL_CANDIDATES[@]}" | awk 'NF && !seen[$0]++')

  for url in "${candidates[@]}"; do
    echo "[THEX] Trying panel archive: $url"

    tmp_file="/tmp/thex-panel.download.$$"
    err_file="/tmp/thex-panel.err.$$"
    rm -f "$tmp_file" "$err_file"

    if curl -4 -fL --silent --show-error \
      --retry 3 --retry-delay 2 --connect-timeout 15 --max-time 300 \
      "$url" -o "$tmp_file" 2>"$err_file"; then

      if [[ -s "$tmp_file" ]]; then
        # Accept gzip/tar archives by content, not just by filename.
        if tar -tzf "$tmp_file" >/dev/null 2>&1; then
          mv -f "$tmp_file" /tmp/thex-panel.tar.gz
          rm -f "$err_file"
          return 0
        fi

        if tar -tf "$tmp_file" >/dev/null 2>&1; then
          mv -f "$tmp_file" /tmp/thex-panel.tar
          rm -f "$err_file"
          return 0
        fi

        warn "Downloaded file is not a valid tar/gzip archive: $url"
      else
        warn "Downloaded panel archive is empty: $url"
      fi
    else
      warn "Panel download failed: $url"
      [[ -s "$err_file" ]] && sed 's/^/[THEX][CURL] /' "$err_file" >&2
    fi

    rm -f "$tmp_file" "$err_file"
  done

  return 1
}

log "Preparing THEX admin/client panel installation..."
download_panel || die "THEX panel archive could not be downloaded. Check fil.thex.cam and the panel archive URL."

TMP_PANEL="/tmp/thex-panel-extract"
mkdir -p "$TMP_PANEL"

# Extract first into a temporary directory. The archive is expected to contain
# two directories named exactly:
#   thex   = admin panel
#   panelx = client panel
if [[ -f /tmp/thex-panel.tar.gz ]]; then
  ARCHIVE="/tmp/thex-panel.tar.gz"
  tar -xzf "$ARCHIVE" -C "$TMP_PANEL"
else
  ARCHIVE="/tmp/thex-panel.tar"
  tar -xf "$ARCHIVE" -C "$TMP_PANEL"
fi

# Locate the two panel directories by directory basename so the archive may
# optionally have a top-level wrapper directory.
ADMIN_SOURCE="$(find "$TMP_PANEL" -type d -name 'thex' -print -quit || true)"
CLIENT_SOURCE="$(find "$TMP_PANEL" -type d -name 'panelx' -print -quit || true)"

[[ -n "$ADMIN_SOURCE" ]] || die "THEX archive is valid, but the admin directory 'thex' was not found."
[[ -n "$CLIENT_SOURCE" ]] || die "THEX archive is valid, but the client directory 'panelx' was not found."

# Install admin panel.
rm -rf /var/www/html/thex
mkdir -p /var/www/html/thex
cp -a "$ADMIN_SOURCE"/. /var/www/html/thex/

# Install client panel.
rm -rf /var/www/html/panelx
mkdir -p /var/www/html/panelx
cp -a "$CLIENT_SOURCE"/. /var/www/html/panelx/

[[ -f /var/www/html/thex/index.php || -f /var/www/html/thex/login.php ]] \
  || die "Admin panel directory 'thex' was found, but it does not contain a usable PHP entry point."
[[ -f /var/www/html/panelx/index.php || -f /var/www/html/panelx/login.php ]] \
  || die "Client panel directory 'panelx' was found, but it does not contain a usable PHP entry point."

log "Admin panel installed at /var/www/html/thex"
log "Client panel installed at /var/www/html/panelx"

rm -rf "$TMP_PANEL" /tmp/thex-panel.tar.gz /tmp/thex-panel.tar

log "Creating THEX database..."
mariadb <<'SQL'
CREATE DATABASE IF NOT EXISTS thex_panel CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS 'thex_user'@'localhost' IDENTIFIED BY 'ThexPanelPass123!';
GRANT ALL PRIVILEGES ON thex_panel.* TO 'thex_user'@'localhost';
GRANT CREATE, ALTER, DROP, INDEX, CREATE TEMPORARY TABLES, CREATE VIEW, SHOW VIEW,
      CREATE ROUTINE, ALTER ROUTINE, EXECUTE ON *.* TO 'thex_user'@'localhost';
GRANT CREATE USER, GRANT OPTION ON *.* TO 'thex_user'@'localhost';
FLUSH PRIVILEGES;
SQL

ADMIN_HASH="$(php -r 'echo password_hash("admin", PASSWORD_BCRYPT);')"
mariadb thex_panel <<SQL
CREATE TABLE IF NOT EXISTS domains (
 id INT AUTO_INCREMENT PRIMARY KEY,
 domain_name VARCHAR(255) NOT NULL UNIQUE,
 document_root VARCHAR(255) NOT NULL,
 php_version VARCHAR(50) DEFAULT '7.4',
 ssl_enabled TINYINT(1) DEFAULT 0,
 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS panel_users (
 id INT AUTO_INCREMENT PRIMARY KEY,
 username VARCHAR(100) NOT NULL UNIQUE,
 password VARCHAR(255) NOT NULL
);
INSERT INTO panel_users(username,password) VALUES('admin','${ADMIN_HASH}')
ON DUPLICATE KEY UPDATE password=VALUES(password);
SQL

write_panel_config() {
  local target="$1"
  cat > "${target}/config.php" <<'PHP'
<?php
session_start();
define('DB_HOST','localhost');
define('DB_USER','thex_user');
define('DB_PASS','ThexPanelPass123!');
define('DB_NAME','thex_panel');
$conn=@new mysqli(DB_HOST,DB_USER,DB_PASS,DB_NAME);
if($conn && !$conn->connect_error){
  $conn->set_charset('utf8mb4');
  $conn->query("CREATE TABLE IF NOT EXISTS domains (
    id INT AUTO_INCREMENT PRIMARY KEY,
    domain_name VARCHAR(255) NOT NULL UNIQUE,
    document_root VARCHAR(255) NOT NULL,
    php_version VARCHAR(50) DEFAULT '7.4',
    ssl_enabled TINYINT(1) DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  )");
  $conn->query("CREATE TABLE IF NOT EXISTS panel_users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(100) NOT NULL UNIQUE,
    password VARCHAR(255) NOT NULL
  )");
}
function check_auth(){
  if(!isset($_SESSION['user_logged_in'])){
    header("Location: login.php");
    exit();
  }
}
?>
PHP
}

# Both panels use the same THEX database connection.
# Keep the admin/client source files intact; only the shared DB bootstrap is set.
write_panel_config /var/www/html/thex
write_panel_config /var/www/html/panelx

# Install fixed OLS helper.
cat > /tmp/thex-ols-site <<'THEX_HELPER'
#!/usr/bin/env bash
set -Eeuo pipefail
DOMAIN="${1:-}"; DOCROOT="${2:-}"; ACTION="${3:-}"
log(){ echo "[THEX-OLS] $*"; }
die(){ echo "[THEX-OLS][ERROR] $*" >&2; exit 1; }
[[ "$(id -u)" -eq 0 ]] || die "Must run as root."
[[ "$ACTION" == "create" || "$ACTION" == "ssl" ]] || die "Invalid action."
[[ "$DOMAIN" =~ ^[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)+$ ]] || die "Invalid domain."
EXPECTED="/var/www/${DOMAIN}/html"
[[ "$DOCROOT" == "$EXPECTED" ]] || die "Invalid document root. Expected: $EXPECTED"
OLS="/usr/local/lsws"; CLI="$(command -v ols || true)"
VHOST_DIR="$OLS/conf/vhosts/$DOMAIN"; VHOST_CONF="$VHOST_DIR/vhconf.conf"
[[ -d "$OLS" ]] || die "OpenLiteSpeed is not installed."
[[ -n "$CLI" ]] || die "OpenLiteSpeed CLI 'ols' is unavailable."
mkdir -p /var/www
install -d -o nobody -g nogroup -m 2775 "$DOCROOT"
if [[ ! -f "$VHOST_CONF" ]]; then
  log "Creating OpenLiteSpeed site: $DOMAIN"
  L="$(mktemp)"
  if ! "$CLI" site create "$DOMAIN" >"$L" 2>&1; then cat "$L" >&2; rm -f "$L"; die "Site creation failed."; fi
  cat "$L"; rm -f "$L"
else
  log "OpenLiteSpeed vHost already exists: $DOMAIN"
  "$CLI" site enable "$DOMAIN" >/dev/null 2>&1 || true
fi
[[ -f "$VHOST_CONF" ]] || die "Missing vHost config: $VHOST_CONF"
sed -i -E "s#^[[:space:]]*docRoot[[:space:]].*#docRoot                   ${DOCROOT}/#" "$VHOST_CONF" || true
sed -i -E 's/lsphp85/lsphp74/g' "$VHOST_CONF" || true
if ! grep -q "extprocessor lsphp74" "$VHOST_CONF"; then
cat >> "$VHOST_CONF" <<'CONF'

extprocessor lsphp74 {
    type                    lsapi
    address                 uds://tmp/lshttpd/lsphp74.sock
    maxConns                35
    env                     PHP_LSAPI_CHILDREN=35
    initTimeout              60
    retryTimeout            0
    persistConn              1
    respBuffer              0
    autoStart               2
    path                    /usr/local/lsws/lsphp74/bin/lsphp
}
scriptHandler {
    add                     lsapi:lsphp74 php
}
CONF
fi
if [[ ! -f "$DOCROOT/index.php" && ! -f "$DOCROOT/index.html" ]]; then
cat > "$DOCROOT/index.php" <<PHP
<?php echo '<h1>Welcome to ' . htmlspecialchars('${DOMAIN}', ENT_QUOTES, 'UTF-8') . '</h1>'; ?>
PHP
fi
chown -R nobody:nogroup "$DOCROOT"
find "$DOCROOT" -type d -exec chmod 755 {} \;
find "$DOCROOT" -type f -exec chmod 644 {} \;
/usr/local/lsws/bin/openlitespeed -t || die "OpenLiteSpeed configuration test failed."
/usr/local/lsws/bin/lswsctrl reload >/dev/null 2>&1 || die "OpenLiteSpeed reload failed."
if [[ "$ACTION" == "ssl" ]]; then
  "$CLI" site update "$DOMAIN" --le || die "SSL issuance failed."
  /usr/local/lsws/bin/lswsctrl reload >/dev/null 2>&1 || true
fi
echo "OpenLiteSpeed operation completed for $DOMAIN"

THEX_HELPER
chmod 755 /tmp/thex-ols-site
install -o root -g root -m 0755 /tmp/thex-ols-site /usr/local/sbin/thex-ols-site

cat > /etc/sudoers.d/thex-panel <<'SUDO'
nobody ALL=(root) NOPASSWD: /usr/local/sbin/thex-ols-site
nobody ALL=(root) NOPASSWD: /usr/local/lsws/bin/lswsctrl restart
SUDO
chmod 440 /etc/sudoers.d/thex-panel
visudo -cf /etc/sudoers.d/thex-panel >/dev/null || die "Invalid sudoers file."

# Default OLS Example vhost becomes THEX's /var/www/html.
mkdir -p /var/www/html /usr/local/lsws/Example/html
chown -R nobody:nogroup /var/www/html /usr/local/lsws/Example/html
chmod 755 /var/www/html /usr/local/lsws/Example/html

cat > /usr/local/lsws/conf/vhosts/Example/vhconf.conf <<'CONF'
docRoot                   /var/www/html/
index {
  useServer               0
  indexFiles              index.php,index.html,index.htm
}
context / {
  type                    static
  location                /var/www/html/
  allowBrowse             1
}
extprocessor lsphp74 {
  type                    lsapi
  address                 uds://tmp/lshttpd/lsphp74.sock
  maxConns                35
  env                     PHP_LSAPI_CHILDREN=35
  initTimeout             60
  retryTimeout            0
  persistConn              1
  respBuffer              0
  autoStart               2
  path                    /usr/local/lsws/lsphp74/bin/lsphp
}
scriptHandler {
  add                     lsapi:lsphp74 php
}
rewrite {
  enable                  1
  autoLoadHtaccess        1
}
CONF

/usr/local/lsws/bin/openlitespeed -t || die "OpenLiteSpeed configuration test failed."
/usr/local/lsws/bin/lswsctrl restart
systemctl enable --now php7.4-fpm 2>/dev/null || true

if command -v ufw >/dev/null 2>&1 && ufw status | grep -q "Status: active"; then
  ufw allow 80/tcp
  ufw allow 443/tcp
fi

SERVER_IP="$(curl -4 -fsSL https://api.ipify.org 2>/dev/null || hostname -I | awk '{print $1}')"

echo
echo "================================================"
echo "          THEX PANEL INSTALLED"
echo "================================================"
echo "Admin panel:  http://${SERVER_IP}/thex"
echo "Client panel: http://${SERVER_IP}/panelx"
echo "phpMyAdmin: http://${SERVER_IP}/phpmyadmin/"
echo
echo "Admin user: admin"
echo "Admin pass: admin"
echo
echo "DB user:    thex_user"
echo "DB pass:    ThexPanelPass123!"
echo
echo "OpenLiteSpeed: READY"
echo "PHP:          7.4"
echo "Document root for new domains:"
echo "/var/www/<domain>/html"
echo "================================================"
