#!/usr/bin/env bash
# =============================================================================
# TapPass + MediTap School Server Setup
# Ubuntu 22.04 LTS
# =============================================================================
set -euo pipefail

# ── Colour helpers ─────────────────────────────────────────────────────────────
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 "${GREEN}[INFO]${RESET}  $*"; }
warn()    { echo -e "${YELLOW}[WARN]${RESET}  $*"; }
error()   { echo -e "${RED}[ERROR]${RESET} $*" >&2; }
section() { echo -e "\n${CYAN}${BOLD}━━━  $*  ━━━${RESET}"; }

# ── Utility: generate a random password ───────────────────────────────────────
gen_password() {
    tr -dc 'A-Za-z0-9!@#%^&*()_+' </dev/urandom | head -c 24
}

# ── 1. Root check ──────────────────────────────────────────────────────────────
section "Pre-flight checks"

if [[ $EUID -ne 0 ]]; then
    error "This script must be run as root. Try: sudo bash $0"
    exit 1
fi
info "Running as root — OK"

# ── 2. Ubuntu 22.04 check ─────────────────────────────────────────────────────
if [[ -f /etc/os-release ]]; then
    source /etc/os-release
    if [[ "${ID}" != "ubuntu" || "${VERSION_ID}" != "22.04" ]]; then
        warn "This script is designed for Ubuntu 22.04 LTS."
        warn "Detected: ${PRETTY_NAME:-unknown}"
        read -r -p "Continue anyway? [y/N] " _confirm
        [[ "${_confirm,,}" == "y" ]] || { error "Aborted."; exit 1; }
    else
        info "Ubuntu 22.04 LTS — OK"
    fi
else
    warn "/etc/os-release not found — cannot verify OS version."
fi

# ── Welcome banner ─────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}╔══════════════════════════════════════════════════════════════╗${RESET}"
echo -e "${BOLD}║        TapPass + MediTap School Server Setup                 ║${RESET}"
echo -e "${BOLD}╠══════════════════════════════════════════════════════════════╣${RESET}"
echo -e "${BOLD}║  This script will install and configure:                     ║${RESET}"
echo -e "${BOLD}║   • Apache 2   (web server)                                  ║${RESET}"
echo -e "${BOLD}║   • MySQL 8    (database server)                              ║${RESET}"
echo -e "${BOLD}║   • PHP 8.2    (runtime + extensions)                        ║${RESET}"
echo -e "${BOLD}║   • UFW        (firewall)                                    ║${RESET}"
echo -e "${BOLD}║   • TapPass    virtual host + database                       ║${RESET}"
echo -e "${BOLD}║   • MediTap    virtual host + database                       ║${RESET}"
echo -e "${BOLD}║   • Daily backup cron + per-5-min cron for TapPass          ║${RESET}"
echo -e "${BOLD}╚══════════════════════════════════════════════════════════════╝${RESET}"
echo ""

# ── 3. Gather configuration variables ─────────────────────────────────────────
section "Configuration"

read -r -p "Server hostname or IP address [$(hostname -I | awk '{print $1}')]: " SERVER_HOSTNAME
SERVER_HOSTNAME="${SERVER_HOSTNAME:-$(hostname -I | awk '{print $1}')}"

read -r -p "TapPass database name [tappass]: " TAPPASS_DB_NAME
TAPPASS_DB_NAME="${TAPPASS_DB_NAME:-tappass}"

read -r -p "TapPass database username [tappass_user]: " TAPPASS_DB_USER
TAPPASS_DB_USER="${TAPPASS_DB_USER:-tappass_user}"

read -r -p "TapPass database password [auto-generate]: " TAPPASS_DB_PASS
if [[ -z "${TAPPASS_DB_PASS}" ]]; then
    TAPPASS_DB_PASS="$(gen_password)"
    info "Generated TapPass DB password: ${TAPPASS_DB_PASS}"
fi

read -r -p "MediTap database name [meditap]: " MEDITAP_DB_NAME
MEDITAP_DB_NAME="${MEDITAP_DB_NAME:-meditap}"

read -r -p "MediTap database username [meditap_user]: " MEDITAP_DB_USER
MEDITAP_DB_USER="${MEDITAP_DB_USER:-meditap_user}"

