#!/bin/env bash

set -e
ubuntu_version=$(lsb_release -a 2>/dev/null | grep -v "No LSB modules are available." | grep "Description:" | awk -F "Description:\t" '{print $2}')

install_formbricks() {
  # Friendly welcome
  echo "🧱 Welcome to the Formbricks Setup Script"
  echo ""
  echo "🛸 Fasten your seatbelts! We're setting up your Formbricks environment on your $ubuntu_version server."
  echo ""

  # Remove any old Docker installations, without stopping the script if they're not found
  echo "🧹 Time to sweep away any old Docker installations."
  sudo apt-get remove docker docker-engine docker.io containerd runc >/dev/null 2>&1 || true

  # Update package list
  echo "🔄 Updating your package list."
  sudo apt-get update >/dev/null 2>&1

  # Install dependencies
  echo "📦 Installing the necessary dependencies."
  sudo apt-get install -y \
    ca-certificates \
    curl \
    gnupg \
    lsb-release >/dev/null 2>&1

  # Set up Docker's official GPG key & stable repository
  echo "🔑 Adding Docker's official GPG key and setting up the stable repository."
  sudo mkdir -m 0755 -p /etc/apt/keyrings >/dev/null 2>&1
  curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg >/dev/null 2>&1
  echo \
    "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list >/dev/null 2>&1

  # Update package list again
  echo "🔄 Updating your package list again."
  sudo apt-get update >/dev/null 2>&1

  # Install Docker
  echo "🐳 Installing Docker."
  sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin >/dev/null 2>&1

  # Test Docker installation
  echo "🚀 Testing your Docker installation."
  if docker --version >/dev/null 2>&1; then
    echo "🎉 Docker is installed!"
  else
    echo "❌ Docker is not installed. Please install Docker before proceeding."
    exit 1
  fi

  # Adding your user to the Docker group
  echo "🐳 Adding your user to the Docker group to avoid using sudo with docker commands."
  sudo groupadd docker >/dev/null 2>&1 || true
  sudo usermod -aG docker $USER >/dev/null 2>&1

  echo "🎉 Hooray! Docker is all set and ready to go. You're now ready to run your Formbricks instance!"

  mkdir -p formbricks && cd formbricks
  echo "📁 Created Formbricks Quickstart directory at ./formbricks."

  # Ask the user for their domain name (recommend surveys subdomain)
  echo "🔗 Please enter your app domain (e.g., surveys.example.com). 🚨 Do NOT enter the protocol (http/https):"
  read domain_name

  echo "🔗 Do you want us to set up an HTTPS certificate for you? [Y/n]"
  read https_setup
  https_setup=$(echo "$https_setup" | tr '[:upper:]' '[:lower:]')

  # Set default value for HTTPS setup
  if [[ -z $https_setup ]]; then
    https_setup="y"
  fi

  if [[ $https_setup == "y" ]]; then
    echo "🔗 Please make sure that the domain points to the server's IP address and that ports 80 & 443 are open in your server's firewall. Is everything set up? [Y/n]"
    read dns_setup
    dns_setup=$(echo "$dns_setup" | tr '[:upper:]' '[:lower:]')

    # Set default value for DNS setup
    if [[ -z $dns_setup ]]; then
      dns_setup="y"
    fi

    if [[ $dns_setup == "y" ]]; then
      echo "💡 Please enter your email address for the SSL certificate:"
      read email_address

      echo "🔗 Do you want to enforce HTTPS (HSTS)? [Y/n]"
      read hsts_enabled
      hsts_enabled=$(echo "$hsts_enabled" | tr '[:upper:]' '[:lower:]')

      #  Set default value for HSTS
      if [[ -z $hsts_enabled ]]; then
        hsts_enabled="y"
      fi

    else
      echo "❌ Ports 80 & 443 are not open. We can't help you in providing the SSL certificate."
      https_setup="n"
      hsts_enabled="n"
    fi
  else
    https_setup="n"
    hsts_enabled="n"
  fi

  # Ask for HSTS configuration for HTTPS redirection if custom certificate is used
  if [[ $https_setup == "n" ]]; then
    echo "You have chosen not to set up HTTPS certificate for your domain. Please make sure to set up HTTPS on your own. You can refer to the Formbricks documentation(https://formbricks.com/docs/self-hosting/custom-ssl) for more information."

    echo "🔗 Do you want to enforce HTTPS (HSTS)? [Y/n]"
    read hsts_enabled
    hsts_enabled=$(echo "$hsts_enabled" | tr '[:upper:]' '[:lower:]')

    #  Set default value for HSTS
    if [[ -z $hsts_enabled ]]; then
      hsts_enabled="y"
    fi
  fi

  # Installing Traefik
  echo "🚗 Configuring Traefik..."

  if [[ $hsts_enabled == "y" ]]; then
    hsts_middlewares="middlewares:
        - hstsHeader"
    http_redirection="http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
          permanent: true"
  else
    hsts_middlewares=""
    http_redirection=""
  fi

  if [[ $https_setup == "y" ]]; then
    certResolver="certResolver: default"
    certificates_resolvers="certificatesResolvers:
  default:
    acme:
      email: $email_address
      storage: acme.json
      caServer: "https://acme-v02.api.letsencrypt.org/directory"
      tlsChallenge: {}"
  else
    certResolver=""
    certificates_resolvers=""
  fi

  cat <<EOT >traefik.yaml
entryPoints:
  web:
    address: ":80"
    $http_redirection
    transport:
      respondingTimeouts:
        readTimeout: 60s
  websecure:
    address: ":443"
    transport:
      respondingTimeouts:
        readTimeout: 60s
    http:
      tls:
        $certResolver
        options: default
      $hsts_middlewares
providers:
  docker:
    watch: true
    exposedByDefault: false
  file:
    directory: /
$certificates_resolvers
EOT

  cat <<EOT >traefik-dynamic.yaml
# configuring min TLS version
tls:
  options:
    default:
      minVersion: VersionTLS12
      cipherSuites:
        # TLS 1.2 strong ciphers
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
        - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
        - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
        - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
        # TLS 1.3 ciphers are not configurable in Traefik; they are enabled by default
      curvePreferences:
        - CurveP521
        - CurveP384
      sniStrict: true
      alpnProtocols:
        - h2
        - http/1.1
        - acme-tls/1
EOT

  echo "💡 Created traefik.yaml and traefik-dynamic.yaml file."

  if [[ $https_setup == "y" ]]; then
    touch acme.json
    chmod 600 acme.json
    echo "💡 Created acme.json file with correct permissions."
  fi

  # Prompt for email service setup
  read -p "📧 Do you want to set up the email service? You will need SMTP credentials for the same! [y/N]" email_service
  email_service=$(echo "$email_service" | tr '[:upper:]' '[:lower:]')

  # Set default value for email service setup
  if [[ -z $email_service ]]; then
    email_service="n"
  fi

  if [[ $email_service == "y" ]]; then
    echo "Please provide the following email service details: "

    echo -n "Enter your SMTP configured Email ID: "
    read mail_from

    echo -n "Enter your SMTP configured Email Name: "
    read mail_from_name

    echo -n "Enter your SMTP Host URL: "
    read smtp_host

    echo -n "Enter your SMTP Host Port: "
    read smtp_port

    echo -n "Enter your SMTP username: "
    read smtp_user

    read -s -p "Enter your SMTP password: " smtp_password; echo "***"

    echo -n "Enable Authenticated SMTP? Enter 1 for yes and 0 for no(default is 1): "
    read smtp_authenticated

    echo -n "Enable Secure SMTP (use SSL)? Enter 1 for yes and 0 for no: "
    read smtp_secure_enabled

  else
    mail_from=""
    mail_from_name=""
    smtp_host=""
    smtp_port=""
    smtp_user=""
    smtp_password=""
    smtp_authenticated=1
    smtp_secure_enabled=0
  fi

  # Prompt for file upload setup
  echo ""
  echo "📁 Do you want to configure file uploads?"
  echo "   If you skip this, the following features will be disabled:"
  echo "   - Adding images to surveys (e.g., in questions or as background)"
  echo "   - 'File Upload' and 'Picture Selection' question types"
  echo "   - Project logos"
  echo "   - Custom organization logo in emails"
  read -p "Configure file uploads now? [Y/n] " configure_uploads
  configure_uploads=$(echo "$configure_uploads" | tr '[:upper:]' '[:lower:]')
  if [[ -z $configure_uploads ]]; then configure_uploads="y"; fi

  if [[ $configure_uploads == "y" ]]; then
    # Storage choice: External S3 vs bundled MinIO
    read -p "🗄️  Do you want to use an external S3-compatible storage (AWS S3/DO Spaces/etc.)? [y/N] " use_external_s3
    use_external_s3=$(echo "$use_external_s3" | tr '[:upper:]' '[:lower:]')
    if [[ -z $use_external_s3 ]]; then use_external_s3="n"; fi

    if [[ $use_external_s3 == "y" ]]; then
      echo "🔧 Enter S3 configuration (leave Endpoint empty for AWS S3):"
      read -p "   S3 Access Key: " ext_s3_access_key
      read -s -p "   S3 Secret Key: " ext_s3_secret_key; echo "***"
      read -p "   S3 Region (e.g., us-east-1): " ext_s3_region
      read -p "   S3 Bucket Name: " ext_s3_bucket
      read -p "   S3 Endpoint URL (leave empty if you are using AWS S3, otherwise please enter the endpoint URL of the third party S3 compatible storage service): " ext_s3_endpoint
      
      minio_storage="n"
    else
      minio_storage="y"
      default_files_domain="files.$domain_name"
      read -p "🔗 Enter the files subdomain for object storage (e.g., $default_files_domain): " files_domain
      if [[ -z $files_domain ]]; then files_domain="$default_files_domain"; fi

      echo "🔑 Generating MinIO credentials..."
      minio_root_user="formbricks-$(openssl rand -hex 4)"
      minio_root_password=$(openssl rand -base64 20)
      minio_service_user="formbricks-service-$(openssl rand -hex 4)"
      minio_service_password=$(openssl rand -base64 20)
      minio_bucket_name="formbricks-uploads"
      minio_policy_name="formbricks-policy"
      
      echo "✅ MinIO will be configured with:"
      echo "   S3 Access Key (least privilege): $minio_service_user"
      echo "   Bucket: $minio_bucket_name"
    fi
  else
    minio_storage="n"
    use_external_s3="n"
    echo "⚠️ File uploads are disabled. Proceeding without S3/MinIO configuration."
  fi

  echo "📥 Downloading docker-compose.yml from Formbricks GitHub repository..."
  curl -fsSL -o docker-compose.yml https://raw.githubusercontent.com/formbricks/formbricks/stable/docker/docker-compose.yml

  echo "🚙 Updating docker-compose.yml with your custom inputs..."
  sed -i "/WEBAPP_URL:/s|WEBAPP_URL:.*|WEBAPP_URL: \"https://$domain_name\"|" docker-compose.yml
  sed -i "/NEXTAUTH_URL:/s|NEXTAUTH_URL:.*|NEXTAUTH_URL: \"https://$domain_name\"|" docker-compose.yml

  nextauth_secret=$(openssl rand -hex 32) && sed -i "/NEXTAUTH_SECRET:$/s/NEXTAUTH_SECRET:.*/NEXTAUTH_SECRET: $nextauth_secret/" docker-compose.yml
  echo "🚗 NEXTAUTH_SECRET updated successfully!"

  encryption_key=$(openssl rand -hex 32) && sed -i "/ENCRYPTION_KEY:$/s/ENCRYPTION_KEY:.*/ENCRYPTION_KEY: $encryption_key/" docker-compose.yml
  echo "🚗 ENCRYPTION_KEY updated successfully!"

  cron_secret=$(openssl rand -hex 32) && sed -i "/CRON_SECRET:$/s/CRON_SECRET:.*/CRON_SECRET: $cron_secret/" docker-compose.yml	
  echo "🚗 CRON_SECRET updated successfully!"
  
  if [[ -n $mail_from ]]; then
    sed -i "s|# MAIL_FROM:|MAIL_FROM: \"$mail_from\"|" docker-compose.yml
    sed -i "s|# MAIL_FROM_NAME:|MAIL_FROM_NAME: \"$mail_from_name\"|" docker-compose.yml
    sed -i "s|# SMTP_HOST:|SMTP_HOST: \"$smtp_host\"|" docker-compose.yml
    sed -i "s|# SMTP_PORT:|SMTP_PORT: \"$smtp_port\"|" docker-compose.yml
    sed -i "s|# SMTP_SECURE_ENABLED:|SMTP_SECURE_ENABLED: $smtp_secure_enabled|" docker-compose.yml
    sed -i "s|# SMTP_USER:|SMTP_USER: \"$smtp_user\"|" docker-compose.yml
    sed -i "s|# SMTP_PASSWORD:|SMTP_PASSWORD: \"$smtp_password\"|" docker-compose.yml
    sed -i "s|# SMTP_AUTHENTICATED:|SMTP_AUTHENTICATED: $smtp_authenticated|" docker-compose.yml
  fi

  if [[ $use_external_s3 == "y" ]]; then
    echo "🚗 Configuring external S3..."
    sed -i "s|# S3_ACCESS_KEY:|S3_ACCESS_KEY: \"$ext_s3_access_key\"|" docker-compose.yml
    sed -i "s|# S3_SECRET_KEY:|S3_SECRET_KEY: \"$ext_s3_secret_key\"|" docker-compose.yml
    sed -i "s|# S3_REGION:|S3_REGION: \"$ext_s3_region\"|" docker-compose.yml
    sed -i "s|# S3_BUCKET_NAME:|S3_BUCKET_NAME: \"$ext_s3_bucket\"|" docker-compose.yml
    if [[ -n $ext_s3_endpoint ]]; then
      sed -i "s|# S3_ENDPOINT_URL:|S3_ENDPOINT_URL: \"$ext_s3_endpoint\"|" docker-compose.yml
      # Ensure S3_FORCE_PATH_STYLE is enabled for S3-compatible endpoints
      sed -E -i 's|^([[:space:]]*)#?[[:space:]]*S3_FORCE_PATH_STYLE:[[:space:]]*.*$|\1S3_FORCE_PATH_STYLE: 1|' docker-compose.yml
    else
      # Comment out S3_FORCE_PATH_STYLE for native AWS S3
      sed -E -i 's|^([[:space:]]*)#?[[:space:]]*S3_FORCE_PATH_STYLE:[[:space:]]*.*$|\1# S3_FORCE_PATH_STYLE:|' docker-compose.yml
    fi
    echo "🚗 External S3 configuration updated successfully!"
  elif [[ $minio_storage == "y" ]]; then
    echo "🚗 Configuring bundled MinIO..."
    sed -i "s|# S3_ACCESS_KEY:|S3_ACCESS_KEY: \"$minio_service_user\"|" docker-compose.yml
    sed -i "s|# S3_SECRET_KEY:|S3_SECRET_KEY: \"$minio_service_password\"|" docker-compose.yml
    sed -i "s|# S3_REGION:|S3_REGION: \"us-east-1\"|" docker-compose.yml
    sed -i "s|# S3_BUCKET_NAME:|S3_BUCKET_NAME: \"$minio_bucket_name\"|" docker-compose.yml
    if [[ $https_setup == "y" ]]; then
      sed -i "s|# S3_ENDPOINT_URL:|S3_ENDPOINT_URL: \"https://$files_domain\"|" docker-compose.yml
    else
      sed -i "s|# S3_ENDPOINT_URL:|S3_ENDPOINT_URL: \"http://$files_domain\"|" docker-compose.yml
    fi
    # Ensure S3_FORCE_PATH_STYLE is enabled for MinIO
    sed -E -i 's|^([[:space:]]*)#?[[:space:]]*S3_FORCE_PATH_STYLE:[[:space:]]*.*$|\1S3_FORCE_PATH_STYLE: 1|' docker-compose.yml
    echo "🚗 MinIO S3 configuration updated successfully!"
  fi

  # SUPER SIMPLE: Use multiple simple operations instead of complex AWK

  # Step 1: Add Traefik labels to formbricks service
  awk -v domain_name="$domain_name" -v hsts_enabled="$hsts_enabled" '
/formbricks:/,/^ *$/ {
    if ($0 ~ /<<: \*environment$/) {
        print "    labels:"
        print "      - \"traefik.enable=true\""
        print "      - \"traefik.http.routers.formbricks.rule=Host(`" domain_name "`)\""
        print "      - \"traefik.http.routers.formbricks.entrypoints=websecure\""
        print "      - \"traefik.http.routers.formbricks.tls=true\""
        print "      - \"traefik.http.routers.formbricks.tls.certresolver=default\""
        print "      - \"traefik.http.services.formbricks.loadbalancer.server.port=3000\""
        if (hsts_enabled == "y") {
            print "      - \"traefik.http.middlewares.hstsHeader.headers.stsSeconds=31536000\""
            print "      - \"traefik.http.middlewares.hstsHeader.headers.forceSTSHeader=true\""
            print "      - \"traefik.http.middlewares.hstsHeader.headers.stsPreload=true\""
            print "      - \"traefik.http.middlewares.hstsHeader.headers.stsIncludeSubdomains=true\""
        } else {
            print "      - \"traefik.http.routers.formbricks_http.entrypoints=web\""
            print "      - \"traefik.http.routers.formbricks_http.rule=Host(`" domain_name "`)\""
        }
        print $0
    } else {
        print $0
    }
    next
}
{ print }
' docker-compose.yml >tmp.yml && mv tmp.yml docker-compose.yml

  # Step 2: Ensure formbricks waits for minio-init to complete successfully (mapping depends_on)
  if [[ $minio_storage == "y" ]]; then
    # Remove any existing simple depends_on list and replace with mapping
    awk '
      BEGIN{in_fb=0; removing=0}
      /^  formbricks:/ {in_fb=1}
      in_fb && /^    depends_on:/ {removing=1; next}
      in_fb && removing && /^    [A-Za-z0-9_-]+:/ {removing=0}
      /^  [A-Za-z0-9_-]+:/ && !/^  formbricks:/ {in_fb=0}
      { if(!removing) print }
    ' docker-compose.yml > tmp.yml && mv tmp.yml docker-compose.yml

    awk '
      BEGIN{in_fb=0; inserted=0}
      /^  formbricks:/ {in_fb=1}
      /^  [A-Za-z0-9_-]+:/ && !/^  formbricks:/ {in_fb=0}
      {
        print
        if (in_fb && !inserted && $0 ~ /^    image:/) {
          print "    depends_on:"
          print "      postgres:"
          print "        condition: service_started"
          print "      minio-init:"
          print "        condition: service_completed_successfully"
          inserted=1
        }
      }
    ' docker-compose.yml > tmp.yml && mv tmp.yml docker-compose.yml
  fi

  # Step 3: Build service snippets and inject them BEFORE the volumes section (non-destructive: skip if service exists)
  services_snippet_file="services_snippet.yml"
  : > "$services_snippet_file"

  insert_traefik="y"
  if grep -q "^  traefik:" docker-compose.yml; then insert_traefik="n"; fi

  if [[ $minio_storage == "y" ]]; then
    insert_minio="y"; insert_minio_init="y"
    if grep -q "^  minio:" docker-compose.yml; then insert_minio="n"; fi
    if grep -q "^  minio-init:" docker-compose.yml; then insert_minio_init="n"; fi

    if [[ $insert_minio == "y" ]]; then
      cat >> "$services_snippet_file" << EOF

  minio:
    restart: always
    image: minio/minio@sha256:13582eff79c6605a2d315bdd0e70164142ea7e98fc8411e9e10d089502a6d883
    command: server /data
    environment:
      MINIO_ROOT_USER: "$minio_root_user"
      MINIO_ROOT_PASSWORD: "$minio_root_password"
    volumes:
      - minio-data:/data
    labels:
      - "traefik.enable=true"
      # S3 API on files subdomain
      - "traefik.http.routers.minio-s3.rule=Host(\`$files_domain\`)"
      - "traefik.http.routers.minio-s3.entrypoints=websecure"
      - "traefik.http.routers.minio-s3.tls=true"
      - "traefik.http.routers.minio-s3.tls.certresolver=default"
      - "traefik.http.routers.minio-s3.service=minio-s3"
      - "traefik.http.services.minio-s3.loadbalancer.server.port=9000"
      # CORS and rate limit (adjust origins if needed)
      - "traefik.http.routers.minio-s3.middlewares=minio-cors,minio-ratelimit"
      - "traefik.http.middlewares.minio-cors.headers.accesscontrolallowmethods=GET,PUT,POST,DELETE,HEAD,OPTIONS"
      - "traefik.http.middlewares.minio-cors.headers.accesscontrolallowheaders=*"
      - "traefik.http.middlewares.minio-cors.headers.accesscontrolalloworiginlist=https://$domain_name"
      - "traefik.http.middlewares.minio-cors.headers.accesscontrolmaxage=100"
      - "traefik.http.middlewares.minio-cors.headers.addvaryheader=true"
      - "traefik.http.middlewares.minio-ratelimit.ratelimit.average=100"
      - "traefik.http.middlewares.minio-ratelimit.ratelimit.burst=200"
EOF
    fi

    if [[ $insert_minio_init == "y" ]]; then
      cat >> "$services_snippet_file" << EOF
  minio-init:
    image: minio/mc@sha256:95b5f3f7969a5c5a9f3a700ba72d5c84172819e13385aaf916e237cf111ab868
    depends_on:
      - minio
    environment:
      MINIO_ROOT_USER: "$minio_root_user"
      MINIO_ROOT_PASSWORD: "$minio_root_password"
      MINIO_SERVICE_USER: "$minio_service_user"
      MINIO_SERVICE_PASSWORD: "$minio_service_password"
      MINIO_BUCKET_NAME: "$minio_bucket_name"
    entrypoint: ["/bin/sh", "/tmp/minio-init.sh"]
    volumes:
      - ./minio-init.sh:/tmp/minio-init.sh:ro
EOF
    fi

    if [[ $insert_traefik == "y" ]]; then
      cat >> "$services_snippet_file" << EOF
  traefik:
    image: "traefik:v2.11.31"
    restart: always
    container_name: "traefik"
    depends_on:
      - formbricks
      - minio
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./traefik.yaml:/traefik.yaml
      - ./traefik-dynamic.yaml:/traefik-dynamic.yaml
      - ./acme.json:/acme.json
      - /var/run/docker.sock:/var/run/docker.sock:ro
EOF
    fi

    # Downgrade MinIO router to plain HTTP when HTTPS is not configured
    if [[ $https_setup != "y" ]]; then
      sed -i 's/traefik.http.routers.minio-s3.entrypoints=websecure/traefik.http.routers.minio-s3.entrypoints=web/' "$services_snippet_file"
      sed -i '/traefik.http.routers.minio-s3.tls=true/d' "$services_snippet_file"
      sed -i '/traefik.http.routers.minio-s3.tls.certresolver=default/d' "$services_snippet_file"
      sed -i "s|accesscontrolalloworiginlist=https://$domain_name|accesscontrolalloworiginlist=http://$domain_name|" "$services_snippet_file"
    fi
  else
    if [[ $insert_traefik == "y" ]]; then
      cat > "$services_snippet_file" << EOF

  traefik:
    image: "traefik:v2.11.31"
    restart: always
    container_name: "traefik"
    depends_on:
      - formbricks
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./traefik.yaml:/traefik.yaml
      - ./traefik-dynamic.yaml:/traefik-dynamic.yaml
      - ./acme.json:/acme.json
      - /var/run/docker.sock:/var/run/docker.sock:ro
EOF
    else
      : > "$services_snippet_file"
    fi
  fi

  awk '
  {
    print
    if ($0 ~ /^services:$/ && !inserted) {
      while ((getline line < "services_snippet.yml") > 0) print line
      close("services_snippet.yml")
      inserted = 1
    }
  }
  ' docker-compose.yml > tmp.yml && mv tmp.yml docker-compose.yml

  rm -f "$services_snippet_file"

  # Ensure required volumes exist without removing user-defined volumes
  if grep -q '^volumes:' docker-compose.yml; then
    # Ensure postgres
    if ! awk '/^volumes:/{invol=1; next} invol && (/^[^[:space:]]/ || NF==0){invol=0} invol{ if($1=="postgres:") found=1 } END{ exit(found?0:1) }' docker-compose.yml; then
      awk '
        /^volumes:/ { print; invol=1; next }
        invol && /^[^[:space:]]/ { if(!added){ print "  postgres:"; print "    driver: local"; added=1 } ; invol=0 }
        { print }
        END { if (invol && !added) { print "  postgres:"; print "    driver: local" } }
      ' docker-compose.yml > tmp.yml && mv tmp.yml docker-compose.yml
    fi
    # Ensure redis
    if ! awk '/^volumes:/{invol=1; next} invol && (/^[^[:space:]]/ || NF==0){invol=0} invol{ if($1=="redis:") found=1 } END{ exit(found?0:1) }' docker-compose.yml; then
      awk '
        /^volumes:/ { print; invol=1; next }
        invol && /^[^[:space:]]/ { if(!added){ print "  redis:"; print "    driver: local"; added=1 } ; invol=0 }
        { print }
        END { if (invol && !added) { print "  redis:"; print "    driver: local" } }
      ' docker-compose.yml > tmp.yml && mv tmp.yml docker-compose.yml
    fi
    # Ensure minio-data if needed
    if [[ $minio_storage == "y" ]]; then
      if ! awk '/^volumes:/{invol=1; next} invol && (/^[^[:space:]]/ || NF==0){invol=0} invol{ if($1=="minio-data:") found=1 } END{ exit(found?0:1) }' docker-compose.yml; then
        awk '
          /^volumes:/ { print; invol=1; next }
          invol && /^[^[:space:]]/ { if(!added){ print "  minio-data:"; print "    driver: local"; added=1 } ; invol=0 }
          { print }
          END { if (invol && !added) { print "  minio-data:"; print "    driver: local" } }
        ' docker-compose.yml > tmp.yml && mv tmp.yml docker-compose.yml
      fi
    fi
  else
    {
      echo ""
      echo "volumes:"
      echo "  postgres:"
      echo "    driver: local"
      echo "  redis:"
      echo "    driver: local"
      if [[ $minio_storage == "y" ]]; then
        echo "  minio-data:"
        echo "    driver: local"
      fi
    } >> docker-compose.yml
  fi

  # Create minio-init script outside heredoc to avoid variable expansion issues
  if [[ $minio_storage == "y" ]]; then
    cat > minio-init.sh << 'MINIO_SCRIPT_EOF'
#!/bin/sh
echo '⏳ Waiting for MinIO to be ready...'
attempts=0
max_attempts=30
until mc alias set minio http://minio:9000 "$MINIO_ROOT_USER" "$MINIO_ROOT_PASSWORD" >/dev/null 2>&1 \
  && mc ls minio >/dev/null 2>&1; do
  attempts=$((attempts + 1))
  if [ $attempts -ge $max_attempts ]; then
    printf '❌ Failed to connect to MinIO after %s attempts\n' $max_attempts
    exit 1
  fi
  printf '...still waiting attempt %s/%s\n' $attempts $max_attempts
  sleep 2
done
echo '🔗 MinIO reachable; alias configured.'

echo '🪣 Creating bucket (idempotent)...';
mc mb minio/$MINIO_BUCKET_NAME --ignore-existing;

echo '📄 Creating JSON policy file...';
cat > /tmp/formbricks-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:DeleteObject", "s3:GetObject", "s3:PutObject"],
      "Resource": ["arn:aws:s3:::$MINIO_BUCKET_NAME/*"]
    },
    {
      "Effect": "Allow",
      "Action": ["s3:ListBucket"],
      "Resource": ["arn:aws:s3:::$MINIO_BUCKET_NAME"]
    }
  ]
}
EOF

