#!/bin/bash
set -euo pipefail

echo ""
echo "==============================="
echo " LaSuite Meet - Quick Setup"
echo "==============================="
echo ""

# Check dependencies
command -v docker >/dev/null 2>&1 || { echo "Error: Docker is not installed."; exit 1; }
docker compose version >/dev/null 2>&1 || { echo "Error: Docker Compose is not installed."; exit 1; }
command -v openssl >/dev/null 2>&1 || { echo "Error: openssl is not installed."; exit 1; }

# Prompt for reverse proxy choice
echo "Which reverse proxy are you using?"
echo "  1) nginx-proxy + acme-companion (recommended for new deployments)"
echo "  2) Traefik"
echo ""
read -p "Choice [1/2]: " PROXY_CHOICE
if [ "$PROXY_CHOICE" != "1" ] && [ "$PROXY_CHOICE" != "2" ]; then
  echo "Invalid choice. Exiting."
  exit 1
fi

# Prompt for domains
echo ""
read -p "Meet domain    (e.g. meet.example.com):    " MEET_HOST
read -p "Auth domain    (e.g. auth.example.com):    " AUTH_HOST
read -p "LiveKit domain (e.g. livekit.example.com): " LIVEKIT_HOST
read -p "Admin account email (used for Keycloak):  " ADMIN_EMAIL

if [ "$PROXY_CHOICE" = "1" ]; then
  read -p "Email for Let's Encrypt notifications:     " LETSENCRYPT_EMAIL
fi

echo ""
echo "Generating secrets..."

DJANGO_SECRET=$(openssl rand -hex 32)
LIVEKIT_SECRET=$(openssl rand -hex 32)
DB_PASSWORD=$(openssl rand -hex 16)
KC_DB_PASSWORD=$(openssl rand -hex 16)
KC_CLIENT_SECRET=$(openssl rand -hex 16)
KC_ADMIN_PASSWORD=$(openssl rand -hex 16)
BT='`'

# Create project directory
mkdir -p meet && cd meet

# Create the proxy network (if it doesn't already exist)
docker network create proxy 2>/dev/null || true

echo "Downloading configuration files..."
curl -sL -o .env https://meet-doc.bebopo.eu/examples/docker.env
curl -sL -o livekit-server.yaml https://meet-doc.bebopo.eu/examples/livekit-server.yaml
curl -sL -o nginx-routing.conf https://meet-doc.bebopo.eu/examples/routing.conf
curl -sL -o keycloak-realm.json https://meet-doc.bebopo.eu/examples/keycloak-realm.json
curl -sL -o compose.yml https://meet-doc.bebopo.eu/examples/compose.yml

echo "Customizing .env..."
sed -i \
  -e "s|meet\.example\.com|${MEET_HOST}|g" \
  -e "s|auth\.example\.com|${AUTH_HOST}|g" \
  -e "s|livekit\.example\.com|${LIVEKIT_HOST}|g" \
  -e "s|^DJANGO_SECRET_KEY=.*|DJANGO_SECRET_KEY=${DJANGO_SECRET}|" \
  -e "s|^DB_PASSWORD=.*|DB_PASSWORD=${DB_PASSWORD}|" \
  -e "s|^KC_DB_PASSWORD=.*|KC_DB_PASSWORD=${KC_DB_PASSWORD}|" \
  -e "s|^OIDC_RP_CLIENT_SECRET=.*|OIDC_RP_CLIENT_SECRET=${KC_CLIENT_SECRET}|" \
  -e "s|^LIVEKIT_API_SECRET=.*|LIVEKIT_API_SECRET=${LIVEKIT_SECRET}|" \
  .env

echo "Customizing livekit-server.yaml..."
sed -i "s/REPLACE_ME/${LIVEKIT_SECRET}/" livekit-server.yaml

echo "Customizing keycloak-realm.json..."
sed -i "s/REPLACE_ME/${KC_CLIENT_SECRET}/" keycloak-realm.json
sed -i "s/meet\.example\.com/${MEET_HOST}/g" keycloak-realm.json
sed -i "s/admin@example\.com/${ADMIN_EMAIL}/" keycloak-realm.json

echo "Customizing compose.yml..."
sed -i \
  -e "s|KC_BOOTSTRAP_ADMIN_PASSWORD:.*|KC_BOOTSTRAP_ADMIN_PASSWORD: ${KC_ADMIN_PASSWORD}|" \
  -e "s|meet\.example\.com|${MEET_HOST}|g" \
  -e "s|auth\.example\.com|${AUTH_HOST}|g" \
  -e "s|livekit\.example\.com|${LIVEKIT_HOST}|g" \
  compose.yml
if [ -n "$LETSENCRYPT_EMAIL" ]; then
  sed -i "s/you@example\.com/${LETSENCRYPT_EMAIL}/g" compose.yml
