#!/bin/bash

cat << "EOF"
  ██████╗██╗  ██╗ █████╗ ███╗   ██╗ ██████╗ ███████╗
 ██╔════╝██║  ██║██╔══██╗████╗  ██║██╔════╝ ██╔════╝
 ██║     ███████║███████║██╔██╗ ██║██║  ███╗█████╗  
 ██║     ██╔══██║██╔══██║██║╚██╗██║██║   ██║██╔══╝  
 ╚██████╗██║  ██║██║  ██║██║ ╚████║╚██████╔╝███████╗
  ╚═════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝  ╚═══╝ ╚═════╝ ╚══════╝
                                                    
 ███╗   ███╗ █████╗ ██╗  ██╗███████╗██████╗ 
 ████╗ ████║██╔══██╗██║ ██╔╝██╔════╝██╔══██╗
 ██╔████╔██║███████║█████╔╝ █████╗  ██████╔╝
 ██║╚██╔╝██║██╔══██║██╔═██╗ ██╔══╝  ██╔══██╗
 ██║ ╚═╝ ██║██║  ██║██║  ██╗███████╗██║  ██║
 ╚═╝     ╚═╝╚═╝  ╚═╝╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝
                        Configuration Wizard
EOF

# Get the absolute path of the script directory
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
ENV_FILE="$SCRIPT_DIR/.env"
MKDOCS_YML="$SCRIPT_DIR/mkdocs/mkdocs.yml"  # Fixed path - removed extra 'docs' directory
TUNNEL_CONFIG_DIR="$SCRIPT_DIR/configs/cloudflare"
TUNNEL_CONFIG_FILE="$TUNNEL_CONFIG_DIR/tunnel-config.yml"
SERVICES_YAML="$SCRIPT_DIR/configs/homepage/services.yaml"
MAIN_HTML="$SCRIPT_DIR/mkdocs/docs/overrides/main.html"
MAP_ENV_FILE="$SCRIPT_DIR/map/.env"  # Add the map's .env file path
DOCKER_COMPOSE_FILE="$SCRIPT_DIR/docker-compose.yml"

echo "Looking for .env file at: $ENV_FILE"

# Function to generate a random secure password
generate_password() {
  local length=${1:-16}
  openssl rand -base64 48 | tr -dc 'a-zA-Z0-9!@#$%^&*()-_=+' | head -c "$length"
}

# Function to safely update environment variables in .env file
update_env_var() {
  local key=$1
  local value=$2
  
  # More robust method to handle special characters in passwords
  if grep -q "^$key=" "$ENV_FILE"; then
    # Create a temporary file
    local tmpfile=$(mktemp)
    
    # Process the .env file line by line
    while IFS= read -r line; do
      if [[ "$line" =~ ^$key= ]]; then
        echo "$key=$value" >> "$tmpfile"
      else
        echo "$line" >> "$tmpfile"
      fi
    done < "$ENV_FILE"
    
    # Replace the original file with the temporary file
    mv "$tmpfile" "$ENV_FILE"
    echo "Updated $key in .env file"
  else
    # Add new key-value pair if it doesn't exist
    echo "$key=$value" >> "$ENV_FILE"
    echo "Added $key to .env file"
  fi
}

# Function to create a timestamped backup of the .env file
backup_env_file() {
  if [ -f "$ENV_FILE" ]; then
    local timestamp=$(date +"%Y%m%d_%H%M%S")
    local backup_file="$ENV_FILE.backup_$timestamp"
    
    echo "Creating backup of current .env file to: $backup_file"
    if cp "$ENV_FILE" "$backup_file"; then
      echo "Backup created successfully!"
      return 0
    else
      echo "Failed to create backup file. Proceeding with caution..."
      return 1
    fi
  fi
}

# Function to get all used ports on the system
get_used_ports() {
  local used_ports=()
  
  # Try different methods to get used ports, in order of preference
  if command -v ss >/dev/null 2>&1; then
    # Use ss (preferred, modern replacement for netstat)
    while IFS= read -r line; do
      if [[ "$line" =~ :([0-9]+)[[:space:]] ]]; then
        used_ports+=("${BASH_REMATCH[1]}")
      fi
    done < <(ss -tuln 2>/dev/null | grep -E ':[0-9]+[[:space:]]')
  elif command -v netstat >/dev/null 2>&1; then
    # Use netstat (fallback)
    while IFS= read -r line; do
      if [[ "$line" =~ :([0-9]+)[[:space:]] ]]; then
        used_ports+=("${BASH_REMATCH[1]}")
      fi
    done < <(netstat -tuln 2>/dev/null | grep -E ':[0-9]+[[:space:]]')
  elif command -v lsof >/dev/null 2>&1; then
    # Use lsof (another fallback)
    while IFS= read -r line; do
      if [[ "$line" =~ :([0-9]+)[[:space:]] ]]; then
        used_ports+=("${BASH_REMATCH[1]}")
      fi
    done < <(lsof -i -P -n 2>/dev/null | grep LISTEN | grep -E ':[0-9]+[[:space:]]')
  else
    echo "Warning: No port scanning tools available (ss, netstat, or lsof)"
    return 1
  fi
  
  # Remove duplicates and sort
  printf '%s\n' "${used_ports[@]}" | sort -nu
}

# Function to check if a specific port is available
is_port_available() {
  local port=$1
  local used_ports_list=$2
  
  # Check if port is in the used ports list
  if echo "$used_ports_list" | grep -q "^$port$"; then
    return 1  # Port is in use
  else
    return 0  # Port is available
  fi
}

