#!/bin/bash
#
# DSS - Secret Scanner
# Non-destructive scan for potential exposed secrets
# Outputs JSON with risk report (no actual secret values)
#

set -e

PROJECT_PATH="${1:-.}"

# Patterns to detect (regex)
SECRET_PATTERNS=(
  "password\s*[:=]\s*['\"][^'\"]+['\"]"
  "api[_-]?key\s*[:=]\s*['\"][^'\"]+['\"]"
  "secret[_-]?key\s*[:=]\s*['\"][^'\"]+['\"]"
  "access[_-]?token\s*[:=]\s*['\"][^'\"]+['\"]"
  "private[_-]?key\s*[:=]\s*['\"][^'\"]+['\"]"
  "aws[_-]?access"
  "AKIA[0-9A-Z]{16}"
  "ghp_[a-zA-Z0-9]{36}"
  "sk-[a-zA-Z0-9]{48}"
)

# Files to ignore
IGNORE_DIRS="node_modules|\.git|dist|build|__pycache__|\.next|venv"

# Initialize results
declare -a findings

scan_for_secrets() {
  local pattern="$1"
  local results

  results=$(grep -rEil "$pattern" "$PROJECT_PATH" \
    --include="*.js" --include="*.ts" --include="*.py" \
    --include="*.json" --include="*.yaml" --include="*.yml" \
    --include="*.env*" --include="*.config.*" \
    2>/dev/null | grep -vE "$IGNORE_DIRS" | head -20 || true)

  if [[ -n "$results" ]]; then
    while IFS= read -r file; do
      if [[ -n "$file" ]]; then
        # Get line count without revealing content
        local count=$(grep -cEi "$pattern" "$file" 2>/dev/null || echo 0)
        findings+=("{\"file\":\"${file#$PROJECT_PATH/}\",\"pattern\":\"${pattern:0:30}...\",\"matches\":$count}")
      fi
    done <<< "$results"
  fi
}

# Check for common secret files
check_secret_files() {
  local risky_files=(
    ".env"
    ".env.local"
    ".env.production"
    "credentials.json"
    "secrets.json"
    "config/secrets.yml"
    ".aws/credentials"
    "id_rsa"
    "id_ed25519"
    "*.pem"
    "*.key"
  )

  for pattern in "${risky_files[@]}"; do
    local found=$(find "$PROJECT_PATH" -name "$pattern" -type f ! -path "*/$IGNORE_DIRS/*" 2>/dev/null | head -5)
    if [[ -n "$found" ]]; then
      while IFS= read -r file; do
        if [[ -n "$file" ]]; then
          # Check if file is in .gitignore
          local in_gitignore="false"
          if [[ -f "$PROJECT_PATH/.gitignore" ]]; then
            grep -q "$(basename "$file")" "$PROJECT_PATH/.gitignore" 2>/dev/null && in_gitignore="true"
          fi
          findings+=("{\"file\":\"${file#$PROJECT_PATH/}\",\"type\":\"risky_file\",\"in_gitignore\":$in_gitignore}")
        fi
      done <<< "$found"
    fi
  done
}

# Run scans
for pattern in "${SECRET_PATTERNS[@]}"; do
  scan_for_secrets "$pattern"
done

check_secret_files

# Calculate risk score
total_findings=${#findings[@]}
risk_score="low"
[[ $total_findings -gt 5 ]] && risk_score="medium"
[[ $total_findings -gt 15 ]] && risk_score="high"
[[ $total_findings -gt 30 ]] && risk_score="critical"

# Output JSON
joined=$(IFS=,; echo "${findings[*]}")

cat <<EOF
{
  "scan_type": "secrets",
  "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "project_path": "$PROJECT_PATH",
  "risk_level": "$risk_score",
  "total_findings": $total_findings,
  "findings": [${joined:-}],
  "recommendations": [
    "Review all findings and remove hardcoded secrets",
    "Use environment variables for sensitive data",
    "Add secret files to .gitignore",
    "Consider using a secrets manager"
  ]
}
EOF
