#!/bin/bash
# MCP-ZERO Docker Configuration Generator
# Creates Docker files for containerized deployment of MCP-ZERO
# Implements offline-first resilience pattern with proper fallback

# Generate the main docker-compose.yaml file
generate_docker_compose() {
  local docker_dir="$1"
  local api_port="$2"
  local dashboard_port="$3"
  local rpc_port="$4"
  local offline_mode="$5"
  
  echo "Generating docker-compose.yaml file..."
  
  cat > "${docker_dir}/docker-compose.yaml" << EOF
version: '3.8'

services:
  # API Server
  mcp-api:
    build:
      context: .
      dockerfile: docker/Dockerfile.api
    ports:
      - "${api_port}:${api_port}"
    volumes:
      - ./.mcp/config:/app/config
      - ./.mcp/db:/app/db
      - ./.mcp/locks:/app/locks
      - ./.mcp/certs:/app/certs
    environment:
      - MCP_CONFIG_PATH=/app/config/api.json
      - MCP_API_PORT=${api_port}
      - MCP_OFFLINE_MODE=$([ "$offline_mode" -eq 1 ] && echo "true" || echo "false")
    restart: unless-stopped
    networks:
      - mcp-network

  # Dashboard UI
  mcp-dashboard:
    build:
      context: .
      dockerfile: docker/Dockerfile.dashboard
    ports:
      - "${dashboard_port}:${dashboard_port}"
    volumes:
      - ./.mcp/config:/app/config
    environment:
      - MCP_CONFIG_PATH=/app/config/dashboard.json
      - MCP_DASHBOARD_PORT=${dashboard_port}
      - MCP_API_URL=http://mcp-api:${api_port}
    restart: unless-stopped
    depends_on:
      - mcp-api
    networks:
      - mcp-network

  # RPC Server
  mcp-rpc:
    build:
      context: .
      dockerfile: docker/Dockerfile.rpc
    ports:
      - "${rpc_port}:${rpc_port}"
    volumes:
      - ./.mcp/config:/app/config
      - ./.mcp/db:/app/db
      - ./.mcp/locks:/app/locks
    environment:
      - MCP_CONFIG_PATH=/app/config/rpc.json
      - MCP_RPC_PORT=${rpc_port}
      - MCP_OFFLINE_MODE=$([ "$offline_mode" -eq 1 ] && echo "true" || echo "false")
    restart: unless-stopped
    networks:
      - mcp-network

  # Monitoring Service
  mcp-monitoring:
    build:
      context: .
      dockerfile: docker/Dockerfile.monitoring
    volumes:
      - ./.mcp/config:/app/config
      - ./.mcp/db:/app/db
      - ./logs:/app/logs
    environment:
      - MCP_CONFIG_PATH=/app/config/monitoring.json
      - MCP_OFFLINE_MODE=$([ "$offline_mode" -eq 1 ] && echo "true" || echo "false")
    restart: unless-stopped
    depends_on:
      - mcp-api
    networks:
      - mcp-network

networks:
  mcp-network:
    driver: bridge
EOF

  echo "docker-compose.yaml generated successfully"
}

# Generate Dockerfile for API service
generate_api_dockerfile() {
  local docker_dir="$1"
  
  echo "Generating API Dockerfile..."
  
  cat > "${docker_dir}/Dockerfile.api" << EOF
FROM golang:1.18-alpine AS builder

WORKDIR /build

# Copy go mod files first for better caching
COPY go.mod go.sum ./
RUN go mod download

# Copy source code
COPY ./src/api ./src/api
COPY ./src/common ./src/common

# Build with offline-first resilience flags
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags="-w -s" -o mcp-api ./src/api

# Create a minimal production image
FROM alpine:3.15

WORKDIR /app

# Install dependencies for offline resilience
RUN apk --no-cache add ca-certificates sqlite tzdata

# Copy built binary
COPY --from=builder /build/mcp-api .

# Create directories for volumes
RUN mkdir -p /app/config /app/db /app/locks /app/certs

# Offline first resilience check script
COPY ./src/api/scripts/offline_check.sh /app/offline_check.sh
RUN chmod +x /app/offline_check.sh

# Set entrypoint with connection check
ENTRYPOINT ["/bin/sh", "-c", "/app/offline_check.sh && /app/mcp-api"]
EOF

  echo "API Dockerfile generated successfully"
}