# Function to find next available port starting from a given port
find_next_available_port() {
  local start_port=$1
  local used_ports_list=$2
  local max_attempts=${3:-100}  # Maximum ports to check
  
  for ((i=0; i<max_attempts; i++)); do
    local test_port=$((start_port + i))
    
    # Skip ports below 1024 (system ports) and above 65535
    if [ "$test_port" -lt 1024 ] || [ "$test_port" -gt 65535 ]; then
      continue
    fi
    
    if is_port_available "$test_port" "$used_ports_list"; then
      echo "$test_port"
      return 0
    fi
  done
  
  echo "Error: Could not find available port starting from $start_port" >&2
  return 1
}

# Function to initialize available ports for services
initialize_available_ports() {
  echo "Scanning system for used ports to avoid conflicts..."
  
  # Get list of all used ports
  local used_ports_list
  used_ports_list=$(get_used_ports)
  
  if [ $? -ne 0 ] || [ -z "$used_ports_list" ]; then
    echo "Warning: Could not scan system ports. Using default ports."
    echo "You may need to manually resolve conflicts later."
    return 1
  fi
  
  echo "Found $(echo "$used_ports_list" | wc -l) ports currently in use"
  
  # Define desired starting ports for each service
  local -A service_ports=(
    ["CODE_SERVER_PORT"]=8888
    ["LISTMONK_PORT"]=9000
    ["LISTMONK_DB_PORT"]=5432
    ["MKDOCS_PORT"]=4000
    ["MKDOCS_SITE_SERVER_PORT"]=4001
    ["N8N_PORT"]=5678
    ["NOCODB_PORT"]=8090
    ["HOMEPAGE_PORT"]=3010
    ["GITEA_WEB_PORT"]=3030
    ["GITEA_SSH_PORT"]=2222
    ["MAP_PORT"]=3000
    ["MINI_QR_PORT"]=8089
  )
  
  # Find available ports for each service
  local -A available_ports
  for service in "${!service_ports[@]}"; do
    local preferred_port=${service_ports[$service]}
    local available_port
    
    if is_port_available "$preferred_port" "$used_ports_list"; then
      available_port=$preferred_port
      echo "✅ $service: Using preferred port $preferred_port"
    else
      available_port=$(find_next_available_port "$preferred_port" "$used_ports_list")
      if [ $? -eq 0 ]; then
        echo "⚠️  $service: Port $preferred_port in use, using $available_port instead"
      else
        echo "❌ $service: Could not find available port, using $preferred_port (may conflict)"
        available_port=$preferred_port
      fi
    fi
    
    available_ports[$service]=$available_port
    # Add the assigned port to used_ports_list to avoid double-assignment
    used_ports_list=$(printf '%s\n%s' "$used_ports_list" "$available_port" | sort -nu)
  done
  
  # Export the available ports as global variables
  for service in "${!available_ports[@]}"; do
    export "$service=${available_ports[$service]}"
  done
  
  echo "Port assignment completed successfully!"
  return 0
}

# Function to initialize the .env file with default values
initialize_env_file() {
  echo "Initializing new .env file with available ports..."
  
  # Initialize available ports before creating the .env file
  initialize_available_ports
  
  cat > "$ENV_FILE" << EOL
# Never share this file publicly. It contains sensitive information.
# This file is used to configure various applications and services.
# Generated by Changemaker Config Wizard on $(date)

# User and Group Configuration
USER_NAME=coder
USER_ID=1000
GROUP_ID=1000

# Port Configuration (automatically assigned to avoid conflicts)
CODE_SERVER_PORT=${CODE_SERVER_PORT:-8888}
LISTMONK_PORT=${LISTMONK_PORT:-9000}
LISTMONK_DB_PORT=${LISTMONK_DB_PORT:-5432}
MKDOCS_PORT=${MKDOCS_PORT:-4000}
MKDOCS_SITE_SERVER_PORT=${MKDOCS_SITE_SERVER_PORT:-4001}
N8N_PORT=${N8N_PORT:-5678}
NOCODB_PORT=${NOCODB_PORT:-8090}
HOMEPAGE_PORT=${HOMEPAGE_PORT:-3010}
GITEA_WEB_PORT=${GITEA_WEB_PORT:-3030}
GITEA_SSH_PORT=${GITEA_SSH_PORT:-2222}
MAP_PORT=${MAP_PORT:-3000}
MINI_QR_PORT=${MINI_QR_PORT:-8089}

# Domain Configuration
BASE_DOMAIN=https://changeme.org
DOMAIN=changeme.org
LISTMONK_HOSTNAME=listmonk.changeme.org
N8N_HOST=n8n.changeme.org
GITEA_DOMAIN=git.changeme.org
GITEA_ROOT_URL=https://git.changeme.org
HOMEPAGE_VAR_BASE_URL=https://changeme.org

# Cookie and CORS Configuration
COOKIE_DOMAIN=.changeme.org
ALLOWED_ORIGINS=https://map.changeme.org,http://localhost:3000

# Cloudflare Configuration
CF_API_TOKEN=your_cloudflare_api_token
CF_ZONE_ID=your_cloudflare_zone_id
CF_TUNNEL_ID=your_cloudflared_tunnel_id
CF_DOMAIN=changeme.org
CF_ACCOUNT_ID=your_cloudflare_account_id

# Database Configuration (PostgreSQL for Listmonk)
POSTGRES_USER=listmonk
POSTGRES_PASSWORD=changeMe
POSTGRES_DB=listmonk

# Listmonk Database Performance Settings
LISTMONK_DB_MAX_OPEN=25
LISTMONK_DB_MAX_IDLE=25
LISTMONK_DB_MAX_LIFETIME=300s

# Listmonk Admin Configuration
LISTMONK_ADMIN_USER=admin
LISTMONK_ADMIN_PASSWORD=changeMe

# N8N Configuration
N8N_USER_EMAIL=admin@example.com
N8N_USER_PASSWORD=changeMe
N8N_ENCRYPTION_KEY=changeMe
GENERIC_TIMEZONE=UTC

# Nocodb Configuration
NOCODB_JWT_SECRET=changeMe
NOCODB_DB_NAME=nocodb
NOCODB_DB_USER=noco
NOCODB_DB_PASSWORD=changeMe

# Gitea Database Configuration
GITEA_DB_PASSWD=changeMe
GITEA_DB_ROOT_PASSWORD=changeMe
EOL

  echo "New .env file created with conflict-free port assignments."
  
  # Show port assignments summary
  echo ""
  echo "=== Port Assignments Summary ==="
  echo "Code Server: ${CODE_SERVER_PORT:-8888}"
  echo "Listmonk: ${LISTMONK_PORT:-9000}"
  echo "Listmonk DB: ${LISTMONK_DB_PORT:-5432}"
  echo "MkDocs: ${MKDOCS_PORT:-4000}"
  echo "MkDocs Site: ${MKDOCS_SITE_SERVER_PORT:-4001}"
  echo "N8N: ${N8N_PORT:-5678}"
  echo "NocoDB: ${NOCODB_PORT:-8090}"
  echo "Homepage: ${HOMEPAGE_PORT:-3010}"
  echo "Gitea Web: ${GITEA_WEB_PORT:-3030}"
  echo "Gitea SSH: ${GITEA_SSH_PORT:-2222}"
  echo "Map: ${MAP_PORT:-3000}"
  echo "Mini QR: ${MINI_QR_PORT:-8089}"
  echo "================================"
}

