#!/bin/bash
# =============================================================================
# Matrix Synapse + Element Web Bare-Metal Install Script
# For Ubuntu 24.04 LTS
# =============================================================================
# Usage:
#   export DOMAIN="mx.example.com"
#   export ADMIN_USER="admin"
#   export ADMIN_EMAIL="admin@example.com"
#   curl -sSL https://git.vish.gg/Vish/matrix-element/raw/branch/main/install-baremetal.sh | bash
#
# Run as root on a fresh Ubuntu 24.04 VM
# =============================================================================

set -e

# Configuration
DOMAIN="${DOMAIN:-mx.example.com}"
ADMIN_USER="${ADMIN_USER:-admin}"
ADMIN_EMAIL="${ADMIN_EMAIL:-admin@example.com}"
TURN_DOMAIN="${TURN_DOMAIN:-$DOMAIN}"
TURN_PORT="${TURN_PORT:-3479}"
TURN_TLS_PORT="${TURN_TLS_PORT:-5350}"
TURN_MIN_PORT="${TURN_MIN_PORT:-49201}"
TURN_MAX_PORT="${TURN_MAX_PORT:-49250}"
ELEMENT_VERSION="${ELEMENT_VERSION:-v1.12.8}"
LISTEN_PORT="${LISTEN_PORT:-8080}"

echo "=========================================="
echo "Matrix Synapse + Element Web Installer"
echo "=========================================="
echo "Domain: $DOMAIN"
echo "Admin: $ADMIN_USER"
echo "=========================================="

# Check root
if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root"
   exit 1
fi

# Update system
echo "[1/10] Updating system..."
apt update && apt upgrade -y

# Install dependencies
echo "[2/10] Installing dependencies..."
apt install -y postgresql postgresql-contrib nginx coturn \
    python3-pip python3-venv python3-dev build-essential \
    libffi-dev libssl-dev libjpeg-dev libxslt1-dev \
    curl wget git jq

# Create synapse user
echo "[3/10] Creating synapse user..."
useradd -r -m -d /opt/synapse -s /bin/bash synapse 2>/dev/null || true
mkdir -p /opt/synapse /opt/element
chown synapse:synapse /opt/synapse

# Setup PostgreSQL
echo "[4/10] Setting up PostgreSQL..."
DB_PASS="REDACTED_PASSWORD" rand -hex 16)
sudo -u postgres psql -c "CREATE USER synapse WITH PASSWORD 'REDACTED_PASSWORD';" 2>/dev/null || \
sudo -u postgres psql -c "ALTER USER synapse WITH PASSWORD 'REDACTED_PASSWORD';"
sudo -u postgres psql -c "CREATE DATABASE synapse ENCODING 'UTF8' LC_COLLATE='C' LC_CTYPE='C' template=template0 OWNER synapse;" 2>/dev/null || true

# Install Synapse
echo "[5/10] Installing Synapse..."
sudo -u synapse bash << SYNAPSE_INSTALL
cd /opt/synapse
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip setuptools wheel
pip install matrix-synapse psycopg2-binary lxml 'prometheus-client<0.21'
SYNAPSE_INSTALL

# Generate config
echo "[6/10] Generating Synapse configuration..."
cd /opt/synapse
sudo -u synapse /opt/synapse/venv/bin/python -m synapse.app.homeserver \
    --server-name "$DOMAIN" \
    --config-path homeserver.yaml \
    --generate-config \
    --report-stats=no

# Get generated secrets
REG_SECRET=$(grep 'registration_shared_secret' homeserver.yaml | head -1 | awk '{print $2}')
MAC_SECRET=$(grep 'macaroon_secret_key' homeserver.yaml | head -1 | awk '{print $2}')
FORM_SECRET=$(grep 'form_secret' homeserver.yaml | head -1 | awk '{print $2}')
TURN_SECRET=$(openssl rand -hex 32)

# Create production config
cat > /opt/synapse/homeserver.yaml << YAML
server_name: "$DOMAIN"
pid_file: /opt/synapse/homeserver.pid
public_baseurl: https://$DOMAIN/

listeners:
  - port: 8008
    tls: false
    type: http
    x_forwarded: true
    resources:
      - names: [client, federation]
        compress: false

database:
  name: psycopg2
  args:
    user: synapse
    password: "REDACTED_PASSWORD"
    database: synapse
    host: localhost
    cp_min: 5
    cp_max: 10

