#!/usr/bin/env bash
#
# Установка панели игрового хостинга в один клик.
# Поддерживается и развивается с помощью REDL.IO — Хостинг с искусственным интеллектом.
#
# Что делает скрипт:
#   1. Ставит nginx, PHP 8.x (FPM), MariaDB
#   2. Разворачивает код панели в /var/www/hostinpl
#   3. Создаёт базу, пользователя и загружает схему
#   4. Прописывает конфиг (пароль БД, адрес, токен планировщика)
#   5. Настраивает планировщик (9 заданий) и сторож автозапуска
#   6. Создаёт администратора панели
#
# Запуск:  sudo bash install-panel.sh
#
set -euo pipefail

C_OK=$'\033[1;32m'; C_ERR=$'\033[1;31m'; C_INF=$'\033[1;36m'; C_W=$'\033[1;33m'; C_0=$'\033[0m'
step()  { printf '%s»%s %s\n' "$C_INF" "$C_0" "$1"; }
ok()    { printf '  %s✓%s %s\n' "$C_OK" "$C_0" "$1"; }
warn()  { printf '  %s!%s %s\n' "$C_W" "$C_0" "$1"; }
die()   { printf '%s✗ %s%s\n' "$C_ERR" "$1" "$C_0" >&2; exit 1; }

[[ $EUID -eq 0 ]] || die "Запустите скрипт от root:  sudo bash $0"
SRC="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
[[ -d "$SRC/panel" ]] || die "Рядом со скриптом нет каталога panel/ — распакуйте репозиторий целиком"

WEBROOT=/var/www/hostinpl
DBNAME=hostin
DBUSER=hostinpl
PORT="${PORT:-80}"

printf '\n%s=== Панель игрового хостинга · установка ===%s\n' "$C_INF" "$C_0"
printf 'Поддерживается и развивается с помощью REDL.IO — Хостинг с искусственным интеллектом\n\n'