# Function to update the site_url in mkdocs.yml
update_mkdocs_yml() {
  local new_domain=$1
  
  if [ ! -f "$MKDOCS_YML" ]; then
    echo "Warning: mkdocs.yml not found at $MKDOCS_YML"
    return 1
  fi
  
  echo "Updating site_url in mkdocs.yml..."
  
  # Create a backup of the mkdocs.yml file
  local timestamp=$(date +"%Y%m%d_%H%M%S")
  local backup_file="${MKDOCS_YML}.backup_${timestamp}"
  cp "$MKDOCS_YML" "$backup_file"
  echo "Created backup of mkdocs.yml at $backup_file"
  
  # Update the site_url value - handle both http and https
  sed -i "s|^site_url:.*|site_url: https://$new_domain|" "$MKDOCS_YML"
  
  if grep -q "site_url: https://$new_domain" "$MKDOCS_YML"; then
    echo "✅ Updated site_url in mkdocs.yml to: https://$new_domain"
    return 0
  else
    echo "Warning: Failed to update site_url in mkdocs.yml"
    return 1
  fi
}

# Function to update service URLs in services.yaml
update_services_yaml() {
  local new_domain=$1
  
  if [ ! -f "$SERVICES_YAML" ]; then
    echo "Warning: services.yaml not found at $SERVICES_YAML"
    return 1
  fi
  
  echo "Updating service URLs in services.yaml..."
  
  # Create a backup of the services.yaml file
  local timestamp=$(date +"%Y%m%d_%H%M%S")
  local backup_file="${SERVICES_YAML}.backup_${timestamp}"
  cp "$SERVICES_YAML" "$backup_file"
  echo "Created backup of services.yaml at $backup_file"
  
  # Define service name to subdomain mapping
  # This approach is URL-agnostic - it doesn't matter what the current URLs are
  declare -A service_mappings=(
    ["Code Server"]="code.$new_domain"
    ["Listmonk"]="listmonk.$new_domain"
    ["NocoDB"]="db.$new_domain"
    ["Map Server"]="map.$new_domain"
    ["Main Site"]="$new_domain"
    ["MkDocs (Live)"]="docs.$new_domain"
    ["Mini QR"]="qr.$new_domain"
    ["n8n"]="n8n.$new_domain"
    ["Gitea"]="git.$new_domain"
  )
  
  # Process each service mapping
  for service_name in "${!service_mappings[@]}"; do
    local target_url="https://${service_mappings[$service_name]}"
    
    # Use awk to find and update the href for each specific service
    # This finds the service by name and updates its href regardless of current URL
    awk -v service="$service_name" -v new_url="$target_url" '
    BEGIN { in_service = 0 }
    
    # Check if we found the service name
    /- [^:]+:/ { 
      if ($0 ~ ("- " service ":")) {
        in_service = 1
      } else {
        in_service = 0
      }
    }
    
    # If we are in the target service and find href line, update it
    in_service && /href:/ {
      gsub(/href: "[^"]*"/, "href: \"" new_url "\"")
    }
    
    # Print the line (modified or not)
    { print }
    ' "$SERVICES_YAML" > "${SERVICES_YAML}.tmp"
    
    # Replace the original file with the updated version
    mv "${SERVICES_YAML}.tmp" "$SERVICES_YAML"
    
    echo "  ✓ Updated $service_name -> $target_url"
  done
  
  echo "✅ All service URLs updated to use domain: $new_domain"
  return 0
}