echo '🔒 Creating policy (idempotent)...';
if ! mc admin policy info minio formbricks-policy >/dev/null 2>&1; then
  mc admin policy create minio formbricks-policy /tmp/formbricks-policy.json || mc admin policy add minio formbricks-policy /tmp/formbricks-policy.json;
  echo 'Policy created successfully.';
else
  echo 'Policy already exists, skipping creation.';
fi

echo '👤 Creating service user (idempotent)...';
if ! mc admin user info minio "$MINIO_SERVICE_USER" >/dev/null 2>&1; then
  mc admin user add minio "$MINIO_SERVICE_USER" "$MINIO_SERVICE_PASSWORD";
  echo 'User created successfully.';
else
  echo 'User already exists, skipping creation.';
fi

echo '🔗 Attaching policy to user (idempotent)...';
mc admin policy attach minio formbricks-policy --user "$MINIO_SERVICE_USER" || echo 'Policy already attached or attachment failed (non-fatal).';

echo '✅ MinIO setup complete!';
exit 0;
MINIO_SCRIPT_EOF
    chmod +x minio-init.sh
  fi

  newgrp docker <<END

docker compose up -d

echo "🔗 To edit more variables and deeper config, go to the formbricks/docker-compose.yml, edit the file, and restart the container!"

echo "🚨 Make sure you have set up the DNS records as well as inbound rules for the domain name and IP address of this instance."
echo ""