# Generate Dockerfile for Dashboard UI
generate_dashboard_dockerfile() {
  local docker_dir="$1"
  
  echo "Generating Dashboard Dockerfile..."
  
  cat > "${docker_dir}/Dockerfile.dashboard" << EOF
FROM node:16-alpine as builder

WORKDIR /build

# Copy package files
COPY ./src/dashboard/ui/package.json ./src/dashboard/ui/package-lock.json ./

# Install dependencies
RUN npm ci

# Copy source code
COPY ./src/dashboard/ui ./

# Build the dashboard
RUN npm run build

# Create a minimal production image
FROM nginx:alpine

# Copy built static files
COPY --from=builder /build/dist /usr/share/nginx/html

# Copy nginx configuration
COPY ./src/dashboard/ui/nginx.conf /etc/nginx/conf.d/default.conf

# Copy offline-first check script
COPY ./src/dashboard/ui/scripts/offline_check.sh /usr/share/nginx/
RUN chmod +x /usr/share/nginx/offline_check.sh

# Run with offline check first
ENTRYPOINT ["/bin/sh", "-c", "/usr/share/nginx/offline_check.sh && nginx -g 'daemon off;'"]
EOF

  echo "Dashboard Dockerfile generated successfully"
}

# Generate Dockerfile for RPC service
generate_rpc_dockerfile() {
  local docker_dir="$1"
  
  echo "Generating RPC Dockerfile..."
  
  cat > "${docker_dir}/Dockerfile.rpc" << EOF
FROM golang:1.18-alpine AS builder

WORKDIR /build

# Copy go mod files first for better caching
COPY go.mod go.sum ./
RUN go mod download

# Copy source code
COPY ./src/rpc ./src/rpc
COPY ./src/common ./src/common

# Build with offline-first resilience flags
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags="-w -s" -o mcp-rpc ./src/rpc

# Create a minimal production image
FROM alpine:3.15

WORKDIR /app

# Install dependencies for offline resilience
RUN apk --no-cache add ca-certificates sqlite tzdata

# Copy built binary
COPY --from=builder /build/mcp-rpc .

# Create directories for volumes
RUN mkdir -p /app/config /app/db /app/locks

# Offline first resilience check script
COPY ./src/rpc/scripts/offline_check.sh /app/offline_check.sh
RUN chmod +x /app/offline_check.sh

# Set entrypoint with connection check
ENTRYPOINT ["/bin/sh", "-c", "/app/offline_check.sh && /app/mcp-rpc"]
EOF

  echo "RPC Dockerfile generated successfully"
}

# Generate Dockerfile for Monitoring service
generate_monitoring_dockerfile() {
  local docker_dir="$1"
  
  echo "Generating Monitoring Dockerfile..."
  
  cat > "${docker_dir}/Dockerfile.monitoring" << EOF
FROM golang:1.18-alpine AS builder

WORKDIR /build

# Copy go mod files first for better caching
COPY go.mod go.sum ./
RUN go mod download

# Copy source code
COPY ./src/monitoring ./src/monitoring
COPY ./src/common ./src/common

# Build with offline-first resilience flags
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags="-w -s" -o mcp-monitoring ./src/monitoring

# Create a minimal production image
FROM alpine:3.15

WORKDIR /app

# Install dependencies for offline resilience
RUN apk --no-cache add ca-certificates sqlite tzdata

# Copy built binary
COPY --from=builder /build/mcp-monitoring .

# Create directories for volumes
RUN mkdir -p /app/config /app/db /app/logs

# Create offline check script
RUN echo '#!/bin/sh\n\
if [ -f /app/locks/offline.lock ]; then\n\
  echo "Offline lock file detected, starting in offline mode"\n\
  export MCP_OFFLINE_MODE=true\n\
fi\n\
exit 0' > /app/offline_check.sh && chmod +x /app/offline_check.sh

# Set entrypoint with connection check
ENTRYPOINT ["/bin/sh", "-c", "/app/offline_check.sh && /app/mcp-monitoring"]
EOF

  echo "Monitoring Dockerfile generated successfully"
}