# Function to update the login URL in main.html
update_main_html() {
  local new_domain=$1
  
  if [ ! -f "$MAIN_HTML" ]; then
    echo "Warning: main.html not found at $MAIN_HTML"
    return 1
  fi
  
  echo "Updating login URL in main.html..."
  
  # Create a backup of the main.html file
  local timestamp=$(date +"%Y%m%d_%H%M%S")
  local backup_file="${MAIN_HTML}.backup_${timestamp}"
  cp "$MAIN_HTML" "$backup_file"
  echo "Created backup of main.html at $backup_file"
  
  # Update the login button href - handle current domain
  sed -i "s|href=\"https://homepage\.[^\"]*\"|href=\"https://homepage.$new_domain\"|g" "$MAIN_HTML"
  
  # Also update any albertademocracytaskforce.org references
  sed -i "s|albertademocracytaskforce\.org|$new_domain|g" "$MAIN_HTML"
  
  # Update any test.com or changeme.org references
  sed -i "s|test\.com|$new_domain|g" "$MAIN_HTML"
  sed -i "s|changeme\.org|$new_domain|g" "$MAIN_HTML"
  
  echo "✅ Updated login URL in main.html to: https://homepage.$new_domain"
  return 0
}

# Function to get Cloudflare API Token and Zone ID
get_cloudflare_credentials() {
  echo ""
  echo "To use Cloudflare tunnels, you'll need to configure your credentials."
  echo ""
  echo "=== Cloudflare Configuration ==="
  echo ""
  echo "You'll need:"
  echo "1. Your Cloudflare API Token (with Zone.DNS and Account.Cloudflare Tunnel permissions)"
  echo "2. Your Cloudflare Zone ID (found in the Cloudflare dashboard overview)"
  echo "3. Your Cloudflare Account ID (found in the Cloudflare dashboard)"
  echo ""
  echo "These credentials will be used for:"
  echo "- Creating and configuring tunnels"
  echo "- Managing DNS records"
  echo "- Setting up access policies"
  echo ""
}

# Function to update the tunnel configuration file with new domain
update_tunnel_config() {
  local new_domain=$1
  local tunnel_id=${2:-"(insert-tunnel-id)"}
  local creds_path=${3:-"/path/to/credentials/file"}
  
  # Create directory if it doesn't exist
  mkdir -p "$TUNNEL_CONFIG_DIR"
  
  echo "Updating tunnel configuration with new domain..."
  
  # Create a backup if file exists
  if [ -f "$TUNNEL_CONFIG_FILE" ]; then
    local timestamp=$(date +"%Y%m%d_%H%M%S")
    local backup_file="${TUNNEL_CONFIG_FILE}.backup_${timestamp}"
    cp "$TUNNEL_CONFIG_FILE" "$backup_file"
    echo "Created backup of tunnel-config.yml at $backup_file"
  fi
  
  # Load current environment variables to get port numbers
  load_env_vars
  
  # Create/update the tunnel configuration
  cat > "$TUNNEL_CONFIG_FILE" << EOL
# filepath: /home/bunker-admin/changemaker.lite/configs/cloudflare/tunnel-config.yml
# Cloudflare Tunnel Configuration
# Auto-generated by Changemaker Configuration Wizard

tunnel: $tunnel_id # e.g. 1234567890abcdef
credentials-file: $creds_path # e.g. /home/bunker-admin/.cloudflared/[insert tunnel number].json
ingress:

  - hostname: homepage.$new_domain
    service: http://localhost:${HOMEPAGE_PORT:-3010}

  - hostname: code.$new_domain
    service: http://localhost:${CODE_SERVER_PORT:-8888}

  - hostname: listmonk.$new_domain
    service: http://localhost:${LISTMONK_PORT:-9001}
    
  - hostname: docs.$new_domain
    service: http://localhost:${MKDOCS_PORT:-4000}
    
  - hostname: $new_domain
    service: http://localhost:${MKDOCS_SITE_SERVER_PORT:-4002}
    
  - hostname: n8n.$new_domain
    service: http://localhost:${N8N_PORT:-5678}
    
  - hostname: db.$new_domain
    service: http://localhost:${NOCODB_PORT:-8090}

  - hostname: git.$new_domain
    service: http://localhost:${GITEA_WEB_PORT:-3030}

  - hostname: map.$new_domain
    service: http://localhost:${MAP_PORT:-3000}

  - hostname: qr.$new_domain
    service: http://localhost:${MINI_QR_PORT:-8089}

  # Catch-all rule (required)
  - service: http_status:404
EOL
  
  echo "✅ Updated tunnel configuration for domain: $new_domain"
  return 0
}

# Function to load environment variables from .env file
load_env_vars() {
  if [ -f "$ENV_FILE" ]; then
    # Load variables from .env file, ignoring comments and empty lines
    while IFS= read -r line; do
      if [[ "$line" =~ ^[A-Za-z_][A-Za-z0-9_]*= ]]; then
        export "$line"
      fi
    done < <(grep -E '^[A-Za-z_][A-Za-z0-9_]*=' "$ENV_FILE")
  fi
}