log_config: "/opt/synapse/$DOMAIN.log.config"
media_store_path: /opt/synapse/media_store
signing_key_path: "/opt/synapse/$DOMAIN.signing.key"
trusted_key_servers:
  - server_name: "matrix.org"

registration_shared_secret: $REG_SECRET
macaroon_secret_key: $MAC_SECRET
form_secret: $FORM_SECRET

enable_registration: false
enable_registration_without_verification: false

turn_uris:
  - "turn:$TURN_DOMAIN:$TURN_PORT?transport=udp"
  - "turn:$TURN_DOMAIN:$TURN_PORT?transport=tcp"
  - "turns:$TURN_DOMAIN:$TURN_TLS_PORT?transport=udp"
  - "turns:$TURN_DOMAIN:$TURN_TLS_PORT?transport=tcp"
turn_shared_secret: "$TURN_SECRET"
turn_user_lifetime: 86400000
turn_allow_guests: true

max_upload_size: 100M
url_preview_enabled: true
url_preview_ip_range_blacklist:
  - '127.0.0.0/8'
  - '10.0.0.0/8'
  - '172.16.0.0/12'
  - '192.168.0.0/16'
  - '100.64.0.0/10'
  - '169.254.0.0/16'
  - '::1/128'
  - 'fe80::/64'
  - 'fc00::/7'

suppress_key_server_warning: true
enable_metrics: false
report_stats: false
YAML

# Validate YAML configuration
echo "Validating Synapse configuration..."
python3 -c "import yaml; yaml.safe_load(open('/opt/synapse/homeserver.yaml'))" || {
    echo "ERROR: Invalid YAML in homeserver.yaml"
    exit 1
}

mkdir -p /opt/synapse/media_store
chown -R synapse:synapse /opt/synapse

# Configure coturn
echo "[7/10] Configuring TURN server..."
cat > /etc/turnserver.conf << TURN
listening-port=$TURN_PORT
tls-listening-port=$TURN_TLS_PORT
fingerprint
use-auth-secret
static-auth-secret=$TURN_SECRET
realm=$DOMAIN
total-quota=100
bps-capacity=0
stale-nonce=600
no-multicast-peers
min-port=$TURN_MIN_PORT
max-port=$TURN_MAX_PORT
log-file=/var/log/turnserver.log
TURN

# Download Element Web
echo "[8/10] Installing Element Web..."
cd /opt/element
wget -q "https://github.com/element-hq/element-web/releases/download/$ELEMENT_VERSION/element-$ELEMENT_VERSION.tar.gz"
tar xzf "element-$ELEMENT_VERSION.tar.gz"
mv "element-$ELEMENT_VERSION" web
rm "element-$ELEMENT_VERSION.tar.gz"

cat > /opt/element/web/config.json << ELEMENT
{
    "default_server_config": {
        "m.homeserver": {
            "base_url": "https://$DOMAIN",
            "server_name": "$DOMAIN"
        }
    },
    "disable_guests": true,
    "default_theme": "dark",
    "room_directory": {
        "servers": ["matrix.org", "$DOMAIN"]
    }
}
ELEMENT

# Configure nginx
echo "[9/10] Configuring nginx..."
cat > /etc/nginx/sites-available/matrix << NGINX
server {
    listen $LISTEN_PORT;
    listen [::]:$LISTEN_PORT;
    server_name $DOMAIN;

    root /opt/element/web;
    index index.html;

    location ~ ^(/_matrix|/_synapse/client) {
        proxy_pass http://127.0.0.1:8008;
        proxy_set_header X-Forwarded-For \$remote_addr;
        proxy_set_header X-Forwarded-Proto \$scheme;
        proxy_set_header Host \$host;
        client_max_body_size 100M;
        proxy_http_version 1.1;
    }

    location /_matrix/federation {
        proxy_pass http://127.0.0.1:8008;
        proxy_set_header X-Forwarded-For \$remote_addr;
        proxy_set_header X-Forwarded-Proto \$scheme;
        proxy_set_header Host \$host;
        client_max_body_size 100M;
    }

    location /.well-known/matrix/server {
        default_type application/json;
        return 200 '{"m.server": "$DOMAIN:443"}';
    }

    location /.well-known/matrix/client {
        default_type application/json;
        add_header Access-Control-Allow-Origin *;
        return 200 '{"m.homeserver": {"base_url": "https://$DOMAIN"}}';
    }

    location / {
        try_files \$uri \$uri/ /index.html;
    }
}
NGINX

