#!/bin/bash
echo "#############################################################"
echo "#                                                           "
echo "#  WARNING: This script will REPLACE ALL DNS records at      "
echo "#  the target domain ($CF_DOMAIN)!                           "
echo "#                                                           "
echo "#  All existing DNS records for the listed subdomains will   "
echo "#  be deleted and replaced with new CNAME records.           "
echo "#                                                           "
echo "#############################################################"
echo ""
echo "-------------------------------------------------------------"
echo "Cloudflare Credentials Required"
echo "Please ensure your .env file contains the following variables:"
echo "  CF_API_TOKEN=your_cloudflare_api_token"
echo "  CF_ZONE_ID=your_cloudflare_zone_id"
echo "  CF_TUNNEL_ID=your_cloudflared_tunnel_id"
echo "  CF_DOMAIN=yourdomain.com"
echo ""
echo "You can find these values in your Cloudflare dashboard:"
echo "  - API Token: https://dash.cloudflare.com/profile/api-tokens (Create a token with Zone:DNS:Edit and Access:Apps:Edit permissions for your domain)"
echo "  - Zone ID: On your domain's overview page"
echo "  - Tunnel ID: In the Zero Trust dashboard under Access > Tunnels"
echo "  - Domain: The domain you want to use for your services"
echo ""
echo "-------------------------------------------------------------"
echo ""
read -p "Type 'y' to continue or any other key to abort: " consent
if [[ "$consent" != "y" && "$consent" != "Y" ]]; then
  echo "Aborted by user."
  exit 1
fi
# Source environment variables from the .env file in the same directory
ENV_FILE="$(dirname "$0")/.env"
if [ -f "$ENV_FILE" ]; then
  export $(grep -v '^#' "$ENV_FILE" | xargs)
else
  echo "Error: .env file not found at $ENV_FILE"
  exit 1
fi

# Check if required Cloudflare variables are set
if [ -z "$CF_API_TOKEN" ] || [ -z "$CF_ZONE_ID" ] || [ -z "$CF_TUNNEL_ID" ] || [ -z "$CF_DOMAIN" ]; then
  echo "Error: One or more required Cloudflare environment variables (CF_API_TOKEN, CF_ZONE_ID, CF_TUNNEL_ID, CF_DOMAIN) are not set in $ENV_FILE."
  exit 1
fi

# Check if jq is installed
if ! command -v jq &> /dev/null; then
    echo "Error: jq is required but not installed. Please install jq to continue."
    echo "On Debian/Ubuntu: sudo apt-get install jq"
    echo "On RHEL/CentOS: sudo yum install jq"
    exit 1
fi

# Array of subdomains based on docker-compose.yml services
SUBDOMAINS=(
  "homepage"
  "excalidraw"
  "listmonk"
  "monica"
  "flatnotes"
  "code-server"
  "ollama"
  "open-webui"
  "gitea"
  "mini-qr"
  "ferdium"
  "answer"
  "nocodb"
  "n8n"
  "convertx"
  "rocket"
  "live"
  "vw"
)

# First, remove existing DNS records for these subdomains
echo "Removing existing DNS records..."

for subdomain in "${SUBDOMAINS[@]}"; do
  echo "Checking for existing records for $subdomain.$CF_DOMAIN..."
  
  # Get all DNS records for this subdomain
  RECORDS=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records?name=$subdomain.$CF_DOMAIN" \
    -H "Authorization: Bearer $CF_API_TOKEN" \
    -H "Content-Type: application/json")
  
  # Extract record IDs
  RECORD_IDS=$(echo $RECORDS | jq -r '.result[].id')
  
  # Delete each record
  for record_id in $RECORD_IDS; do
    echo "Deleting record $record_id for $subdomain.$CF_DOMAIN..."
    
    curl -s -X DELETE "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records/$record_id" \
      -H "Authorization: Bearer $CF_API_TOKEN" \
      -H "Content-Type: application/json"
  done
done

echo "All existing records have been removed."

# Add CNAME records for each subdomain
for subdomain in "${SUBDOMAINS[@]}"; do
  echo "Adding CNAME record for $subdomain.$CF_DOMAIN..."
  
  curl -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records" \
    -H "Authorization: Bearer $CF_API_TOKEN" \
    -H "Content-Type: application/json" \
    --data "{
      \"type\": \"CNAME\",
      \"name\": \"$subdomain\",
      \"content\": \"$CF_TUNNEL_ID.cfargotunnel.com\",
      \"ttl\": 1,
      \"proxied\": true
    }"
  
  echo -e "\n"
done

echo "All CNAME records have been added."

# Add root domain record
echo "Adding root domain (@ record)..."
curl -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records" \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data "{
    \"type\": \"CNAME\",
    \"name\": \"@\",
    \"content\": \"$CF_TUNNEL_ID.cfargotunnel.com\",
    \"ttl\": 1,
    \"proxied\": true
  }"