# Function to update or create the map's .env file with domain settings
update_map_env() {
    local new_domain=$1
    
    # Check if the map directory exists
    if [ ! -d "$SCRIPT_DIR/map" ]; then
        echo "Map directory not found at $SCRIPT_DIR/map"
        return
    fi
    
    echo "Creating/updating map .env file at: $MAP_ENV_FILE"
    
    cat > "$MAP_ENV_FILE" << EOL
NOCODB_API_URL=https://db.$new_domain/api/v1
NOCODB_API_TOKEN=changeme

# NocoDB View URL is the URL to your NocoDB view where the map data is stored.
NOCODB_VIEW_URL=

# NOCODB_LOGIN_SHEET is the URL to your NocoDB login sheet.
NOCODB_LOGIN_SHEET=

# NOCODB_SETTINGS_SHEET is the URL to your NocoDB settings sheet.
NOCODB_SETTINGS_SHEET=

# NOCODB_SHIFTS_SHEET is the urls to your shifts sheets.
NOCODB_SHIFTS_SHEET=

# NOCODB_SHIFT_SIGNUPS_SHEET is the URL to your NocoDB shift signups sheet where users can add their own shifts.
NOCODB_SHIFT_SIGNUPS_SHEET=

# MkDocs Integration (using main domain, not subdomain)
MKDOCS_URL=https://$new_domain
MKDOCS_SEARCH_URL=https://$new_domain
MKDOCS_SITE_SERVER_PORT=4002

# Server Configuration
PORT=3000
NODE_ENV=production

# Session Secret (IMPORTANT: Generate a secure random string for production)
# You can generate one with: openssl rand -hex 32
SESSION_SECRET=$(openssl rand -hex 32 2>/dev/null || echo "changeme")

# Map Defaults (Edmonton, Alberta, Canada)
DEFAULT_LAT=53.5461
DEFAULT_LNG=-113.4938
DEFAULT_ZOOM=11

# Optional: Map Boundaries (prevents users from adding points outside area)
# BOUND_NORTH=53.7
# BOUND_SOUTH=53.4
# BOUND_EAST=-113.3
# BOUND_WEST=-113.7

# Cloudflare Settings
TRUST_PROXY=true
COOKIE_DOMAIN=.$new_domain

# Update NODE_ENV to production for HTTPS
NODE_ENV=production

# Add allowed origin
ALLOWED_ORIGINS=https://map.$new_domain,http://localhost:3000
EOL
    
    echo "Map .env file updated with domain: $new_domain"
}

# Function to sync ports from root .env to map .env
sync_map_ports() {
    echo "Syncing ports from root .env to map configuration..."
    
    # Load the current port values from root .env
    local mkdocs_port=$(grep "^MKDOCS_PORT=" "$ENV_FILE" | cut -d'=' -f2)
    local mkdocs_site_port=$(grep "^MKDOCS_SITE_SERVER_PORT=" "$ENV_FILE" | cut -d'=' -f2)
    local map_port=$(grep "^MAP_PORT=" "$ENV_FILE" | cut -d'=' -f2)
    
    # Set defaults if not found
    mkdocs_port=${mkdocs_port:-4000}
    mkdocs_site_port=${mkdocs_site_port:-4002}
    map_port=${map_port:-3000}
    
    # Update the map's .env with the correct ports
    if grep -q "^PORT=" "$MAP_ENV_FILE"; then
        sed -i "s|^PORT=.*|PORT=$map_port|" "$MAP_ENV_FILE"
    else
        echo "PORT=$map_port" >> "$MAP_ENV_FILE"
    fi
    
    # Add/Update MkDocs configuration
    if grep -q "^MKDOCS_URL=" "$MAP_ENV_FILE"; then
        sed -i "s|^MKDOCS_URL=.*|MKDOCS_URL=http://localhost:$mkdocs_site_port|" "$MAP_ENV_FILE"
    else
        echo "" >> "$MAP_ENV_FILE"
        echo "# MkDocs Integration" >> "$MAP_ENV_FILE"
        echo "MKDOCS_URL=http://localhost:$mkdocs_site_port" >> "$MAP_ENV_FILE"
    fi
    
    if grep -q "^MKDOCS_SEARCH_URL=" "$MAP_ENV_FILE"; then
        sed -i "s|^MKDOCS_SEARCH_URL=.*|MKDOCS_SEARCH_URL=http://localhost:$mkdocs_site_port|" "$MAP_ENV_FILE"
    else
        echo "MKDOCS_SEARCH_URL=http://localhost:$mkdocs_site_port" >> "$MAP_ENV_FILE"
    fi
    
    if grep -q "^MKDOCS_SITE_SERVER_PORT=" "$MAP_ENV_FILE"; then
        sed -i "s|^MKDOCS_SITE_SERVER_PORT=.*|MKDOCS_SITE_SERVER_PORT=$mkdocs_site_port|" "$MAP_ENV_FILE"
    else
        echo "MKDOCS_SITE_SERVER_PORT=$mkdocs_site_port" >> "$MAP_ENV_FILE"
    fi
    
    echo "✅ Synced ports to map configuration:"
    echo "   - Map Port: $map_port"
    echo "   - MkDocs Dev Port: $mkdocs_port"
    echo "   - MkDocs Site Port: $mkdocs_site_port"
    echo "   - MkDocs URL: http://localhost:$mkdocs_site_port"
}

