#!/bin/bash
# ============================================================
#  RemoteLink — Instalační skript pro Ubuntu 24.04
#  Multihostingový server (nginx + existující PHP/Python)
#  Nastaví: Node.js, PM2, nginx vhost, SSL (Let's Encrypt)
# ============================================================

set -e

# ── Barvy ────────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'

log()     { echo -e "${GREEN}[✓]${NC} $1"; }
info()    { echo -e "${CYAN}[→]${NC} $1"; }
warn()    { echo -e "${YELLOW}[!]${NC} $1"; }
error()   { echo -e "${RED}[✗]${NC} $1"; exit 1; }
section() { echo -e "\n${BOLD}${CYAN}━━━ $1 ━━━${NC}\n"; }

# ── Úvodní banner ─────────────────────────────────────────────
clear
echo -e "${CYAN}"
cat << 'EOF'
  ____                      _       _     _       _
 |  _ \ ___ _ __ ___   ___ | |_ ___| |   (_)_ __ | | __
 | |_) / _ \ '_ ` _ \ / _ \| __/ _ \ |   | | '_ \| |/ /
 |  _ <  __/ | | | | | (_) | ||  __/ |___| | | | |   <
 |_| \_\___|_| |_| |_|\___/ \__\___|_____|_|_| |_|_|\_\

EOF
echo -e "${NC}"
echo -e "${BOLD}Instalační skript pro Ubuntu 24.04${NC}"
echo -e "WebRTC vzdálená správa plochy\n"

# ── Root check ────────────────────────────────────────────────
if [[ $EUID -ne 0 ]]; then
  error "Spusť skript jako root: sudo bash install.sh"
fi

# ════════════════════════════════════════════════════════════
# KONFIGURACE — vyplň před spuštěním
# ════════════════════════════════════════════════════════════
section "Konfigurace"

# Doména (bez https://)
read -p "$(echo -e ${BOLD})Doména pro RemoteLink (např. remote.example.com): $(echo -e ${NC})" DOMAIN
[[ -z "$DOMAIN" ]] && error "Doména nesmí být prázdná"

# Instalační adresář
read -p "$(echo -e ${BOLD})Instalační adresář [/opt/remotelink]: $(echo -e ${NC})" INSTALL_DIR
INSTALL_DIR="${INSTALL_DIR:-/opt/remotelink}"

# Port WebSocket serveru (interní, za nginx)
read -p "$(echo -e ${BOLD})Interní port signaling serveru [9000]: $(echo -e ${NC})" WS_PORT
WS_PORT="${WS_PORT:-9000}"

# Uživatel pro běh serveru (ne root)
read -p "$(echo -e ${BOLD})Systémový uživatel pro službu [www-data]: $(echo -e ${NC})" RUN_USER
RUN_USER="${RUN_USER:-www-data}"

# SSL přes Let's Encrypt?
read -p "$(echo -e ${BOLD})Nastavit SSL certifikát přes Let's Encrypt? [Y/n]: $(echo -e ${NC})" DO_SSL
DO_SSL="${DO_SSL:-Y}"

# Email pro Let's Encrypt
if [[ "$DO_SSL" =~ ^[Yy]$ ]]; then
  read -p "$(echo -e ${BOLD})Email pro Let's Encrypt: $(echo -e ${NC})" LE_EMAIL
  [[ -z "$LE_EMAIL" ]] && error "Email je povinný pro Let's Encrypt"
fi

echo ""
info "Doména:       $DOMAIN"
info "Adresář:      $INSTALL_DIR"
info "WS port:      $WS_PORT"
info "Uživatel:     $RUN_USER"
info "SSL:          $([[ "$DO_SSL" =~ ^[Yy]$ ]] && echo 'Ano (Let\'s Encrypt)' || echo 'Ne')"
echo ""
read -p "$(echo -e ${BOLD})Pokračovat? [Y/n]: $(echo -e ${NC})" CONFIRM
[[ "$CONFIRM" =~ ^[Nn]$ ]] && echo "Zrušeno." && exit 0

# ════════════════════════════════════════════════════════════
section "Systémové závislosti"
# ════════════════════════════════════════════════════════════

info "Aktualizuji balíčky..."
apt-get update -qq

# nginx
if ! command -v nginx &>/dev/null; then
  info "Instaluji nginx..."
  apt-get install -y -qq nginx
  log "nginx nainstalován"