fi

echo "Writing compose.yml..."

if [ "$PROXY_CHOICE" = "1" ]; then
# Option 1: nginx-proxy + acme-companion
cat > compose.yml << COMPOSE_EOF
services:

  backend:
    image: lasuite/meet-backend:latest
    restart: unless-stopped
    user: root
    env_file: .env
    healthcheck:
      test: ["CMD", "python", "manage.py", "check"]
      interval: 15s
      timeout: 30s
      retries: 20
      start_period: 10s
    depends_on:
      postgresql:
        condition: service_healthy
      redis:
        condition: service_started
      livekit:
        condition: service_started
    networks: [proxy, internal]

  frontend:
    image: lasuite/meet-frontend:latest
    restart: unless-stopped
    entrypoint: [/docker-entrypoint.sh]
    command: ["nginx", "-g", "daemon off;"]
    env_file: .env
    environment:
      - VIRTUAL_HOST=${MEET_HOST}
      - VIRTUAL_PORT=8083
      - LETSENCRYPT_HOST=${MEET_HOST}
      - LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL}
    volumes:
      - ./nginx-routing.conf:/etc/nginx/conf.d/routing.conf:ro
    depends_on:
      backend:
        condition: service_healthy
    networks: [proxy, internal]

  celery:
    image: lasuite/meet-backend:latest
    restart: unless-stopped
    command: ["celery", "-A", "meet.celery_app", "worker", "-l", "INFO"]
    env_file: .env
    depends_on: [backend]
    networks: [internal]

  postgresql:
    image: postgres:16
    restart: unless-stopped
    environment:
      POSTGRES_DB: meet
      POSTGRES_USER: meet
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -d meet -U meet"]
      interval: 1s
      timeout: 2s
      retries: 300
    volumes: [meet_db:/var/lib/postgresql/data]
    networks: [internal]

  redis:
    image: redis:7
    restart: unless-stopped
    networks: [internal]

  livekit:
    image: livekit/livekit-server:latest
    restart: unless-stopped
    command: --config /config.yaml
    environment:
      - VIRTUAL_HOST=${LIVEKIT_HOST}
      - VIRTUAL_PORT=7880
      - LETSENCRYPT_HOST=${LIVEKIT_HOST}
      - LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL}
    ports:
      - "7881:7881"
      - "7882:7882/udp"
    volumes:
      - ./livekit-server.yaml:/config.yaml:ro
    depends_on: [redis]
    networks: [proxy, internal]

  keycloak:
    image: quay.io/keycloak/keycloak:latest
    restart: unless-stopped
    command:
      - start
      - --import-realm
    environment:
      VIRTUAL_HOST: ${AUTH_HOST}
      VIRTUAL_PORT: "8080"
      LETSENCRYPT_HOST: ${AUTH_HOST}
      LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL}
      KC_BOOTSTRAP_ADMIN_USERNAME: admin
      KC_BOOTSTRAP_ADMIN_PASSWORD: ${KC_ADMIN_PASSWORD}
      KC_DB: postgres
      KC_DB_URL_HOST: kc-postgresql
      KC_DB_URL_DATABASE: keycloak
      KC_DB_PASSWORD: ${KC_DB_PASSWORD}
      KC_DB_USERNAME: keycloak
      KC_HOSTNAME: https://${AUTH_HOST}
      KC_PROXY_HEADERS: xforwarded
      KC_HTTP_ENABLED: "true"
    volumes:
      - ./keycloak-realm.json:/opt/keycloak/data/import/realm.json:ro
    depends_on: [kc-postgresql]
    networks: [proxy, internal]

  kc-postgresql:
    image: postgres:14
    restart: unless-stopped
    environment:
      POSTGRES_DB: keycloak
      POSTGRES_USER: keycloak
      POSTGRES_PASSWORD: ${KC_DB_PASSWORD}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -d keycloak -U keycloak"]
      interval: 1s
      timeout: 2s
      retries: 300
    volumes: [kc_db:/var/lib/postgresql/data]
    networks: [internal]

volumes:
  meet_db:
  kc_db:

networks:
  proxy:
    external: true
  internal:
COMPOSE_EOF

fi

else