# Function to update or create the map's .env file with domain settings
update_map_env() {
  local new_domain=$1

  # If the map .env file does not exist, create it with defaults
  if [ ! -f "$MAP_ENV_FILE" ]; then
    echo "Map .env file not found at $MAP_ENV_FILE, creating a new one with defaults."
    cat > "$MAP_ENV_FILE" <<EOL
NOCODB_API_URL=https://db.$new_domain/api/v1
NOCODB_API_TOKEN=changeme

# NocoDB View URL is the URL to your NocoDB view where the map data is stored.
NOCODB_VIEW_URL=

# NOCODB_LOGIN_SHEET is the URL to your NocoDB login sheet.
NOCODB_LOGIN_SHEET=

# NOCODB_SETTINGS_SHEET is the URL to your NocoDB settings sheet.
NOCODB_SETTINGS_SHEET=

# NOCODB_SHIFTS_SHEET is the urls to your shifts sheets.
NOCODB_SHIFTS_SHEET=

# NOCODB_SHIFT_SIGNUPS_SHEET is the URL to your NocoDB shift signups sheet where users can add their own shifts.
NOCODB_SHIFT_SIGNUPS_SHEET=

# Server Configuration
PORT=3000
NODE_ENV=production

# Session Secret (IMPORTANT: Generate a secure random string for production)
# You can generate one with: openssl rand -hex 32
SESSION_SECRET=$(openssl rand -hex 32 2>/dev/null || echo "changeme")

# Map Defaults (Edmonton, Alberta, Canada)
DEFAULT_LAT=53.5461
DEFAULT_LNG=-113.4938
DEFAULT_ZOOM=11

# Optional: Map Boundaries (prevents users from adding points outside area)
# BOUND_NORTH=53.7
# BOUND_SOUTH=53.4
# BOUND_EAST=-113.3
# BOUND_WEST=-113.7

# Cloudflare Settings
TRUST_PROXY=true
COOKIE_DOMAIN=.$new_domain

# Update NODE_ENV to production for HTTPS
NODE_ENV=production

# Add allowed origin
ALLOWED_ORIGINS=https://map.$new_domain,http://localhost:3000
EOL
    echo "✅ Created new map .env file at $MAP_ENV_FILE"
    return 0
  fi

  echo "Updating map .env file with new domain settings..."

  # Create a backup of the map's .env file
  local timestamp=$(date +"%Y%m%d_%H%M%S")
  local backup_file="${MAP_ENV_FILE}.backup_${timestamp}"
  cp "$MAP_ENV_FILE" "$backup_file"
  echo "Created backup of map .env at $backup_file"

  # Update NOCODB_API_URL to use new domain
  if grep -q "^NOCODB_API_URL=" "$MAP_ENV_FILE"; then
    sed -i "s|^NOCODB_API_URL=.*|NOCODB_API_URL=https://db.$new_domain/api/v1|" "$MAP_ENV_FILE"
  else
    echo "NOCODB_API_URL=https://db.$new_domain/api/v1" >> "$MAP_ENV_FILE"
  fi

  # Update COOKIE_DOMAIN
  if grep -q "^COOKIE_DOMAIN=" "$MAP_ENV_FILE"; then
    sed -i "s|^COOKIE_DOMAIN=.*|COOKIE_DOMAIN=.$new_domain|" "$MAP_ENV_FILE"
  else
    echo "COOKIE_DOMAIN=.$new_domain" >> "$MAP_ENV_FILE"
  fi

  # Update ALLOWED_ORIGINS
  local allowed_origins="https://map.$new_domain,http://localhost:3000"
  if grep -q "^ALLOWED_ORIGINS=" "$MAP_ENV_FILE"; then
    sed -i "s|^ALLOWED_ORIGINS=.*|ALLOWED_ORIGINS=$allowed_origins|" "$MAP_ENV_FILE"
  else
    echo "ALLOWED_ORIGINS=$allowed_origins" >> "$MAP_ENV_FILE"
  fi

  # Update domain references in NocoDB URLs while preserving the sheet IDs and paths
  # This will update domains like cmlite.org, changeme.org, etc. to the new domain
  sed -i "s|://db\.cmlite\.org/|://db.$new_domain/|g" "$MAP_ENV_FILE"
  sed -i "s|://map\.cmlite\.org|://map.$new_domain|g" "$MAP_ENV_FILE"

  echo "✅ Updated map .env file with:"
  echo "   - NOCODB_API_URL=https://db.$new_domain/api/v1"
  echo "   - COOKIE_DOMAIN=.$new_domain"
  echo "   - ALLOWED_ORIGINS=$allowed_origins"
  echo "   - Updated all NocoDB URLs to use $new_domain domain"
  
  # Sync ports to map configuration
  sync_map_ports
  
  return 0
}

# Function to get instance identifier
get_instance_identifier() {
  # Try to get from directory name first
  local dir_name=$(basename "$SCRIPT_DIR")
  local default_instance=""
  
  # Extract potential instance name from directory
  if [[ "$dir_name" =~ changemaker\.lite\.(.+)$ ]]; then
    default_instance="${BASH_REMATCH[1]}"
  elif [[ "$dir_name" != "changemaker.lite" ]]; then
    default_instance="$dir_name"
  fi
  
  echo ""
  echo "=== Instance Configuration ==="
  echo "To run multiple Changemaker instances on the same machine,"
  echo "each instance needs a unique identifier for containers and networks."
  echo ""
  
  if [ -n "$default_instance" ]; then
    echo "Detected potential instance name from directory: $default_instance"
    read -p "Use this instance identifier? [Y/n]: " use_detected
    if [[ ! "$use_detected" =~ ^[Nn]$ ]]; then
      echo "$default_instance"
      return 0
    fi
  fi
  
  read -p "Enter instance identifier (letters, numbers, hyphens only) [default: main]: " instance_id
  
  # Validate and sanitize instance identifier
  if [ -z "$instance_id" ]; then
    instance_id="main"
  fi
  
  # Remove invalid characters and convert to lowercase
  instance_id=$(echo "$instance_id" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]//g')
  
  if [ -z "$instance_id" ]; then
    instance_id="main"
  fi
  
  echo "$instance_id"
}

