#!/bin/bash
# =============================================================================
# Modular Hosting Setup with optional Cloudflare Tunnel
# Author Fedya Serafiev
# Site itpraktika.com
# =============================================================================

set -euo pipefail

# -- Colors -------------------------------------------------------------------
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
CYAN='\033[0;36m'; BOLD='\033[1m'; RESET='\033[0m'

info()    { echo -e "${CYAN}[INFO]  $*${RESET}"; }
success() { echo -e "${GREEN}[OK]    $*${RESET}"; }
warn()    { echo -e "${YELLOW}[WARN]  $*${RESET}"; }
error()   { echo -e "${RED}[ERROR] $*${RESET}" >&2; exit 1; }

# -- Password generator -------------------------------------------------------
gen_pass() {
    openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c 24
}

# -- Input validation ---------------------------------------------------------
validate_yn() {
    [[ "$1" =~ ^[yYnN]$ ]] || error "Vuvedete 'y' ili 'n'."
}
validate_count() {
    [[ "$1" =~ ^[0-2]$ ]] || error "Vuvedete 0, 1 ili 2."
}

# =============================================================================
echo -e "\n${BOLD}================================================${RESET}"
echo -e "${BOLD}     Modular Hosting Setup - Izberete moduli    ${RESET}"
echo -e "${BOLD}================================================${RESET}\n"

# =============================================================================
# [1/4] Module selection
# =============================================================================
echo -e "${BOLD}[1/4] Izberete koi moduli da se instalират:${RESET}\n"

read -rp "  Instaliraj Cloudflare Tunnel? (y/n): " install_cf
validate_yn "$install_cf"; install_cf="${install_cf,,}"

read -rp "  Instaliraj Uptime Kuma?        (y/n): " install_kuma
validate_yn "$install_kuma"; install_kuma="${install_kuma,,}"

read -rp "  Broy WordPress sajtove?        (0/1/2): " wp_count
validate_count "$wp_count"

# At least one module must be selected
if [[ "$install_cf" == "n" && "$install_kuma" == "n" && "$wp_count" == "0" ]]; then
    error "Tryabva da izberete poне edin modul."
fi

# DB is needed only when WordPress is requested
need_db="n"
[[ "$wp_count" -ge 1 ]] && need_db="y"

# =============================================================================
# [2/4] Cloudflare Tunnel config (only if selected)
# =============================================================================
CLOUDFLARED_CMD=""
CF_ENV_LINE=""
CF_TOKEN_IN_ENV="# Cloudflare Tunnel not installed"
cf_method=""

if [[ "$install_cf" == "y" ]]; then
    echo -e "\n${BOLD}[2/4] Cloudflare Tunnel - metod na svarzavane${RESET}"
    echo "  1) Token  - vuvedash gotov token ot Cloudflare Dashboard"
    echo "  2) Login  - cloudflared se logva sam (URL / brauzar)"
    echo ""
    read -rp "  Izberi metod [1/2]: " cf_method

    case "$cf_method" in
      1)
        read -rp "  Vuvedete Tunnel Token: " cf_token
        [[ -n "$cf_token" ]] || error "Tokenat ne mozhe da e prazen."
        CLOUDFLARED_CMD='tunnel --no-autoupdate run --token ${TUNNEL_TOKEN}'
        CF_ENV_LINE="      - TUNNEL_TOKEN=\${TUNNEL_TOKEN}"
        CF_TOKEN_IN_ENV="TUNNEL_TOKEN=$cf_token"
        ;;
      2)
        info "cloudflared shte izvede URL za avtentikaciya pri start."
        CLOUDFLARED_CMD='tunnel --no-autoupdate login'
        CF_ENV_LINE=""
        CF_TOKEN_IN_ENV="# TUNNEL_TOKEN= (login method - not needed)"
        cf_token=""
        ;;
      *)
        error "Nevaliден izbor. Vuvedete 1 ili 2."
        ;;
    esac
else
    info "Cloudflare Tunnel - skipped."
fi

# =============================================================================
# [3/4] Generate passwords
# =============================================================================
echo -e "\n${BOLD}[3/4] Generirane na paroli...${RESET}"
DB_ROOT_PASS=$(gen_pass)
WP1_DB_PASS=$(gen_pass)
WP2_DB_PASS=$(gen_pass)

# =============================================================================
# [4/4] Generate files
# =============================================================================
echo -e "\n${BOLD}[4/4] Generirane na konfiguracionnite fajlove...${RESET}"

# -- .env ---------------------------------------------------------------------
cat > .env <<ENVEOF
# -- Cloudflare ---------------------------------------------------------------
$CF_TOKEN_IN_ENV

# -- Database -----------------------------------------------------------------
DB_ROOT_PASSWORD=$DB_ROOT_PASS
WP1_DB_PASSWORD=$WP1_DB_PASS
WP2_DB_PASSWORD=$WP2_DB_PASS
ENVEOF
chmod 600 .env
success ".env created (chmod 600)"