else
  log "nginx již nainstalován ($(nginx -v 2>&1 | head -1))"
fi

# Node.js
if ! command -v node &>/dev/null || [[ $(node -e "process.exit(parseInt(process.version.slice(1)) < 18 ? 1 : 0)" ; echo $?) == "1" ]]; then
  info "Instaluji Node.js 20 LTS..."
  curl -fsSL https://deb.nodesource.com/setup_20.x | bash - -qq
  apt-get install -y -qq nodejs
  log "Node.js $(node -v) nainstalován"
else
  log "Node.js $(node -v) již nainstalován"
fi

# PM2 (process manager)
if ! command -v pm2 &>/dev/null; then
  info "Instaluji PM2..."
  npm install -g pm2 -q
  log "PM2 nainstalován"
else
  log "PM2 $(pm2 -v) již nainstalován"
fi

# certbot (jen při SSL)
if [[ "$DO_SSL" =~ ^[Yy]$ ]]; then
  if ! command -v certbot &>/dev/null; then
    info "Instaluji Certbot..."
    apt-get install -y -qq certbot python3-certbot-nginx
    log "Certbot nainstalován"
  else
    log "Certbot již nainstalován"
  fi
fi

# ════════════════════════════════════════════════════════════
section "Instalace RemoteLink serveru"
# ════════════════════════════════════════════════════════════

info "Vytvářím adresář $INSTALL_DIR..."
mkdir -p "$INSTALL_DIR"
cd "$INSTALL_DIR"

# ── server.js ─────────────────────────────────────────────────
info "Zapisuji server.js..."
cat > server.js << 'SERVEREOF'
/**
 * RemoteLink Signaling Server
 */
'use strict';

const WebSocket = require('ws');
const { randomBytes } = require('crypto');
const PORT = process.env.PORT || 9000;

const wss = new WebSocket.Server({ port: PORT });
const rooms   = new Map(); // roomId -> { host, viewer, password }
const clients = new Map(); // ws -> { roomId, role }

function genId() {
  const n = (Math.floor(Math.random() * 900000000) + 100000000).toString();
  return `${n.slice(0,3)}-${n.slice(3,6)}-${n.slice(6,9)}`;
}

function send(ws, obj) {
  if (ws?.readyState === WebSocket.OPEN) ws.send(JSON.stringify(obj));
}

wss.on('connection', ws => {
  ws.on('message', raw => {
    let msg; try { msg = JSON.parse(raw); } catch { return; }
    const { type } = msg;

    if (type === 'register') {
      const roomId   = genId();
      const password = msg.password || randomBytes(4).toString('hex').toUpperCase();
      rooms.set(roomId, { host: ws, viewer: null, password });
      clients.set(ws, { roomId, role: 'host' });
      send(ws, { type: 'registered', roomId, password });
    }

    else if (type === 'join') {
      const { roomId, password } = msg;
      const room = rooms.get(roomId);
      if (!room)                  return send(ws, { type:'error', code:'NOT_FOUND',       message:'ID neexistuje' });
      if (room.password!==password) return send(ws, { type:'error', code:'WRONG_PASSWORD', message:'Chybné heslo' });
      if (room.viewer)            return send(ws, { type:'error', code:'BUSY',             message:'Již připojeno' });
      room.viewer = ws;
      clients.set(ws, { roomId, role: 'viewer' });
      send(ws,       { type: 'joined', roomId });
      send(room.host,{ type: 'viewer_joined' });
    }

    else if (['offer','answer','ice_candidate'].includes(type)) {
      const info = clients.get(ws); if (!info) return;
      const room = rooms.get(info.roomId); if (!room) return;
      send(info.role==='host' ? room.viewer : room.host, msg);
    }

    else if (['chat','file_meta','file_chunk','file_done',
              'mouse_move','mouse_click','key_event','scroll'].includes(type)) {
      const info = clients.get(ws); if (!info) return;
      const room = rooms.get(info.roomId); if (!room) return;
      const target = info.role==='host' ? room.viewer : room.host;
      if (type==='chat') send(target, { type:'chat', from:info.role, text:msg.text, ts:Date.now() });
      else send(target, msg);
    }

    else if (type === 'leave') { handleDisconnect(ws); }
  });

  ws.on('close', () => handleDisconnect(ws));
  ws.on('error', err => console.error('[WS ERROR]', err.message));
});