# Function to update docker-compose.yml with unique names
update_docker_compose_names() {
  local instance_id=$1
  
  if [ -z "$instance_id" ] || [ "$instance_id" = "main" ]; then
    echo "Using default container names (no instance suffix)"
    return 0
  fi
  
  echo "Updating docker-compose.yml with instance identifier: $instance_id"
  
  # Create a backup of the docker-compose.yml file
  local timestamp=$(date +"%Y%m%d_%H%M%S")
  local backup_file="${DOCKER_COMPOSE_FILE}.backup_${timestamp}"
  cp "$DOCKER_COMPOSE_FILE" "$backup_file"
  echo "Created backup of docker-compose.yml at $backup_file"
  
  # Create temporary file for modifications
  local temp_file=$(mktemp)
  
  # Update container names, network names, and volume names
  sed -e "s/container_name: \([^-]*\)$/container_name: \1-${instance_id}/g" \
      -e "s/container_name: \([^-]*\)-changemaker$/container_name: \1-changemaker-${instance_id}/g" \
      -e "s/container_name: \([^-]*\)_\([^-]*\)$/container_name: \1_\2_${instance_id}/g" \
      -e "s/container_name: \([^-]*\)_\([^-]*\)_changemaker$/container_name: \1_\2_changemaker_${instance_id}/g" \
      -e "s/networks:/networks:/g" \
      -e "s/changemaker-lite:/changemaker-lite-${instance_id}:/g" \
      -e "s/- changemaker-lite$/- changemaker-lite-${instance_id}/g" \
      -e "s/driver: bridge$/driver: bridge/g" \
      -e "s/volumes:/volumes:/g" \
      -e "s/listmonk-data:/listmonk-data-${instance_id}:/g" \
      -e "s/n8n_data:/n8n_data_${instance_id}:/g" \
      -e "s/nc_data:/nc_data_${instance_id}:/g" \
      -e "s/db_data:/db_data_${instance_id}:/g" \
      -e "s/gitea_data:/gitea_data_${instance_id}:/g" \
      -e "s/mysql_data:/mysql_data_${instance_id}:/g" \
      "$DOCKER_COMPOSE_FILE" > "$temp_file"
  
  # Replace the original file
  mv "$temp_file" "$DOCKER_COMPOSE_FILE"
  
  echo "✅ Updated docker-compose.yml with instance-specific names:"
  echo "   - Container names: *-${instance_id}"
  echo "   - Network name: changemaker-lite-${instance_id}"
  echo "   - Volume names: *-${instance_id}"
  
  return 0
}

# Function to update .env file with instance identifier
update_env_instance_config() {
  local instance_id=$1
  
  if [ -n "$instance_id" ] && [ "$instance_id" != "main" ]; then
    update_env_var "INSTANCE_ID" "$instance_id"
    update_env_var "COMPOSE_PROJECT_NAME" "changemaker-lite-${instance_id}"
    echo "Updated .env with instance configuration"
  fi
}

# Initialize a new .env file if it doesn't exist
if [ ! -f "$ENV_FILE" ]; then
  echo "No .env file found. Creating a new one from scratch."
  touch "$ENV_FILE"
  initialize_env_file
else
  echo "Found existing .env file. Will update values."
  backup_env_file
  
  # For existing .env files, also scan ports and suggest alternatives if conflicts exist
  echo ""
  echo "Checking existing port assignments for conflicts..."
  load_env_vars
  check_port_conflicts
fi

# Load existing environment variables
load_env_vars

echo -e "\n\nWelcome to Changemaker Config!\n"
echo "This script will help you configure your .env file for Changemaker."
echo "Please provide the following information:"

# Get instance identifier and update docker-compose.yml
echo -e "\n---- Instance Configuration ----"
instance_identifier=$(get_instance_identifier)
update_docker_compose_names "$instance_identifier"
update_env_instance_config "$instance_identifier"

# Domain configuration
read -p "Enter your domain name (without protocol, e.g., example.com): " domain_name

if [ -z "$domain_name" ]; then
  echo "Domain name cannot be empty. Using default: changeme.org"
  domain_name="changeme.org"
fi

echo -e "\nUpdating domain settings in .env file..."

# Update main domain settings
update_env_var "DOMAIN" "$domain_name"
update_env_var "BASE_DOMAIN" "https://$domain_name"
update_env_var "HOMEPAGE_VAR_BASE_URL" "https://$domain_name"
update_env_var "LISTMONK_HOSTNAME" "listmonk.$domain_name"
update_env_var "N8N_HOST" "n8n.$domain_name"
update_env_var "CF_DOMAIN" "$domain_name"
update_env_var "GITEA_DOMAIN" "git.$domain_name"
update_env_var "GITEA_ROOT_URL" "https://git.$domain_name"

# Update cookie and CORS settings
update_env_var "COOKIE_DOMAIN" ".$domain_name"
update_env_var "ALLOWED_ORIGINS" "https://map.$domain_name,http://localhost:3000"

echo "Domain settings updated successfully!"

# Update the map's .env file
echo -e "\nUpdating map configuration..."
update_map_env "$domain_name"

# Cloudflare Configuration
echo -e "\n---- Cloudflare Configuration ----"
get_cloudflare_credentials

read -p "Do you want to configure Cloudflare settings now? [Y/n]: " configure_cf

if [[ ! "$configure_cf" =~ ^[Nn]$ ]]; then
  # Get Cloudflare API token
  read -p "Enter your Cloudflare API Token: " cf_api_token
  if [ -z "$cf_api_token" ] || [ "$cf_api_token" = "your_cloudflare_api_token" ]; then
    echo "Warning: API token is required for Cloudflare integration"
    cf_api_token="your_cloudflare_api_token"
  fi
  update_env_var "CF_API_TOKEN" "$cf_api_token"

  # Get Cloudflare Zone ID
  read -p "Enter your Cloudflare Zone ID: " cf_zone_id
  if [ -z "$cf_zone_id" ] || [ "$cf_zone_id" = "your_cloudflare_zone_id" ]; then
    echo "Warning: Zone ID is required for DNS configuration"
    cf_zone_id="your_cloudflare_zone_id"
  fi
  update_env_var "CF_ZONE_ID" "$cf_zone_id"

  # Get Cloudflare Account ID
  read -p "Enter your Cloudflare Account ID: " cf_account_id
  if [ -z "$cf_account_id" ] || [ "$cf_account_id" = "your_cloudflare_account_id" ]; then
    echo "Warning: Account ID is required for tunnel operations"
    cf_account_id="your_cloudflare_account_id"
  fi
  update_env_var "CF_ACCOUNT_ID" "$cf_account_id"
  
  # Note: CF_TUNNEL_ID will be set by start-production.sh when the tunnel is created
  update_env_var "CF_TUNNEL_ID" "will_be_set_by_start_production"
  
  echo ""
  echo "Cloudflare configuration saved to .env file."
  echo ""
  echo "To complete the setup and deploy your services:"
  echo "1. Start your services with: docker compose up -d"
  echo "2. Run ./start-production.sh to configure the Cloudflare tunnel"
  echo ""