ln -sf /etc/nginx/sites-available/matrix /etc/nginx/sites-enabled/matrix
rm -f /etc/nginx/sites-enabled/default
nginx -t

# Create systemd service
cat > /etc/systemd/system/synapse.service << SERVICE
[Unit]
Description=Synapse Matrix Homeserver
After=network.target postgresql.service

[Service]
Type=notify
User=synapse
Group=synapse
WorkingDirectory=/opt/synapse
ExecStart=/opt/synapse/venv/bin/python -m synapse.app.homeserver --config-path=/opt/synapse/homeserver.yaml
ExecReload=/bin/kill -HUP \$MAINPID
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
SERVICE

# Start services
echo "[10/10] Starting services..."
systemctl daemon-reload
systemctl enable --now postgresql nginx coturn synapse

# Create admin user
sleep 3
ADMIN_PASS="REDACTED_PASSWORD" rand -hex 12)
cd /opt/synapse
sudo -u synapse /opt/synapse/venv/bin/register_new_matrix_user \
    -c homeserver.yaml \
    -u "$ADMIN_USER" \
    -p "$ADMIN_PASS" \
    -a \
    http://localhost:8008

# Save secrets
cat > /root/.matrix_secrets << SECRETS
DOMAIN=$DOMAIN
DB_PASS="REDACTED_PASSWORD"
TURN_SECRET=$TURN_SECRET
ADMIN_USER=$ADMIN_USER
ADMIN_PASS="REDACTED_PASSWORD"
SECRETS
chmod 600 /root/.matrix_secrets

# Download helper scripts
echo "Downloading helper scripts..."
REPO_BASE="https://git.vish.gg/Vish/matrix-element/raw/branch/main"
mkdir -p /opt/matrix-scripts
for script in verify-matrix.sh fix-matrix.sh backup-matrix.sh update-matrix.sh; do
    curl -sSL "$REPO_BASE/$script" -o "/opt/matrix-scripts/$script" 2>/dev/null || true
    chmod +x "/opt/matrix-scripts/$script" 2>/dev/null || true
done
echo "Helper scripts installed to /opt/matrix-scripts/"

# Verify installation
echo ""
echo "Verifying installation..."
sleep 2

VERIFY_FAILED=0

# Check services
for svc in synapse nginx coturn postgresql; do
    if systemctl is-active --quiet $svc; then
        echo "✓ $svc is running"
    else
        echo "✗ $svc is NOT running"
        VERIFY_FAILED=1
    fi
done

# Check Matrix API
if curl -sf http://localhost:8008/_matrix/client/versions > /dev/null; then
    echo "✓ Matrix API responding"
else
    echo "✗ Matrix API not responding"
    VERIFY_FAILED=1
fi

# Check Element Web
if curl -sf http://localhost:$LISTEN_PORT/ > /dev/null; then
    echo "✓ Element Web accessible"
else
    echo "✗ Element Web not accessible"
    VERIFY_FAILED=1
fi

echo ""
echo "=========================================="
if [ $VERIFY_FAILED -eq 0 ]; then
    echo "✅ Matrix Installation Complete!"
else
    echo "⚠️  Installation complete with warnings"
fi
echo "=========================================="
echo ""
echo "Domain: $DOMAIN"
echo "Admin User: @$ADMIN_USER:$DOMAIN"
echo "Admin Password: "REDACTED_PASSWORD"
echo ""
echo "Listening on port $LISTEN_PORT (HTTP)"
echo ""
echo "Next steps:"
echo "1. Configure reverse proxy: HTTPS:443 → HTTP:$LISTEN_PORT"
echo "2. Forward TURN ports: $TURN_PORT, $TURN_TLS_PORT, $TURN_MIN_PORT-$TURN_MAX_PORT"
echo "3. Login at https://$DOMAIN and change password"
echo ""
echo "Secrets saved to /root/.matrix_secrets"
echo ""
echo "Helper scripts installed to /opt/matrix-scripts/"
echo "  ./verify-matrix.sh  - Check installation health"
echo "  ./fix-matrix.sh     - Diagnose and fix issues"
echo "  ./backup-matrix.sh  - Create full backup"
echo "  ./update-matrix.sh  - Update Synapse and Element"
echo ""
echo "Useful commands:"
echo "  systemctl status synapse nginx coturn"
echo "  journalctl -u synapse -f"
echo "  curl http://localhost:8008/_matrix/client/versions"