function handleDisconnect(ws) {
  const info = clients.get(ws); if (!info) return;
  const room = rooms.get(info.roomId);
  if (room) {
    const peer = info.role==='host' ? room.viewer : room.host;
    send(peer, { type:'peer_disconnected', role:info.role });
    if (info.role==='host') rooms.delete(info.roomId);
    else room.viewer = null;
  }
  clients.delete(ws);
}

console.log(`✅ RemoteLink Signaling Server → ws://localhost:${PORT}`);
SERVEREOF

# ── package.json ──────────────────────────────────────────────
info "Zapisuji package.json..."
cat > package.json << PKGEOF
{
  "name": "remotelink-server",
  "version": "1.0.0",
  "main": "server.js",
  "scripts": { "start": "node server.js" },
  "dependencies": { "ws": "^8.16.0" }
}
PKGEOF

# ── Instalace npm závislostí ──────────────────────────────────
info "Instaluji npm závislosti..."
npm install --omit=dev -q
log "npm závislosti nainstalovány"

# ── Oprávnění ─────────────────────────────────────────────────
chown -R "$RUN_USER:$RUN_USER" "$INSTALL_DIR"
log "Oprávnění nastavena pro $RUN_USER"

# ════════════════════════════════════════════════════════════
section "PM2 — Process Manager"
# ════════════════════════════════════════════════════════════

# Ecosystem config
cat > ecosystem.config.js << ECOEOF
module.exports = {
  apps: [{
    name:        'remotelink',
    script:      'server.js',
    cwd:         '$INSTALL_DIR',
    user:        '$RUN_USER',
    env: {
      PORT:      '$WS_PORT',
      NODE_ENV:  'production'
    },
    watch:       false,
    max_restarts: 10,
    restart_delay: 3000,
    error_file:  '/var/log/remotelink/error.log',
    out_file:    '/var/log/remotelink/out.log',
    merge_logs:  true,
    log_date_format: 'YYYY-MM-DD HH:mm:ss'
  }]
};
ECOEOF

# Log adresář
mkdir -p /var/log/remotelink
chown "$RUN_USER:$RUN_USER" /var/log/remotelink

# Spuštění přes PM2
info "Spouštím RemoteLink přes PM2..."
sudo -u "$RUN_USER" pm2 start "$INSTALL_DIR/ecosystem.config.js" 2>/dev/null || \
  pm2 start "$INSTALL_DIR/ecosystem.config.js"

# Autostart po rebootu
info "Nastavuji PM2 autostart..."
pm2 startup systemd -u "$RUN_USER" --hp "/home/$RUN_USER" 2>/dev/null || \
  pm2 startup systemd 2>/dev/null || true
pm2 save
log "PM2 nakonfigurován"

# ════════════════════════════════════════════════════════════
section "nginx — Virtual Host"
# ════════════════════════════════════════════════════════════

NGINX_CONF="/etc/nginx/sites-available/remotelink-${DOMAIN}"

info "Vytvářím nginx vhost pro $DOMAIN..."

cat > "$NGINX_CONF" << NGINXEOF
# RemoteLink — $DOMAIN
# Generováno: $(date)

map \$http_upgrade \$connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    listen [::]:80;
    server_name $DOMAIN;

    # Let's Encrypt challenge
    location /.well-known/acme-challenge/ {
        root /var/www/html;
    }

    # WebSocket signaling endpoint
    location /ws {
        proxy_pass         http://127.0.0.1:$WS_PORT;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade \$http_upgrade;
        proxy_set_header   Connection \$connection_upgrade;
        proxy_set_header   Host \$host;
        proxy_set_header   X-Real-IP \$remote_addr;
        proxy_set_header   X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_read_timeout  86400s;
        proxy_send_timeout  86400s;
        proxy_buffering off;
    }

    # Status stránka (volitelně zakomentuji po SSL)
    location / {
        return 200 'RemoteLink OK';
        add_header Content-Type text/plain;
    }
}
NGINXEOF

# Aktivace vhostu
ln -sf "$NGINX_CONF" "/etc/nginx/sites-enabled/remotelink-${DOMAIN}"