if [[ $minio_storage == "y" ]]; then
    echo "🗄️  MinIO Storage Setup Complete:"
    echo "   • Access Key: $minio_service_user (least privilege)"
    echo "   • Bucket: $minio_bucket_name (✅ created and secured)"
    echo ""
fi

echo "🎉 All done! Please setup your Formbricks instance by visiting your domain at https://$domain_name. You can check the status of Formbricks & Traefik with 'cd formbricks && sudo docker compose ps.'"

END

}

uninstall_formbricks() {
  echo "🗑️ Preparing to Uninstalling Formbricks..."
  read -p "Are you sure you want to uninstall Formbricks? This will delete all the data associated with it! (yes/no): " uninstall_confirmation
  uninstall_confirmation=$(echo "$uninstall_confirmation" | tr '[:upper:]' '[:lower:]')
  if [[ $uninstall_confirmation == "yes" ]]; then
    cd formbricks
    sudo docker compose down
    cd ..
    sudo rm -rf formbricks
    echo "🛑 Formbricks uninstalled successfully!"
  else
    echo "❌ Uninstalling Formbricks has been cancelled."
  fi
}

stop_formbricks() {
  echo "🛑 Stopping Formbricks..."
  cd formbricks
  sudo docker compose down
  echo "🎉 Formbricks instance stopped successfully!"
}

