#!/bin/bash
# Pre-deployment audit sink gate script
# Verifies the write-once audit sink is reachable and writable

set -e

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Default values
ENV="staging"
TIMEOUT=10
AUDIT_SINK_HOST=""
AUDIT_SINK_PORT=""

# Parse arguments
while [[ $# -gt 0 ]]; do
  case $1 in
    --env)
      ENV="$2"
      shift 2
      ;;
    --timeout)
      TIMEOUT="$2"
      shift 2
      ;;
    --host)
      AUDIT_SINK_HOST="$2"
      shift 2
      ;;
    --port)
      AUDIT_SINK_PORT="$2"
      shift 2
      ;;
    --help)
      echo "Usage: $0 [OPTIONS]"
      echo ""
      echo "Options:"
      echo "  --env ENV         Environment (staging|prod) [default: staging]"
      echo "  --timeout SECONDS Timeout in seconds [default: 10]"
      echo "  --host HOST       Audit sink host (auto-detected if not set)"
      echo "  --port PORT       Audit sink port (auto-detected if not set)"
      echo "  --help            Show this help message"
      exit 0
      ;;
    *)
      echo "Unknown option: $1"
      exit 1
      ;;
  esac
done

# Auto-detect audit sink based on environment
if [ -z "$AUDIT_SINK_HOST" ]; then
  case $ENV in
    staging)
      AUDIT_SINK_HOST="ml-staging-audit-sink"
      AUDIT_SINK_PORT="6379"
      ;;
    prod)
      AUDIT_SINK_HOST="ml-prod-audit-sink"
      AUDIT_SINK_PORT="6379"
      ;;
    *)
      echo -e "${RED}Error: Unknown environment '$ENV'${NC}"
      exit 1
      ;;
  esac
fi

echo "Checking audit sink for environment: $ENV"
echo "Host: $AUDIT_SINK_HOST"
echo "Port: $AUDIT_SINK_PORT"
echo "Timeout: ${TIMEOUT}s"

# Check if we can reach the audit sink
echo ""
echo "Step 1: Checking network reachability..."

if command -v nc &> /dev/null; then
  if timeout $TIMEOUT nc -z "$AUDIT_SINK_HOST" "$AUDIT_SINK_PORT" 2>/dev/null; then
    echo -e "${GREEN}✓ Audit sink is reachable on port $AUDIT_SINK_PORT${NC}"
  else
    echo -e "${RED}✗ Audit sink is NOT reachable on $AUDIT_SINK_HOST:$AUDIT_SINK_PORT${NC}"
    echo "This is a HARD STOP for HIPAA deployments."
    exit 1
  fi
elif command -v redis-cli &> /dev/null; then
  # Try to ping via redis-cli if available
  if timeout $TIMEOUT redis-cli -h "$AUDIT_SINK_HOST" -p "$AUDIT_SINK_PORT" ping 2>/dev/null | grep -q "PONG"; then
    echo -e "${GREEN}✓ Audit sink responded to Redis ping${NC}"
  else
    echo -e "${RED}✗ Audit sink did not respond to Redis ping${NC}"
    echo "This is a HARD STOP for HIPAA deployments."
    exit 1
  fi
else
  echo -e "${YELLOW}⚠ Neither nc nor redis-cli available - skipping reachability check${NC}"
  echo "For production, ensure one of these tools is installed."
fi

# Check if audit sink is writable (append-only test)
echo ""
echo "Step 2: Checking write capability..."

# For a proper audit sink, we should be able to write but not modify
# This is typically implemented with Redis append-only file (AOF) persistence
# and restricted commands

if command -v docker &> /dev/null; then
  # Check if the audit sink container is running
  CONTAINER_NAME="ml-${ENV}-audit-sink"
  
  if docker ps | grep -q "$CONTAINER_NAME"; then
    echo -e "${GREEN}✓ Audit sink container '$CONTAINER_NAME' is running${NC}"
    
    # Test write capability
    TEST_KEY="audit_test_$(date +%s)"
    TEST_VALUE="test_$(uuidgen 2>/dev/null || echo $RANDOM)"
    
    if docker exec "$CONTAINER_NAME" redis-cli SET "$TEST_KEY" "$TEST_VALUE" EX 60 > /dev/null 2>&1; then
      echo -e "${GREEN}✓ Audit sink accepts writes${NC}"
      
      # Verify we can read it back
      READ_VALUE=$(docker exec "$CONTAINER_NAME" redis-cli GET "$TEST_KEY" 2>/dev/null)
      if [ "$READ_VALUE" = "$TEST_VALUE" ]; then
        echo -e "${GREEN}✓ Audit sink read-after-write successful${NC}"
      else
        echo -e "${YELLOW}⚠ Audit sink read-after-write mismatch${NC}"
      fi
      
      # Clean up
      docker exec "$CONTAINER_NAME" redis-cli DEL "$TEST_KEY" > /dev/null 2>&1 || true
    else
      echo -e "${RED}✗ Audit sink does not accept writes${NC}"
      exit 1
    fi
  else
    echo -e "${YELLOW}⚠ Audit sink container '$CONTAINER_NAME' not found${NC}"
    echo "Container may not be running or may have a different name."
  fi
else
  echo -e "${YELLOW}⚠ Docker not available - skipping container check${NC}"
fi

# Final summary
echo ""
echo "==================================="
echo "Audit Sink Check Summary"
echo "==================================="
echo -e "${GREEN}✓ Audit sink is reachable and writable${NC}"
echo ""
echo "Deployment can proceed."
echo "Note: This check does NOT verify:"
echo "  - Append-only configuration"
echo "  - Log retention policies"
echo "  - Chain integrity"
echo "  - Tamper resistance"
echo ""
echo "These must be verified separately for full HIPAA compliance."

exit 0