# Test konfigurace
info "Testuji nginx konfiguraci..."
nginx -t 2>&1 | grep -E "ok|error" || true
nginx -t || error "nginx konfigurace je chybná — zkontroluj /etc/nginx/sites-available/"

# Reload nginx
info "Restartuji nginx..."
systemctl reload nginx
log "nginx vhost aktivován"

# ════════════════════════════════════════════════════════════
section "SSL certifikát (Let's Encrypt)"
# ════════════════════════════════════════════════════════════

if [[ "$DO_SSL" =~ ^[Yy]$ ]]; then
  info "Získávám SSL certifikát pro $DOMAIN..."

  certbot --nginx \
    -d "$DOMAIN" \
    --email "$LE_EMAIL" \
    --agree-tos \
    --non-interactive \
    --redirect \
    2>&1 | tail -10

  if [[ $? -eq 0 ]]; then
    log "SSL certifikát nainstalován"

    # Přidat WebSocket proxy do HTTPS bloku (certbot přidal :443)
    # Nginx conf už má /ws location — certbot ho zachová
    systemctl reload nginx
    log "nginx s SSL restartován"

    # Obnova certifikátu
    if ! crontab -l 2>/dev/null | grep -q certbot; then
      (crontab -l 2>/dev/null; echo "0 3 * * * certbot renew --quiet --post-hook 'systemctl reload nginx'") | crontab -
      log "Automatická obnova SSL nastavena (každý den ve 3:00)"
    fi

    WS_PROTOCOL="wss"
  else
    warn "SSL certifikát se nepodařilo získat — pokračuji bez SSL"
    WS_PROTOCOL="ws"
  fi
else
  WS_PROTOCOL="ws"
fi

# ════════════════════════════════════════════════════════════
section "Firewall (UFW)"
# ════════════════════════════════════════════════════════════

if command -v ufw &>/dev/null; then
  info "Nastavuji UFW firewall..."
  ufw allow 22/tcp   comment 'SSH'      2>/dev/null || true
  ufw allow 80/tcp   comment 'HTTP'     2>/dev/null || true
  ufw allow 443/tcp  comment 'HTTPS'    2>/dev/null || true
  # Port 9000 NEOTEVÍRÁME — přístup jen přes nginx/localhost
  log "UFW porty nastaveny (22, 80, 443)"
else
  warn "UFW není nainstalován — zkontroluj firewall ručně"
fi

# ════════════════════════════════════════════════════════════
section "Aktualizace klienta"
# ════════════════════════════════════════════════════════════

WS_URL="${WS_PROTOCOL}://${DOMAIN}/ws"

info "Generuji instrukce pro klientskou aplikaci..."

cat > "$INSTALL_DIR/CLIENT_CONFIG.txt" << CLIENTEOF
════════════════════════════════════════════════════
 RemoteLink — Konfigurace klientské aplikace
════════════════════════════════════════════════════

V souboru  app/src/app.js  na řádku 8 změň:

  const SIGNAL_URL = '$WS_URL';

════════════════════════════════════════════════════
CLIENTEOF

cat "$INSTALL_DIR/CLIENT_CONFIG.txt"

# ════════════════════════════════════════════════════════════
section "Instalace dokončena!"
# ════════════════════════════════════════════════════════════

echo -e "${GREEN}${BOLD}"
cat << DONEEOF
╔══════════════════════════════════════════════════════╗
║           RemoteLink úspěšně nainstalován!           ║
╠══════════════════════════════════════════════════════╣
║                                                      ║
║  Signaling server:  $WS_URL
║  Instalační dir:    $INSTALL_DIR
║  Konfig nginx:      $NGINX_CONF
║  PM2 služba:        remotelink
║                                                      ║
╠══════════════════════════════════════════════════════╣
║  Užitečné příkazy:                                   ║
║                                                      ║
║  pm2 status                 # stav serveru           ║
║  pm2 logs remotelink        # logy                   ║
║  pm2 restart remotelink     # restart                ║
║  nginx -t && nginx -s reload # reload nginx          ║
║                                                      ║
║  Logy:  /var/log/remotelink/                         ║
╚══════════════════════════════════════════════════════╝
DONEEOF
echo -e "${NC}"

echo -e "${BOLD}Další krok:${NC} Otevři  app/src/app.js  a nastav:"
echo -e "  ${CYAN}const SIGNAL_URL = '${WS_URL}';${NC}"
echo ""