# Option 2: Traefik
cat > compose.yml << COMPOSE_EOF
services:

  backend:
    image: lasuite/meet-backend:latest
    restart: unless-stopped
    user: root
    env_file: .env
    healthcheck:
      test: ["CMD", "python", "manage.py", "check"]
      interval: 15s
      timeout: 30s
      retries: 20
      start_period: 10s
    depends_on:
      postgresql:
        condition: service_healthy
      redis:
        condition: service_started
      livekit:
        condition: service_started
    networks: [proxy, internal]

  frontend:
    image: lasuite/meet-frontend:latest
    restart: unless-stopped
    entrypoint: [/docker-entrypoint.sh]
    command: ["nginx", "-g", "daemon off;"]
    env_file: .env
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.meet-frontend.rule=Host(${BT}${MEET_HOST}${BT})"
      - "traefik.http.routers.meet-frontend.entrypoints=websecure"
      - "traefik.http.routers.meet-frontend.tls=true"
      - "traefik.http.routers.meet-frontend.tls.certresolver=letsencrypt"
      - "traefik.http.services.meet-frontend.loadbalancer.server.port=8083"
    volumes:
      - ./nginx-routing.conf:/etc/nginx/conf.d/routing.conf:ro
    depends_on:
      backend:
        condition: service_healthy
    networks: [proxy, internal]

  celery:
    image: lasuite/meet-backend:latest
    restart: unless-stopped
    command: ["celery", "-A", "meet.celery_app", "worker", "-l", "INFO"]
    env_file: .env
    depends_on: [backend]
    networks: [internal]

  postgresql:
    image: postgres:16
    restart: unless-stopped
    environment:
      POSTGRES_DB: meet
      POSTGRES_USER: meet
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -d meet -U meet"]
      interval: 1s
      timeout: 2s
      retries: 300
    volumes: [meet_db:/var/lib/postgresql/data]
    networks: [internal]

  redis:
    image: redis:7
    restart: unless-stopped
    networks: [internal]

  livekit:
    image: livekit/livekit-server:latest
    restart: unless-stopped
    command: --config /config.yaml
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.meet-livekit.rule=Host(${BT}${LIVEKIT_HOST}${BT})"
      - "traefik.http.routers.meet-livekit.entrypoints=websecure"
      - "traefik.http.routers.meet-livekit.tls=true"
      - "traefik.http.routers.meet-livekit.tls.certresolver=letsencrypt"
      - "traefik.http.services.meet-livekit.loadbalancer.server.port=7880"
    ports:
      - "7881:7881"
      - "7882:7882/udp"
    volumes:
      - ./livekit-server.yaml:/config.yaml:ro
    depends_on: [redis]
    networks: [proxy, internal]

  keycloak:
    image: quay.io/keycloak/keycloak:latest
    restart: unless-stopped
    command:
      - start
      - --import-realm
    environment:
      KC_BOOTSTRAP_ADMIN_USERNAME: admin
      KC_BOOTSTRAP_ADMIN_PASSWORD: ${KC_ADMIN_PASSWORD}
      KC_DB: postgres
      KC_DB_URL_HOST: kc-postgresql
      KC_DB_URL_DATABASE: keycloak
      KC_DB_PASSWORD: ${KC_DB_PASSWORD}
      KC_DB_USERNAME: keycloak
      KC_HOSTNAME: https://${AUTH_HOST}
      KC_PROXY_HEADERS: xforwarded
      KC_HTTP_ENABLED: "true"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.meet-keycloak.rule=Host(${BT}${AUTH_HOST}${BT})"
      - "traefik.http.routers.meet-keycloak.entrypoints=websecure"
      - "traefik.http.routers.meet-keycloak.tls=true"
      - "traefik.http.routers.meet-keycloak.tls.certresolver=letsencrypt"
      - "traefik.http.services.meet-keycloak.loadbalancer.server.port=8080"
    volumes:
      - ./keycloak-realm.json:/opt/keycloak/data/import/realm.json:ro
    depends_on: [kc-postgresql]
    networks: [proxy, internal]

  kc-postgresql:
    image: postgres:14
    restart: unless-stopped
    environment:
      POSTGRES_DB: keycloak
      POSTGRES_USER: keycloak
      POSTGRES_PASSWORD: ${KC_DB_PASSWORD}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -d keycloak -U keycloak"]
      interval: 1s
      timeout: 2s
      retries: 300
    volumes: [kc_db:/var/lib/postgresql/data]
    networks: [internal]

volumes:
  meet_db:
  kc_db:

networks:
  proxy:
    external: true
  internal:
COMPOSE_EOF

else

fi

echo ""
echo "Pulling images (this may take a few minutes)..."
docker compose pull

echo "Starting stack..."
docker compose up -d

echo ""
echo "Waiting for backend to become healthy..."
until docker inspect --format='{{.State.Health.Status}}' meet-backend-1 2>/dev/null | grep -q "^healthy$"; do
  printf "."
  sleep 2
done
echo " ready"

echo "Running database migrations..."
docker exec -u root meet-backend-1 python manage.py migrate

echo ""
echo "==============================="
echo " Setup complete!"
echo "==============================="
echo ""
echo " Open:  https://${MEET_HOST}"
echo " Login: meet-admin / ChangeMe!"
echo ""
echo " Next steps: https://meet-doc.bebopo.eu/self-hosting/simple/next-steps/"
echo ""