# -- DB init SQL (only when WP is needed) -------------------------------------
if [[ "$need_db" == "y" ]]; then
    mkdir -p db-init
    SQL_CONTENT=""
    if [[ "$wp_count" -ge 1 ]]; then
        SQL_CONTENT+="CREATE DATABASE IF NOT EXISTS wp1_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n"
        SQL_CONTENT+="CREATE USER IF NOT EXISTS 'wp1_user'@'%' IDENTIFIED BY '${WP1_DB_PASS}';\n"
        SQL_CONTENT+="GRANT ALL PRIVILEGES ON wp1_db.* TO 'wp1_user'@'%';\n"
    fi
    if [[ "$wp_count" -ge 2 ]]; then
        SQL_CONTENT+="CREATE DATABASE IF NOT EXISTS wp2_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n"
        SQL_CONTENT+="CREATE USER IF NOT EXISTS 'wp2_user'@'%' IDENTIFIED BY '${WP2_DB_PASS}';\n"
        SQL_CONTENT+="GRANT ALL PRIVILEGES ON wp2_db.* TO 'wp2_user'@'%';\n"
    fi
    SQL_CONTENT+="FLUSH PRIVILEGES;\n"
    printf "%b" "$SQL_CONTENT" > db-init/01-init.sql
    success "db-init/01-init.sql created"
fi

# -- docker-compose.yml -------------------------------------------------------
cat > docker-compose.yml <<DCEOF
services:
DCEOF

# -- Cloudflare Tunnel --------------------------------------------------------
if [[ "$install_cf" == "y" ]]; then
cat >> docker-compose.yml <<DCEOF

  # -- Cloudflare Tunnel -------------------------------------------------------
  cloudflared:
    image: cloudflare/cloudflared:latest
    restart: always
    command: $CLOUDFLARED_CMD
    networks:
      - internal
DCEOF
    if [[ -n "$CF_ENV_LINE" ]]; then
cat >> docker-compose.yml <<DCEOF
    environment:
$CF_ENV_LINE
DCEOF
    fi
fi

# -- MariaDB (only when WP is needed) -----------------------------------------
if [[ "$need_db" == "y" ]]; then
cat >> docker-compose.yml <<DCEOF

  # -- Database ----------------------------------------------------------------
  db:
    image: mariadb:10.6
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: \${DB_ROOT_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql
      - ./db-init:/docker-entrypoint-initdb.d:ro
    networks:
      - internal
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 10s
      timeout: 5s
      retries: 5
DCEOF
fi

# -- Uptime Kuma --------------------------------------------------------------
if [[ "$install_kuma" == "y" ]]; then
cat >> docker-compose.yml <<DCEOF

  # -- Uptime Kuma -------------------------------------------------------------
  uptime-kuma:
    image: louislam/uptime-kuma:latest
    container_name: uptime-kuma
    restart: always
    volumes:
      - kuma_data:/app/data
    networks:
      - internal
DCEOF
fi

# -- WordPress 1 --------------------------------------------------------------
if [[ "$wp_count" -ge 1 ]]; then
cat >> docker-compose.yml <<DCEOF

  # -- WordPress 1 -------------------------------------------------------------
  wp1:
    image: wordpress:latest
    restart: always
    depends_on:
      db:
        condition: service_healthy
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wp1_user
      WORDPRESS_DB_PASSWORD: \${WP1_DB_PASSWORD}
      WORDPRESS_DB_NAME: wp1_db
    volumes:
      - wp1_data:/var/www/html
    networks:
      - internal
DCEOF
fi

# -- WordPress 2 --------------------------------------------------------------
if [[ "$wp_count" -ge 2 ]]; then
cat >> docker-compose.yml <<DCEOF

  # -- WordPress 2 -------------------------------------------------------------
  wp2:
    image: wordpress:latest
    restart: always
    depends_on:
      db:
        condition: service_healthy
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wp2_user
      WORDPRESS_DB_PASSWORD: \${WP2_DB_PASSWORD}
      WORDPRESS_DB_NAME: wp2_db
    volumes:
      - wp2_data:/var/www/html
    networks:
      - internal
DCEOF
fi

# -- Networks & Volumes -------------------------------------------------------
cat >> docker-compose.yml <<DCEOF

networks:
  internal:
    driver: bridge

volumes:
DCEOF

# Only add volumes that are actually used
[[ "$need_db" == "y" ]]      && echo "  db_data:"   >> docker-compose.yml
[[ "$install_kuma" == "y" ]] && echo "  kuma_data:" >> docker-compose.yml
[[ "$wp_count" -ge 1 ]]      && echo "  wp1_data:"  >> docker-compose.yml
[[ "$wp_count" -ge 2 ]]      && echo "  wp2_data:"  >> docker-compose.yml

success "docker-compose.yml created"

# =============================================================================
# Summary
# =============================================================================
echo ""
echo -e "${BOLD}================================================${RESET}"
echo -e "${BOLD}              Summary / Rezultat                ${RESET}"
echo -e "${BOLD}================================================${RESET}"

if [[ "$install_cf" == "y" ]]; then
    CF_LABEL="Yes ($([ "$cf_method" == "1" ] && echo "Token" || echo "Login"))"
else
    CF_LABEL="No"
fi

echo -e "  Cloudflare Tunnel : ${CYAN}$CF_LABEL${RESET}"
echo -e "  Uptime Kuma       : ${CYAN}$([ "$install_kuma" == "y" ] && echo "Yes" || echo "No")${RESET}"
echo -e "  WordPress sites   : ${CYAN}$wp_count${RESET}"
echo -e "  MariaDB           : ${CYAN}$([ "$need_db" == "y" ] && echo "Yes" || echo "No")${RESET}"
echo ""
echo -e "${BOLD}  Files created:${RESET}"
echo    "    .env                (chmod 600)"
echo    "    docker-compose.yml"
[[ "$need_db" == "y" ]] && echo "    db-init/01-init.sql"
echo ""
echo -e "${BOLD}  Next step:${RESET}"
echo -e "    ${GREEN}docker compose up -d${RESET}"
echo ""
warn "Keep .env in a safe place - it contains your passwords!"
echo -e "${BOLD}================================================${RESET}\n"