read -r -p "MediTap database password [auto-generate]: " MEDITAP_DB_PASS
if [[ -z "${MEDITAP_DB_PASS}" ]]; then
    MEDITAP_DB_PASS="$(gen_password)"
    info "Generated MediTap DB password: ${MEDITAP_DB_PASS}"
fi

read -r -p "MySQL root password [auto-generate]: " MYSQL_ROOT_PASS
if [[ -z "${MYSQL_ROOT_PASS}" ]]; then
    MYSQL_ROOT_PASS="$(gen_password)"
    info "Generated MySQL root password: ${MYSQL_ROOT_PASS}"
fi

echo ""
info "Configuration summary:"
info "  Server:          ${SERVER_HOSTNAME}"
info "  TapPass DB:      ${TAPPASS_DB_NAME} / ${TAPPASS_DB_USER}"
info "  MediTap DB:      ${MEDITAP_DB_NAME} / ${MEDITAP_DB_USER}"
echo ""
read -r -p "Proceed with installation? [Y/n] " _go
[[ "${_go,,}" != "n" ]] || { warn "Aborted by user."; exit 0; }

# ── 4. System update ───────────────────────────────────────────────────────────
section "System update"
apt-get update -y
apt-get upgrade -y
info "System updated."

# ── 5. Install packages ────────────────────────────────────────────────────────
section "Installing packages"
DEBIAN_FRONTEND=noninteractive apt-get install -y \
    apache2 \
    mysql-server \
    php8.2 \
    libapache2-mod-php8.2 \
    php8.2-mysql \
    php8.2-curl \
    php8.2-mbstring \
    php8.2-xml \
    php8.2-zip \
    php8.2-gd \
    curl \
    unzip \
    ufw
info "Packages installed."

# ── 6. Load MySQL timezone data ───────────────────────────────────────────────
section "Loading MySQL timezone data"
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql || warn "Timezone data load encountered errors (may be harmless)."
info "Timezone data loaded."

# ── 7. Configure MySQL ────────────────────────────────────────────────────────
section "Configuring MySQL"

# Set root password and create databases/users
mysql -u root <<SQL
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '${MYSQL_ROOT_PASS}';

