#!/usr/bin/env bash
# templates.sh - Project templates for wizard

# Get template name
get_template_name() {
  local template="$1"
  
  case "$template" in
  saas) echo "SaaS Application" ;;
  ecommerce) echo "E-commerce Platform" ;;
  blog) echo "Blog/CMS" ;;
  api) echo "API Backend" ;;
  mobile) echo "Mobile Backend" ;;
  custom) echo "Custom Configuration" ;;
  *) echo "Unknown" ;;
  esac
}

# Get template services
get_template_services() {
  local template="$1"
  local required_var="$2"
  local optional_var="$3"
  
  case "$template" in
  saas)
    eval "${required_var}=(\"PostgreSQL\" \"Redis\" \"Authentication\")"
    eval "${optional_var}=(\"MinIO Storage\" \"Email Service\" \"Search\" \"Admin UI\" \"Functions\" \"Dashboard\")"
    ;;
  ecommerce)
    eval "${required_var}=(\"PostgreSQL\" \"Redis\" \"MinIO Storage\" \"Search\")"
    eval "${optional_var}=(\"RabbitMQ\" \"Email Service\" \"Admin UI\" \"Dashboard\" \"Functions\")"
    ;;
  blog)
    eval "${required_var}=(\"PostgreSQL\" \"Search\")"
    eval "${optional_var}=(\"Redis\" \"MinIO Storage\" \"Email Service\" \"Admin UI\")"
    ;;
  api)
    eval "${required_var}=(\"PostgreSQL\" \"Redis\")"
    eval "${optional_var}=(\"RabbitMQ\" \"MinIO Storage\" \"Email Service\" \"Monitoring\")"
    ;;
  mobile)
    eval "${required_var}=(\"PostgreSQL\" \"Redis\" \"Authentication\")"
    eval "${optional_var}=(\"MinIO Storage\" \"Push Notifications\" \"Functions\" \"WebSockets\")"
    ;;
  custom)
    eval "${required_var}=(\"PostgreSQL\")"
    eval "${optional_var}=(\"Redis\" \"MinIO Storage\" \"Search\" \"Email Service\" \"RabbitMQ\" \"Admin UI\" \"Functions\" \"Dashboard\")"
    ;;
  esac
}