else
  echo "Skipping Cloudflare configuration."
  echo "You'll need to configure Cloudflare settings manually before running start-production.sh."
fi

# Update the site_url in mkdocs.yml
echo -e "\nUpdating site_url in mkdocs.yml..."
update_mkdocs_yml "$domain_name"

# Update service URLs in services.yaml
echo -e "\nUpdating service URLs in services.yaml..."
update_services_yaml "$domain_name"

# Update the login URL in main.html
echo -e "\nUpdating login URL in main.html..."
update_main_html "$domain_name"

# Listmonk Admin Credentials configuration
echo -e "\n---- Listmonk Admin Credentials ----"
read -p "Enter Listmonk admin email/username [default: admin@example.com]: " listmonk_user
read -sp "Enter Listmonk admin password [default: changeMe]: " listmonk_password
echo # Add new line after password input

if [ -z "$listmonk_user" ]; then
  listmonk_user="admin@example.com"
fi

if [ -z "$listmonk_password" ]; then
  listmonk_password="changeMe"
fi

update_env_var "LISTMONK_ADMIN_USER" "$listmonk_user"
update_env_var "LISTMONK_ADMIN_PASSWORD" "$listmonk_password"

echo "Listmonk admin credentials updated."

# N8N User Credentials configuration
echo -e "\n---- N8N Admin Credentials ----"
read -p "Enter N8N admin email [default: admin@example.com]: " n8n_email
read -sp "Enter N8N admin password [default: changeMe]: " n8n_password
echo # Add new line after password input

if [ -z "$n8n_email" ]; then
  n8n_email="admin@example.com"
fi

if [ -z "$n8n_password" ]; then
  n8n_password="changeMe"
fi

update_env_var "N8N_USER_EMAIL" "$n8n_email"
update_env_var "N8N_USER_PASSWORD" "$n8n_password"

echo "N8N admin credentials updated."

# Generate secure passwords for database and encryption
echo -e "\n---- Generating Secure Passwords ----"
echo "Generating secure passwords for database and encryption keys..."

# Generate and update database password
postgres_password=$(generate_password 20)
update_env_var "POSTGRES_PASSWORD" "$postgres_password"

# Generate and update N8N encryption key
n8n_encryption_key=$(generate_password 32)
update_env_var "N8N_ENCRYPTION_KEY" "$n8n_encryption_key"

# Generate and update NocoDB passwords
nocodb_jwt_secret=$(generate_password 32)
update_env_var "NOCODB_JWT_SECRET" "$nocodb_jwt_secret"

nocodb_db_password=$(generate_password 20)
update_env_var "NOCODB_DB_PASSWORD" "$nocodb_db_password"

# Generate and update Gitea passwords (these should already exist in the file)
gitea_db_password=$(generate_password 20)
update_env_var "GITEA_DB_PASSWD" "$gitea_db_password"

gitea_db_root_password=$(generate_password 20)
update_env_var "GITEA_DB_ROOT_PASSWORD" "$gitea_db_root_password"

echo "Secure passwords generated and updated."

echo -e "\n✅ Configuration completed successfully!"
echo "Your .env file has been configured with:"
echo "- Instance ID: $instance_identifier"
echo "- Domain: $domain_name"
echo "- Cookie Domain: .$domain_name"
echo "- Allowed Origins: https://map.$domain_name,http://localhost:3000"
echo "- Map .env updated with domain settings"
echo "- Listmonk Admin: $listmonk_user"
echo "- N8N Admin Email: $n8n_email"
echo "- Secure random passwords for database, encryption, and NocoDB"
echo "- Tunnel configuration updated at: $TUNNEL_CONFIG_FILE"
echo -e "\nYour .env file is located at: $ENV_FILE"
echo "A backup of your original .env file was created before modifications."

echo ""
echo "======================================"
echo "Next Steps:"
echo "======================================"
echo ""
if [ -n "$instance_identifier" ] && [ "$instance_identifier" != "main" ]; then
  echo "Instance: $instance_identifier"
  echo ""
fi
echo "1. Start services locally:"
echo "   docker compose up -d"
echo ""
echo "2. Test all services at:"
echo "   - Homepage: http://localhost:${HOMEPAGE_PORT:-3010}"
echo "   - Code Server: http://localhost:${CODE_SERVER_PORT:-8888}"
echo "   - Listmonk: http://localhost:${LISTMONK_PORT:-9000}"
echo "   - Documentation: http://localhost:${MKDOCS_PORT:-4000}"
echo "   - n8n: http://localhost:${N8N_PORT:-5678}"
echo "   - NocoDB: http://localhost:${NOCODB_PORT:-8090}"
echo "   - Gitea: http://localhost:${GITEA_WEB_PORT:-3030}"
echo "   - Map: http://localhost:${MAP_PORT:-3000}"
echo "   - Mini QR: http://localhost:${MINI_QR_PORT:-8089}"
echo ""
echo "3. When ready for production:"
echo "   ./start-production.sh"
echo ""
echo "======================================"