update_formbricks() {
  echo "🔄 Updating Formbricks..."
  cd formbricks
  sudo docker compose pull
  sudo docker compose down
  sudo docker compose up -d
  echo "🎉 Formbricks updated successfully!"
  echo "🎉 Check the status of Formbricks & Traefik with 'cd formbricks && sudo docker compose logs.'"
}

restart_formbricks() {
  echo "🔄 Restarting Formbricks..."
  cd formbricks
  sudo docker compose restart
  echo "🎉 Formbricks restarted successfully!"
}

get_logs() {
  echo "📃 Getting Formbricks logs..."
  cd formbricks
  sudo docker compose logs
}

cleanup_minio_init() {
  echo "🧹 Cleaning up MinIO init service and references..."
  cd formbricks

  # Remove minio-init service block from docker-compose.yml
  awk '
    BEGIN{skip=0}
    /^services:[[:space:]]*$/ { print; next }
    /^  minio-init:/          { skip=1; next }
    /^  [A-Za-z0-9_-]+:/      { if (skip) skip=0 }
    { if (!skip) print }
  ' docker-compose.yml > tmp.yml && mv tmp.yml docker-compose.yml

  # Remove list-style "- minio-init" lines under depends_on (if any)
  if sed --version >/dev/null 2>&1; then
    sed -E -i '/^[[:space:]]*-[[:space:]]*minio-init[[:space:]]*$/d' docker-compose.yml
  else
    sed -E -i '' '/^[[:space:]]*-[[:space:]]*minio-init[[:space:]]*$/d' docker-compose.yml
  fi

  # Remove the minio-init mapping and its condition line (mapping style depends_on)
  if sed --version >/dev/null 2>&1; then
    sed -i '/^[[:space:]]*minio-init:[[:space:]]*$/,/^[[:space:]]*condition:[[:space:]]*service_completed_successfully[[:space:]]*$/d' docker-compose.yml
  else
    sed -i '' '/^[[:space:]]*minio-init:[[:space:]]*$/,/^[[:space:]]*condition:[[:space:]]*service_completed_successfully[[:space:]]*$/d' docker-compose.yml
  fi

  # Remove any stopped minio-init container and restart without orphans
  docker compose rm -f -s minio-init >/dev/null 2>&1 || true
  docker compose up -d --remove-orphans

  echo "✅ MinIO init cleanup complete."
}

case "$1" in
install)
  install_formbricks
  ;;
update)
  update_formbricks
  ;;
stop)
  stop_formbricks
  ;;
restart)
  restart_formbricks
  ;;
logs)
  get_logs
  ;;
  cleanup-minio-init)
    cleanup_minio_init
    ;;
uninstall)
  uninstall_formbricks
  ;;
*)
  echo "🚀 Executing default step of installing Formbricks"
  install_formbricks
  ;;
esac