# ── 0. вопросы ───────────────────────────────────────────────────────────────
read -rp "Домен или IP панели (например panel.example.com): " DOMAIN
[[ -n "$DOMAIN" ]] || die "Адрес не может быть пустым"
read -rp "E-Mail администратора (он же логин в панель): " ADMMAIL
[[ "$ADMMAIL" == *@*.* ]] || die "Похоже, это не e-mail"
read -rsp "Пароль администратора (минимум 6 символов): " ADMPASS; echo
[[ ${#ADMPASS} -ge 6 ]] || die "Пароль короче 6 символов"

if [[ -e "$WEBROOT" ]]; then
  read -rp "Каталог $WEBROOT уже существует. Перезаписать код панели? (yes/no): " OW
  [[ "$OW" == "yes" ]] || die "Отменено пользователем"
fi

. /etc/os-release 2>/dev/null || true
step "Система: ${PRETTY_NAME:-неизвестна}"

# ── 1. пакеты ────────────────────────────────────────────────────────────────
step "Устанавливаю пакеты (nginx, PHP-FPM, MariaDB)…"
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y -qq nginx mariadb-server unzip curl cron pwgen \
  php-fpm php-mysql php-mbstring php-curl php-gd php-xml php-zip php-ssh2 >/dev/null
PHPV="$(ls -1 /etc/php/ 2>/dev/null | sort -V | tail -1)"
[[ -n "$PHPV" ]] || die "PHP не установился"
ok "PHP $PHPV, $(nginx -v 2>&1 | sed 's/.*nginx\///')"

# ── 2. службы (в контейнерах systemd может отсутствовать) ────────────────────
step "Запускаю MariaDB…"
mkdir -p /run/mysqld && chown mysql:mysql /run/mysqld
if ! mysqladmin ping >/dev/null 2>&1; then
  service mariadb start >/dev/null 2>&1 || /etc/init.d/mariadb start >/dev/null 2>&1 || true
  for _ in $(seq 1 45); do mysqladmin ping >/dev/null 2>&1 && break; sleep 2; done
fi
mysqladmin ping >/dev/null 2>&1 || die "MariaDB не поднялась — проверьте /var/log/mysql/"
ok "MariaDB отвечает"

# ── 3. база ──────────────────────────────────────────────────────────────────
step "Создаю базу данных…"
DBPASS="$(pwgen -cns -1 20)"
mysql -e "CREATE DATABASE IF NOT EXISTS \`$DBNAME\` DEFAULT CHARSET utf8;"
mysql -e "CREATE USER IF NOT EXISTS '$DBUSER'@'localhost' IDENTIFIED BY '$DBPASS';
          ALTER USER '$DBUSER'@'localhost' IDENTIFIED BY '$DBPASS';
          GRANT ALL PRIVILEGES ON \`$DBNAME\`.* TO '$DBUSER'@'localhost';
          FLUSH PRIVILEGES;"
ok "База $DBNAME, пользователь $DBUSER (права только на свою базу)"

# ── 4. файлы ─────────────────────────────────────────────────────────────────
step "Копирую код панели в $WEBROOT…"
mkdir -p "$WEBROOT"
cp -a "$SRC/panel/." "$WEBROOT/"
if [[ -f "$WEBROOT/hostinpl.sql" ]]; then
  TABLES="$(mysql -N -B -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='$DBNAME'")"
  if [[ "$TABLES" -lt 5 ]]; then
    mysql "$DBNAME" < "$WEBROOT/hostinpl.sql"
    ok "Схема загружена: $(mysql -N -B -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='$DBNAME'") таблиц"
  else
    warn "В базе уже $TABLES таблиц — схему не перезаписываю"
  fi
  rm -f "$WEBROOT/hostinpl.sql"
fi

# ── 5. конфиг ────────────────────────────────────────────────────────────────
step "Настраиваю конфигурацию…"
CRONTOKEN="$(pwgen -cns -1 24)"
CFG="$WEBROOT/application/config.php"
PROTO=http; [[ "$PORT" == "443" ]] && PROTO=https
URL="$PROTO://$DOMAIN/"; [[ "$PORT" != "80" && "$PORT" != "443" ]] && URL="http://$DOMAIN:$PORT/"
# Значения подставляются через callback, а не строкой замены: иначе символы вида $1
# в сгенерированном пароле PHP принял бы за обратную ссылку и записал бы мусор.
php -r '
$f=$argv[1];$s=file_get_contents($f);
$set=function($s,$key,$val,$anchor=false){
  $re="~".($anchor?"^":"")."\x27".preg_quote($key,"~")."\x27(\s*)=>(\s*)\x27[^\x27]*\x27~u".($anchor?"m":"");
  return preg_replace_callback($re,function($m)use($key,$val){
    return "\x27".$key."\x27".$m[1]."=>".$m[2]."\x27".$val."\x27";
  },$s,1);
};
$s=$set($s,"db_username",$argv[2]);
$s=$set($s,"db_password",$argv[3]);
$s=$set($s,"url",$argv[4]);
$s=$set($s,"token",$argv[5],true);
file_put_contents($f,$s);' "$CFG" "$DBUSER" "$DBPASS" "$URL" "$CRONTOKEN"
php -l "$CFG" >/dev/null || die "Конфиг повреждён — установка прервана"
grep -q "'db_password' => *'$DBPASS'" "$CFG" || grep -q "$DBPASS" "$CFG" || die "Пароль БД не попал в конфиг"
umask 077; printf 'db_user=%s\ndb_pass=%s\ncron_token=%s\n' "$DBUSER" "$DBPASS" "$CRONTOKEN" > /root/.redl-panel-credentials
ok "Конфиг записан, креды сохранены в /root/.redl-panel-credentials"

# ── 6. права ─────────────────────────────────────────────────────────────────
step "Выставляю права…"
chown -R www-data:www-data "$WEBROOT"
find "$WEBROOT" -type d -exec chmod 750 {} +
find "$WEBROOT" -type f -exec chmod 640 {} +
chmod -R 770 "$WEBROOT/tmp"
ok "Владелец www-data, конфиг недоступен извне"

# ── 7. PHP ───────────────────────────────────────────────────────────────────
step "Настраиваю PHP $PHPV…"
INI="/etc/php/$PHPV/fpm/php.ini"
sed -i 's/^short_open_tag = Off/short_open_tag = On/' "$INI"
sed -i 's/^upload_max_filesize = .*/upload_max_filesize = 90M/' "$INI"
sed -i 's/^post_max_size = .*/post_max_size = 360M/' "$INI"
sed -i 's|^;\?date.timezone =.*|date.timezone = Europe/Moscow|' "$INI"
mkdir -p /run/php
service "php$PHPV-fpm" restart >/dev/null 2>&1 || /etc/init.d/"php$PHPV-fpm" restart >/dev/null 2>&1 || true
sleep 2
[[ -S "/run/php/php$PHPV-fpm.sock" ]] || die "PHP-FPM сокет не создан"
ok "short_open_tag включён (панель использует <? ?>), загрузка до 90 МБ"

# ── 8. nginx ─────────────────────────────────────────────────────────────────
step "Настраиваю nginx (порт $PORT)…"
cat > /etc/nginx/sites-available/hostinpl <<NGINX
server {
    listen 0.0.0.0:$PORT default_server;
    server_name $DOMAIN _;
    root $WEBROOT;
    index index.php;
    client_max_body_size 360M;

    # редиректы без хоста и порта — иначе за обратным прокси уводит на :$PORT
    absolute_redirect off;
    port_in_redirect off;

    location / { try_files \$uri \$uri/ /index.php\$is_args\$args; }

    location ~ \.php\$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php$PHPV-fpm.sock;
        fastcgi_read_timeout 300;
    }

    # закрываем служебное
    location ~ /\.(ht|git)      { deny all; }
    location ~* \.(sql|log)\$    { deny all; }
    location ^~ /application/config.php { deny all; }
}
NGINX
ln -sfn /etc/nginx/sites-available/hostinpl /etc/nginx/sites-enabled/hostinpl
rm -f /etc/nginx/sites-enabled/default
nginx -t >/dev/null 2>&1 || { nginx -t; die "Конфиг nginx не прошёл проверку"; }
service nginx restart >/dev/null 2>&1 || /etc/init.d/nginx restart >/dev/null 2>&1 || nginx
sleep 1
ok "Сайт слушает 0.0.0.0:$PORT"

# ── 9. планировщик ───────────────────────────────────────────────────────────
step "Настраиваю планировщик…"
B="http://127.0.0.1:$PORT/main/cron"
{
  echo 'SHELL=/bin/sh'
  echo 'PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin'
  echo "0 0 * * * root curl -s -m 300 '$B/index?token=$CRONTOKEN' >/dev/null 2>&1"
  echo "* * * * * root curl -s -m 55 '$B/gameServers?token=$CRONTOKEN' >/dev/null 2>&1"
  echo "* * * * * root curl -s -m 55 '$B/tasks?token=$CRONTOKEN' >/dev/null 2>&1"
  echo "*/10 * * * * root curl -s -m 300 '$B/serverReloader?token=$CRONTOKEN' >/dev/null 2>&1"
  echo "*/30 * * * * root curl -s -m 300 '$B/stopServers?token=$CRONTOKEN' >/dev/null 2>&1"
  echo "*/30 * * * * root curl -s -m 300 '$B/stopServersQuery?token=$CRONTOKEN' >/dev/null 2>&1"
  echo "0 * * * * root curl -s -m 300 '$B/updateStats?token=$CRONTOKEN' >/dev/null 2>&1"
  echo "0 * * * * root curl -s -m 300 '$B/updateStatsLocations?token=$CRONTOKEN' >/dev/null 2>&1"
  echo "0 3 * * 0 root curl -s -m 300 '$B/clearLogs?token=$CRONTOKEN' >/dev/null 2>&1"
} > /etc/cron.d/hostinpl
chmod 644 /etc/cron.d/hostinpl
service cron start >/dev/null 2>&1 || /etc/init.d/cron start >/dev/null 2>&1 || true
ok "9 заданий панели (статистика, задачи, автоотключение просрочки)"

# ── 10. сторож автозапуска (нужен там, где нет systemd) ──────────────────────
step "Ставлю сторож автозапуска…"
cat > /usr/local/bin/hostinpl-guard <<GUARD
#!/bin/sh
# Поднимает стек панели, если что-то упало или машина перезагрузилась.
pgrep -x mariadbd >/dev/null 2>&1 || pgrep -x mysqld >/dev/null 2>&1 || {
  mkdir -p /run/mysqld; chown mysql:mysql /run/mysqld
  service mariadb start >/dev/null 2>&1 || /etc/init.d/mariadb start >/dev/null 2>&1
}
pgrep -f "^php-fpm$PHPV: master" >/dev/null 2>&1 || service php$PHPV-fpm start >/dev/null 2>&1
curl -sf -o /dev/null http://127.0.0.1:$PORT/account/login || service nginx start >/dev/null 2>&1
pgrep -x cron >/dev/null 2>&1 || service cron start >/dev/null 2>&1
GUARD
chmod +x /usr/local/bin/hostinpl-guard
cat > /etc/cron.d/hostinpl-guard <<'G'
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
* * * * * root /usr/local/bin/hostinpl-guard >/dev/null 2>&1
@reboot root sleep 20; /usr/local/bin/hostinpl-guard >/dev/null 2>&1
G
chmod 644 /etc/cron.d/hostinpl-guard
ok "Проверка раз в минуту и подъём после перезагрузки"

# ── 11. администратор ────────────────────────────────────────────────────────
step "Создаю администратора панели…"
HASH="$(php -r 'echo md5($argv[1]);' "$ADMPASS")"
mysql "$DBNAME" <<SQL
DELETE FROM users WHERE user_email='$ADMMAIL';
INSERT INTO users
 (user_email,user_password,user_firstname,user_lastname,user_status,user_balance,
  user_access_level,user_date_reg,user_online_date,user_promo_date,user_activate,
  key_activate,ref,rmoney,bonuses,test_server,user_last_date)
VALUES
 ('$ADMMAIL','$HASH','Администратор','Панели',1,0.00,3,NOW(),UNIX_TIMESTAMP(),
  CURDATE(),1,'',0,0.00,0.00,'2',NOW());
SQL
ok "Логин $ADMMAIL, уровень доступа 3 (полный)"

# ── 12. проверка ─────────────────────────────────────────────────────────────
step "Проверяю работу панели…"
sleep 2
CODE="$(curl -s -o /tmp/redl-check.html -w '%{http_code}' -L "http://127.0.0.1:$PORT/account/login" || true)"
[[ "$CODE" == "200" ]] || die "Страница входа вернула $CODE (ожидался 200). Смотрите /var/log/nginx/error.log"
grep -q 'kt_login_signin_form' /tmp/redl-check.html || die "Страница входа отдалась без формы"
rm -f /tmp/redl-check.html
ok "Страница входа отвечает, форма на месте"

printf '\n%s=== Установка завершена ===%s\n\n' "$C_OK" "$C_0"
printf '  Адрес панели : %s\n' "$URL"
printf '  Логин        : %s\n' "$ADMMAIL"
printf '  Пароль       : тот, что вы ввели при установке\n'
printf '  Креды БД     : /root/.redl-panel-credentials\n\n'
printf '%sДальше:%s\n' "$C_INF" "$C_0"
printf '  1. Капча выключена. Включить: Админка → Настройки → Прочие настройки → «Защита от ботов»\n'
printf '     (сначала впишите оба ключа с google.com/recaptcha, потом переключайте)\n'
printf '  2. Платёжные системы: Админка → Настройки → Платёжные системы\n'
printf '  3. Игровую ноду ставьте скриптом install-node.sh и подключайте в Админка → Локации\n\n'
printf 'Поддерживается и развивается с помощью REDL.IO — Хостинг с искусственным интеллектом\n\n'