# Generate .env.local from template
generate_env_from_template() {
  local template="$1"
  local project_name="$2"
  local base_domain="$3"
  local db_name="$4"
  shift 4
  local services=("$@")
  
  # Start with base configuration
  cat > .env.local << EOF
# nself Configuration - Generated by Wizard
# Project: $project_name
# Template: $(get_template_name "$template")
# Generated: $(date)

# ====================================================================
# CORE CONFIGURATION
# ====================================================================

# Project name (used for container names)
PROJECT_NAME=$project_name

# Base domain for all services
BASE_DOMAIN=$base_domain

# Environment
ENVIRONMENT=development

# ====================================================================
# DATABASE CONFIGURATION
# ====================================================================

# PostgreSQL settings
POSTGRES_DB=$db_name
POSTGRES_USER=${project_name}_user
POSTGRES_PASSWORD=localpass123
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_VERSION=15-alpine

EOF

  # Add Redis if selected
  # Check if Redis is in services array
  local has_redis=false
  for service in "${services[@]}"; do
    if [[ "$service" == "Redis" ]]; then
      has_redis=true
      break
    fi
  done
  if [[ "$has_redis" == "true" ]]; then
    cat >> .env.local << EOF
# ====================================================================
# REDIS CONFIGURATION
# ====================================================================

REDIS_ENABLED=true
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_VERSION=7-alpine

EOF
  fi

  # Add MinIO if selected
  # Check if MinIO Storage is in services array
  local has_minio=false
  for service in "${services[@]}"; do
    if [[ "$service" == "MinIO Storage" ]]; then
      has_minio=true
      break
    fi
  done
  if [[ "$has_minio" == "true" ]]; then
    cat >> .env.local << EOF
# ====================================================================
# STORAGE CONFIGURATION
# ====================================================================

MINIO_ENABLED=true
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=minioadmin
MINIO_DEFAULT_BUCKETS=uploads,avatars,documents
MINIO_PORT=9000
MINIO_CONSOLE_PORT=9001

EOF
  fi

  # Add Search if selected
  # Check if Search is in services array
  local has_search=false
  for service in "${services[@]}"; do
    if [[ "$service" == "Search" ]]; then
      has_search=true
      break
    fi
  done
  if [[ "$has_search" == "true" ]]; then
    cat >> .env.local << EOF
# ====================================================================
# SEARCH CONFIGURATION
# ====================================================================

SEARCH_ENABLED=true
SEARCH_ENGINE=meilisearch
SEARCH_HOST=search
SEARCH_PORT=7700
SEARCH_API_KEY=$(openssl rand -hex 32)

EOF
  fi

  # Add Email if selected
  # Check if Email Service is in services array
  local has_email=false
  for service in "${services[@]}"; do
    if [[ "$service" == "Email Service" ]]; then
      has_email=true
      break
    fi
  done
  if [[ "$has_email" == "true" ]]; then
    cat >> .env.local << EOF
# ====================================================================
# EMAIL CONFIGURATION
# ====================================================================

EMAIL_ENABLED=true
EMAIL_PROVIDER=mailpit
EMAIL_FROM=${project_name}@${base_domain}
MAILPIT_PORT=1025
MAILPIT_UI_PORT=8025

EOF
  fi

  # Add RabbitMQ if selected
  # Check if RabbitMQ is in services array
  local has_rabbitmq=false
  for service in "${services[@]}"; do
    if [[ "$service" == "RabbitMQ" ]]; then
      has_rabbitmq=true
      break
    fi
  done
  if [[ "$has_rabbitmq" == "true" ]]; then
    cat >> .env.local << EOF
# ====================================================================
# MESSAGE QUEUE CONFIGURATION
# ====================================================================

RABBITMQ_ENABLED=true
RABBITMQ_USER=rabbit
RABBITMQ_PASSWORD=localpass123
RABBITMQ_HOST=rabbitmq
RABBITMQ_PORT=5672
RABBITMQ_MANAGEMENT_PORT=15672

EOF
  fi

  # Add Admin UI if selected
  # Check if Admin UI is in services array
  local has_admin=false
  for service in "${services[@]}"; do
    if [[ "$service" == "Admin UI" ]]; then
      has_admin=true
      break
    fi
  done
  if [[ "$has_admin" == "true" ]]; then
    cat >> .env.local << EOF
# ====================================================================
# ADMIN UI CONFIGURATION
# ====================================================================

ADMIN_ENABLED=true
ADMIN_PORT=3100
ADMIN_ROUTE=admin.\${BASE_DOMAIN}
ADMIN_USERNAME=admin

EOF
  fi

  # Add Authentication (Hasura) if selected
  # Check if Authentication is in services array
  local has_auth=false
  for service in "${services[@]}"; do
    if [[ "$service" == "Authentication" ]]; then
      has_auth=true
      break
    fi
  done
  if [[ "$has_auth" == "true" ]]; then
    cat >> .env.local << EOF
# ====================================================================
# HASURA CONFIGURATION
# ====================================================================

HASURA_GRAPHQL_DATABASE_URL=postgresql://\${POSTGRES_USER}:\${POSTGRES_PASSWORD}@\${POSTGRES_HOST}:\${POSTGRES_PORT}/\${POSTGRES_DB}
HASURA_GRAPHQL_ADMIN_SECRET=localsecret123
HASURA_GRAPHQL_JWT_SECRET='{"type":"HS256","key":"your-256-bit-secret-key-here-minimum-32-chars"}'
HASURA_GRAPHQL_ENABLE_CONSOLE=true
HASURA_GRAPHQL_DEV_MODE=true
HASURA_PORT=8080
HASURA_ROUTE=api.\${BASE_DOMAIN}

# ====================================================================
# AUTHENTICATION CONFIGURATION
# ====================================================================

AUTH_ENABLED=true
AUTH_PORT=4000
AUTH_ROUTE=auth.\${BASE_DOMAIN}
AUTH_JWT_EXPIRES_IN=7d
AUTH_REFRESH_TOKEN_EXPIRES_IN=30d

EOF
  fi

  # Add SSL configuration
  cat >> .env.local << EOF
# ====================================================================
# SSL CONFIGURATION
# ====================================================================

SSL_MODE=local
SSL_EMAIL=admin@${base_domain}

# ====================================================================
# NGINX CONFIGURATION
# ====================================================================

NGINX_CLIENT_MAX_BODY_SIZE=100M
NGINX_PROXY_TIMEOUT=300
NGINX_WORKER_CONNECTIONS=1024

EOF
}

# Create environment-specific files
create_environment_file() {
  local env="$1"
  local project_name="$2"
  local base_domain="$3"
  
  case "$env" in
  staging)
    cat > .env.staging << EOF
# Staging Environment Configuration
# Extends: .env.local

ENVIRONMENT=staging
BASE_DOMAIN=staging.${base_domain}

# Use different database
POSTGRES_DB=${project_name}_staging

# Disable dev mode
HASURA_GRAPHQL_DEV_MODE=false
HASURA_GRAPHQL_ENABLE_CONSOLE=false

# Enable basic monitoring
MONITORING_ENABLED=true
EOF
    ;;
    
  production)
    cat > .env.prod << EOF
# Production Environment Configuration
# DO NOT STORE SECRETS HERE - Use .env.secrets

ENVIRONMENT=production
BASE_DOMAIN=${base_domain}