CREATE DATABASE IF NOT EXISTS \`${TAPPASS_DB_NAME}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS '${TAPPASS_DB_USER}'@'localhost' IDENTIFIED BY '${TAPPASS_DB_PASS}';
GRANT ALL PRIVILEGES ON \`${TAPPASS_DB_NAME}\`.* TO '${TAPPASS_DB_USER}'@'localhost';

CREATE DATABASE IF NOT EXISTS \`${MEDITAP_DB_NAME}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS '${MEDITAP_DB_USER}'@'localhost' IDENTIFIED BY '${MEDITAP_DB_PASS}';
GRANT ALL PRIVILEGES ON \`${MEDITAP_DB_NAME}\`.* TO '${MEDITAP_DB_USER}'@'localhost';

FLUSH PRIVILEGES;
SQL

info "MySQL root password set."
info "Database '${TAPPASS_DB_NAME}' and user '${TAPPASS_DB_USER}' created."
info "Database '${MEDITAP_DB_NAME}' and user '${MEDITAP_DB_USER}' created."

# ── 8. Create web root directories ────────────────────────────────────────────
section "Creating web root directories"

for DIR in /var/www/tappass /var/www/meditap; do
    mkdir -p "${DIR}"
    chown -R www-data:www-data "${DIR}"
    find "${DIR}" -type d -exec chmod 755 {} \;
    find "${DIR}" -type f -exec chmod 644 {} \;
    info "Created ${DIR}"
done

# Create placeholder index files so Apache returns 200 before files are uploaded
for DIR in /var/www/tappass /var/www/meditap; do
    if [[ ! -f "${DIR}/index.php" ]]; then
        echo '<?php echo "Ready — please upload application files.";' > "${DIR}/index.php"
        chown www-data:www-data "${DIR}/index.php"
        chmod 644 "${DIR}/index.php"
    fi
done

# ── 9. Write Apache virtual host configs ──────────────────────────────────────
section "Configuring Apache virtual hosts"

cat > /etc/apache2/sites-available/tappass.conf <<VHOST
<VirtualHost *:80>
    ServerName ${SERVER_HOSTNAME}
    DocumentRoot /var/www/tappass

    <Directory /var/www/tappass>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog  \${APACHE_LOG_DIR}/tappass_error.log
    CustomLog \${APACHE_LOG_DIR}/tappass_access.log combined
</VirtualHost>
VHOST

cat > /etc/apache2/sites-available/meditap.conf <<VHOST
<VirtualHost *:80>
    ServerName ${SERVER_HOSTNAME}
    DocumentRoot /var/www/meditap

    <Directory /var/www/meditap>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog  \${APACHE_LOG_DIR}/meditap_error.log
    CustomLog \${APACHE_LOG_DIR}/meditap_access.log combined
</VirtualHost>
VHOST

info "Virtual host configs written."

# ── 10. Enable Apache modules and sites ───────────────────────────────────────
section "Enabling Apache modules and sites"

a2enmod rewrite
a2enmod headers
a2ensite tappass.conf
a2ensite meditap.conf
a2dissite 000-default.conf 2>/dev/null || true

info "mod_rewrite, mod_headers enabled. tappass and meditap sites enabled."

# ── 11. Configure UFW firewall ────────────────────────────────────────────────
section "Configuring UFW firewall"

ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable

info "UFW configured: OpenSSH, HTTP (80), HTTPS (443) allowed."

# ── 12. Create backup directory and backup script ─────────────────────────────
section "Setting up backup infrastructure"

mkdir -p /var/backups/tappass
chown root:root /var/backups/tappass
chmod 700 /var/backups/tappass

cat > /usr/local/bin/tappass-backup.sh <<'BACKUPSCRIPT'
#!/usr/bin/env bash
# =============================================================================
# TapPass Automated Backup Script
# Backs up the tappass and meditap databases.
# Run daily via cron at 2:00 AM.
# =============================================================================
set -euo pipefail

BACKUP_DIR="/var/backups/tappass"
DATE="$(date +%Y-%m-%d_%H-%M-%S)"
RETENTION_DAYS=30
MYSQL_CREDS_FILE="/etc/tappass-mysql.cnf"
SUCCESS=true

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }

mkdir -p "${BACKUP_DIR}"

# ── Dump a single database ────────────────────────────────────────────────────
dump_database() {
    local db_name="$1"
    local db_user="$2"
    local db_pass="$3"
    local out_file="${BACKUP_DIR}/${db_name}_${DATE}.sql.gz"

    log "Backing up database: ${db_name}"
    if mysqldump \
        --user="${db_user}" \
        --password="${db_pass}" \
        --single-transaction \
        --routines \
        --triggers \
        "${db_name}" | gzip -9 > "${out_file}"; then
        log "  Saved to ${out_file} ($(du -sh "${out_file}" | cut -f1))"
    else
        log "  ERROR: Failed to back up ${db_name}"
        SUCCESS=false
    fi
}

# ── Read TapPass credentials ──────────────────────────────────────────────────
if [[ -f "${MYSQL_CREDS_FILE}" ]]; then
    source "${MYSQL_CREDS_FILE}"
else
    log "WARNING: ${MYSQL_CREDS_FILE} not found — skipping database backups."
    exit 1
fi

dump_database "${TAPPASS_DB_NAME}"  "${TAPPASS_DB_USER}"  "${TAPPASS_DB_PASS}"
dump_database "${MEDITAP_DB_NAME}"  "${MEDITAP_DB_USER}"  "${MEDITAP_DB_PASS}"

# ── Remove backups older than retention period ────────────────────────────────
log "Removing backups older than ${RETENTION_DAYS} days..."
find "${BACKUP_DIR}" -name "*.sql.gz" -mtime "+${RETENTION_DAYS}" -delete
log "Cleanup complete."

if $SUCCESS; then
    log "Backup completed successfully."
    exit 0
else
    log "Backup completed with errors."
    exit 1
fi
BACKUPSCRIPT

chmod 750 /usr/local/bin/tappass-backup.sh

# Write MySQL credentials file for the backup script
cat > /etc/tappass-mysql.cnf <<CREDS
# TapPass MySQL credentials — keep this file secure (chmod 600)
TAPPASS_DB_NAME="${TAPPASS_DB_NAME}"
TAPPASS_DB_USER="${TAPPASS_DB_USER}"
TAPPASS_DB_PASS="${TAPPASS_DB_PASS}"
MEDITAP_DB_NAME="${MEDITAP_DB_NAME}"
MEDITAP_DB_USER="${MEDITAP_DB_USER}"
MEDITAP_DB_PASS="${MEDITAP_DB_PASS}"
CREDS
chmod 600 /etc/tappass-mysql.cnf

info "Backup script written to /usr/local/bin/tappass-backup.sh"
info "MySQL credentials stored in /etc/tappass-mysql.cnf (mode 600)"

# ── 13. Set up daily backup cron at 2:00 AM ───────────────────────────────────
section "Setting up cron jobs"

# Daily backup cron (root)
BACKUP_CRON="0 2 * * * /usr/local/bin/tappass-backup.sh >> /var/log/tappass-backup.log 2>&1"
(crontab -l 2>/dev/null | grep -vF 'tappass-backup.sh'; echo "${BACKUP_CRON}") | crontab -
info "Daily backup cron set (2:00 AM)."

# ── 14. Set up cron for build_hourly_out.php (www-data, every 5 minutes) ──────
HOURLY_OUT_PATH="/var/www/tappass/cron/build_hourly_out.php"
HOURLY_CRON="*/5 * * * * /usr/bin/php ${HOURLY_OUT_PATH} >> /var/log/tappass-hourly-out.log 2>&1"

# Install into www-data's crontab
(crontab -u www-data -l 2>/dev/null | grep -vF 'build_hourly_out.php'; echo "${HOURLY_CRON}") \
    | crontab -u www-data -
info "build_hourly_out.php cron set (every 5 minutes, www-data)."

# ── 15. Restart services ──────────────────────────────────────────────────────
section "Restarting services"
systemctl restart mysql
systemctl restart apache2
systemctl enable mysql
systemctl enable apache2
info "Apache and MySQL restarted and enabled on boot."

# ── 16. Summary ───────────────────────────────────────────────────────────────
SERVER_IP="$(hostname -I | awk '{print $1}')"

echo ""
echo -e "${BOLD}${GREEN}╔══════════════════════════════════════════════════════════════╗${RESET}"
echo -e "${BOLD}${GREEN}║                   INSTALLATION COMPLETE                     ║${RESET}"
echo -e "${BOLD}${GREEN}╠══════════════════════════════════════════════════════════════╣${RESET}"
echo -e "${BOLD}${GREEN}║  Server IP:    ${SERVER_IP}${RESET}"
echo ""
echo -e "${BOLD}${GREEN}║  TapPass URL:  http://${SERVER_IP}/install.php${RESET}"
echo -e "${BOLD}${GREEN}║  MediTap URL:  http://${SERVER_IP}/${RESET}"
echo ""
echo -e "${BOLD}${YELLOW}  ── TapPass Database ─────────────────────────────────────────${RESET}"
echo -e "  Database : ${TAPPASS_DB_NAME}"
echo -e "  Username : ${TAPPASS_DB_USER}"
echo -e "  Password : ${TAPPASS_DB_PASS}"
echo ""
echo -e "${BOLD}${YELLOW}  ── MediTap Database ─────────────────────────────────────────${RESET}"
echo -e "  Database : ${MEDITAP_DB_NAME}"
echo -e "  Username : ${MEDITAP_DB_USER}"
echo -e "  Password : ${MEDITAP_DB_PASS}"
echo ""
echo -e "${BOLD}${YELLOW}  ── MySQL Root ────────────────────────────────────────────────${RESET}"
echo -e "  Password : ${MYSQL_ROOT_PASS}"
echo ""
echo -e "${BOLD}${CYAN}  ── Next Steps ────────────────────────────────────────────────${RESET}"
echo -e "  1. Upload TapPass files to /var/www/tappass/"
echo -e "  2. Upload MediTap files to /var/www/meditap/"
echo -e "  3. Visit http://${SERVER_IP}/install.php to complete TapPass setup"
echo -e "  4. DELETE install.php after installation is finished"
echo -e "  5. SSH reminder: use key-based auth, disable password login"
echo ""
echo -e "${BOLD}${CYAN}  ── Backups ────────────────────────────────────────────────────${RESET}"
echo -e "  Location  : /var/backups/tappass/"
echo -e "  Schedule  : Daily at 2:00 AM"
echo -e "  Retention : 30 days"
echo -e "  Log       : /var/log/tappass-backup.log"
echo ""
echo -e "${BOLD}${GREEN}╚══════════════════════════════════════════════════════════════╝${RESET}"
echo ""
warn "Save the credentials above in a secure password manager before closing this terminal."