echo -e "\n"
echo "Root domain CNAME record has been added."

# Prompt for admin email
echo "Please enter the admin email address that should have access to protected services:"
read ADMIN_EMAIL

# Validate email format
if [[ ! "$ADMIN_EMAIL" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
  echo "Error: Invalid email format. Please provide a valid email address."
  exit 1
fi

# Now create the Cloudflare Access applications
echo "Creating Cloudflare Access applications..."

# Create access applications only for specific services
PROTECTED_SERVICES=("homepage" "live" "ferdium" "convertx" "mini-qr" "ollama")

for service in "${PROTECTED_SERVICES[@]}"; do
  echo "Creating access application for $service.$CF_DOMAIN..."
  
  SERVICE_APP_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/access/apps" \
    -H "Authorization: Bearer $CF_API_TOKEN" \
    -H "Content-Type: application/json" \
    --data "{
      \"name\": \"$service $CF_DOMAIN\",
      \"domain\": \"$service.$CF_DOMAIN\",
      \"type\": \"self_hosted\",
      \"session_duration\": \"24h\",
      \"app_launcher_visible\": true,
      \"skip_interstitial\": true
    }")

  # Extract the application ID from the response
  SERVICE_APP_ID=$(echo $SERVICE_APP_RESPONSE | jq -r '.result.id')

  if [ -z "$SERVICE_APP_ID" ] || [ "$SERVICE_APP_ID" == "null" ]; then
    echo "Error creating $service access application. Response: $SERVICE_APP_RESPONSE"
  else
    echo "Successfully created $service access application with ID: $SERVICE_APP_ID"
    
    # Create policy for admin email
    echo "Creating admin email policy for $service application..."
    
    POLICY_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/access/apps/$SERVICE_APP_ID/policies" \
      -H "Authorization: Bearer $CF_API_TOKEN" \
      -H "Content-Type: application/json" \
      --data "{
        \"name\": \"Allow Admin Email\",
        \"decision\": \"allow\",
        \"include\": [{
          \"email\": {
            \"email\": \"$ADMIN_EMAIL\"
          }
        }],
        \"require\": [],
        \"exclude\": [],
        \"precedence\": 1,
        \"purpose\": \"Admin Authentication\",
        \"session_duration\": \"24h\"
      }")
    
    # Check if policy creation was successful
    POLICY_SUCCESS=$(echo $POLICY_RESPONSE | jq -r '.success')
    
    if [ "$POLICY_SUCCESS" == "true" ]; then
      POLICY_ID=$(echo $POLICY_RESPONSE | jq -r '.result.id')
      echo "Admin email policy for $service created successfully with ID: $POLICY_ID"
    else
      ERROR_MSG=$(echo $POLICY_RESPONSE | jq -r '.errors[0].message')
      echo "Error creating admin email policy for $service: $ERROR_MSG"
    fi
  fi
done

# 2. Create specific access application for Gitea
echo "Creating access application for gitea.$CF_DOMAIN..."
GITEA_APP_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/access/apps" \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data "{
    \"name\": \"Gitea $CF_DOMAIN\",
    \"domain\": \"gitea.$CF_DOMAIN\",
    \"type\": \"self_hosted\",
    \"app_launcher_visible\": true,
    \"skip_interstitial\": true
  }")

# Extract the application ID from the response
GITEA_APP_ID=$(echo $GITEA_APP_RESPONSE | jq -r '.result.id')

if [ -z "$GITEA_APP_ID" ] || [ "$GITEA_APP_ID" == "null" ]; then
  echo "Error creating Gitea access application. Response: $GITEA_APP_RESPONSE"
else
  echo "Successfully created Gitea access application with ID: $GITEA_APP_ID"
  
  # Create bypass policy for everyone - Updated format
  echo "Creating bypass policy for Gitea application..."
  
  POLICY_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/access/apps/$GITEA_APP_ID/policies" \
    -H "Authorization: Bearer $CF_API_TOKEN" \
    -H "Content-Type: application/json" \
    --data "{
      \"name\": \"Bypass for Everyone\",
      \"decision\": \"bypass\",
      \"include\": [{
        \"everyone\": {}
      }],
      \"require\": [],
      \"exclude\": []
    }")
  
  # Check if policy creation was successful
  POLICY_SUCCESS=$(echo $POLICY_RESPONSE | jq -r '.success')
  
  if [ "$POLICY_SUCCESS" == "true" ]; then
    POLICY_ID=$(echo $POLICY_RESPONSE | jq -r '.result.id')
    echo "Bypass policy for Gitea created successfully with ID: $POLICY_ID"
  else
    ERROR_MSG=$(echo $POLICY_RESPONSE | jq -r '.errors[0].message')
    echo "Error creating bypass policy for Gitea: $ERROR_MSG"
    echo "Full response: $POLICY_RESPONSE"
  fi
fi

echo "Cloudflare Access applications setup complete."