# Generate Docker environment file
generate_docker_env() {
  local docker_dir="$1"
  local api_port="$2"
  local dashboard_port="$3"
  local rpc_port="$4"
  local offline_mode="$5"
  
  echo "Generating .env file for docker-compose..."
  
  cat > "${docker_dir}/.env" << EOF
# MCP-ZERO Docker Environment Configuration
# Generated by burn folder script

# Service Ports
MCP_API_PORT=${api_port}
MCP_DASHBOARD_PORT=${dashboard_port}
MCP_RPC_PORT=${rpc_port}

# Offline Mode Configuration
MCP_OFFLINE_MODE=$([ "$offline_mode" -eq 1 ] && echo "true" || echo "false")

# Security Settings
MCP_API_KEYS=mcp-api-key-$(openssl rand -hex 8)

# Resource Limits
MCP_API_MEMORY_LIMIT=512m
MCP_DASHBOARD_MEMORY_LIMIT=256m
MCP_RPC_MEMORY_LIMIT=512m
MCP_MONITORING_MEMORY_LIMIT=256m
EOF

  echo ".env file generated successfully"
}

# Generate the offline check script
generate_offline_check_script() {
  local docker_dir="$1"
  
  echo "Generating offline check script..."
  
  mkdir -p "${docker_dir}/scripts"
  
  cat > "${docker_dir}/scripts/offline_check.sh" << EOF
#!/bin/sh
# MCP-ZERO offline first resilience script
# Implements single connection attempt pattern

LOCK_FILE_PATH="/app/locks/offline.lock"
CONFIG_FILE="/app/config/offline.json"

# Check if offline lock file exists
if [ -f "\${LOCK_FILE_PATH}" ]; then
  echo "Offline lock file detected, starting in permanent offline mode"
  export MCP_OFFLINE_MODE=true
  exit 0
fi

# Check if offline mode is configured
if [ -f "\${CONFIG_FILE}" ]; then
  OFFLINE_CONFIGURED=\$(grep -o '"enabled": true' "\${CONFIG_FILE}" | wc -l)
  if [ "\${OFFLINE_CONFIGURED}" -gt 0 ]; then
    echo "Offline mode configured in settings, starting in offline mode"
    export MCP_OFFLINE_MODE=true
    exit 0
  fi
fi

# Try to connect to monitoring endpoint
if [ -n "\${MCP_MONITORING_ENDPOINT}" ]; then
  echo "Attempting connection to monitoring endpoint..."
  
  # Single connection attempt pattern
  if ! wget -q --spider --timeout=5 "\${MCP_MONITORING_ENDPOINT}/health" 2>/dev/null; then
    echo "Connection failed, creating offline lock file and switching to offline mode"
    
    # Create offline lock file with timestamp
    echo "{\"created_at\": \"\$(date -Iseconds)\", \"reason\": \"Connection attempt failed\", \"immutable\": true}" > "\${LOCK_FILE_PATH}"
    chmod 444 "\${LOCK_FILE_PATH}"
    
    export MCP_OFFLINE_MODE=true
  else
    echo "Connection successful, starting in online mode"
    export MCP_OFFLINE_MODE=false
  fi
fi

exit 0
EOF

  chmod +x "${docker_dir}/scripts/offline_check.sh"
  
  echo "Offline check script generated successfully"
}

# Generate all Docker files
generate_all_docker() {
  local docker_dir="$1"
  local api_port="$2"
  local dashboard_port="$3"
  local rpc_port="$4"
  local offline_mode="$5"
  
  # Create directories
  mkdir -p "${docker_dir}/scripts"
  mkdir -p "${docker_dir}/volumes"
  
  # Generate Docker files
  generate_docker_compose "${docker_dir}" "${api_port}" "${dashboard_port}" "${rpc_port}" "${offline_mode}"
  generate_api_dockerfile "${docker_dir}"
  generate_dashboard_dockerfile "${docker_dir}"
  generate_rpc_dockerfile "${docker_dir}"
  generate_monitoring_dockerfile "${docker_dir}"
  generate_docker_env "${docker_dir}" "${api_port}" "${dashboard_port}" "${rpc_port}" "${offline_mode}"
  generate_offline_check_script "${docker_dir}"
  
  echo "All Docker configuration files generated successfully"
}

# If script is executed directly, show usage
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
  echo "This script is intended to be sourced by burn.sh"
  echo "Usage: source $(basename "$0")"
fi