# Database
POSTGRES_DB=${project_name}_prod
POSTGRES_VERSION=15

# Disable all dev features
HASURA_GRAPHQL_DEV_MODE=false
HASURA_GRAPHQL_ENABLE_CONSOLE=false
DEBUG=false

# Enable SSL
SSL_MODE=letsencrypt
SSL_EMAIL=admin@${base_domain}

# Enable monitoring
MONITORING_ENABLED=true
BACKUP_ENABLED=true
BACKUP_SCHEDULE="0 2 * * *"

# Security
ADMIN_2FA_ENABLED=true
RATE_LIMITING_ENABLED=true
EOF
    
    # Create .env.secrets template
    cat > .env.secrets << EOF
# Production Secrets - ADD TO .gitignore!
# These values override .env.prod

# Database passwords
POSTGRES_PASSWORD=CHANGE_ME_$(openssl rand -hex 16)

# Service passwords
REDIS_PASSWORD=CHANGE_ME_$(openssl rand -hex 16)
MINIO_ROOT_PASSWORD=CHANGE_ME_$(openssl rand -hex 16)
RABBITMQ_PASSWORD=CHANGE_ME_$(openssl rand -hex 16)

# API Keys
HASURA_GRAPHQL_ADMIN_SECRET=CHANGE_ME_$(openssl rand -hex 32)
HASURA_GRAPHQL_JWT_SECRET='{"type":"HS256","key":"CHANGE_ME_$(openssl rand -hex 32)"}'
SEARCH_API_KEY=CHANGE_ME_$(openssl rand -hex 32)
ADMIN_PASSWORD_HASH=CHANGE_ME_$(openssl rand -hex 32)
ADMIN_SECRET_KEY=CHANGE_ME_$(openssl rand -hex 32)

# External services
SMTP_PASSWORD=
AWS_SECRET_ACCESS_KEY=
STRIPE_SECRET_KEY=
EOF
    
    # Add to .gitignore
    if ! grep -q ".env.secrets" .gitignore 2>/dev/null; then
      echo ".env.secrets" >> .gitignore
    fi
    ;;
  esac
}

# Generate production secrets
generate_production_secrets() {
  log_info "Generating secure production passwords..."
  
  # Generate secure passwords
  local postgres_pass=$(openssl rand -base64 32)
  local redis_pass=$(openssl rand -base64 32)
  local minio_pass=$(openssl rand -base64 32)
  local rabbitmq_pass=$(openssl rand -base64 32)
  local hasura_secret=$(openssl rand -hex 32)
  local jwt_key=$(openssl rand -hex 32)
  local search_key=$(openssl rand -hex 32)
  local admin_pass=$(openssl rand -hex 32)
  local admin_key=$(openssl rand -hex 32)
  
  # Update .env.secrets with real passwords
  # Each password type needs its own replacement
  sed -i.bak "s/POSTGRES_PASSWORD=.*/POSTGRES_PASSWORD=$postgres_pass/" .env.secrets
  sed -i.bak "s/AUTH_DATABASE_PASSWORD=.*/AUTH_DATABASE_PASSWORD=$auth_pass/" .env.secrets
  sed -i.bak "s/STORAGE_DATABASE_PASSWORD=.*/STORAGE_DATABASE_PASSWORD=$storage_pass/" .env.secrets
  sed -i.bak "s/HASURA_ADMIN_SECRET=.*/HASURA_ADMIN_SECRET=$hasura_secret/" .env.secrets
  sed -i.bak "s/JWT_KEY=.*/JWT_KEY=$jwt_key/" .env.secrets
  sed -i.bak "s/SEARCH_API_KEY=.*/SEARCH_API_KEY=$search_key/" .env.secrets
  sed -i.bak "s/ADMIN_PASSWORD_HASH=.*/ADMIN_PASSWORD_HASH=$admin_pass/" .env.secrets
  sed -i.bak "s/ADMIN_SECRET_KEY=.*/ADMIN_SECRET_KEY=$admin_key/" .env.secrets
  
  # Handle other common secrets
  if grep -q "REDIS_PASSWORD=" .env.secrets; then
    sed -i.bak "s/REDIS_PASSWORD=.*/REDIS_PASSWORD=$redis_pass/" .env.secrets
  fi
  if grep -q "RABBITMQ_PASSWORD=" .env.secrets; then
    sed -i.bak "s/RABBITMQ_PASSWORD=.*/RABBITMQ_PASSWORD=$rabbitmq_pass/" .env.secrets
  fi
  
  # Clean up backup files
  rm -f .env.secrets.bak
  
  log_success "Generated secure passwords in .env.secrets"
  log_warning "Keep .env.secrets secure and never commit to git!"
}

# Export functions
export -f get_template_name
export -f get_template_services
export -f generate_env_from_template
export -f create_environment_file
export -f generate_production_secrets