#!/usr/bin/env bash
# =============================================================================
#  THE ANALYZER v1.0 — Autonomous Bug Bounty Analysis Engine
#  Authorized Bug Bounty Use Only
# =============================================================================

set -euo pipefail

# === Setup ===
# Set up path, resolving symlinks
__ANALYZER_SRC="${BASH_SOURCE[0]}"
if command -v readlink &>/dev/null; then
  while [ -h "$__ANALYZER_SRC" ]; do
    __ANALYZER_SRC="$(readlink "$__ANALYZER_SRC")"
    [[ "$__ANALYZER_SRC" != /* ]] && __ANALYZER_SRC="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$__ANALYZER_SRC"
  done
fi
SCRIPT_DIR="$(cd "$(dirname "$__ANALYZER_SRC")" && pwd 2>/dev/null)" || SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
unset __ANALYZER_SRC
export ANALYZER_DIR="$SCRIPT_DIR"
export VECTORS_DIR="$ANALYZER_DIR/vectors"
export ENGINE_DIR="$ANALYZER_DIR/engine"
export LIB_DIR="$ANALYZER_DIR/lib"
export REPORTS_DIR="$ANALYZER_DIR/reports"

# Source core
source "$LIB_DIR/colors.sh"
source "$LIB_DIR/utils.sh"
source "$ENGINE_DIR/discovery.sh"
source "$ENGINE_DIR/recon.sh"
source "$ENGINE_DIR/ollama-brain.sh"
source "$ENGINE_DIR/reporter.sh"

mkdir -p "$REPORTS_DIR"

# === Banner ===
show_banner() {
  clear
  echo -e "${BRIGHT_RED}"
  echo '    ████████╗██╗  ██╗███████╗     █████╗ ███╗   ██╗ █████╗ ██╗  ██╗███████╗   '
  echo '    ╚══██╔══╝██║  ██║██╔════╝    ██╔══██╗████╗  ██║██╔══██╗██║  ██║╚══███╔╝   '
  echo '       ██║   ███████║█████╗      ███████║██╔██╗ ██║███████║███████║  ███╔╝    '
  echo '       ██║   ██╔══██║██╔══╝      ██╔══██║██║╚██╗██║██╔══██║██╔══██║ ███╔╝     '
  echo '       ██║   ██║  ██║███████╗    ██║  ██║██║ ╚████║██║  ██║██║  ██║███████╗   '
  echo '       ╚═╝   ╚═╝  ╚═╝╚══════╝    ╚═╝  ╚═╝╚═╝  ╚═══╝╚═╝  ╚═╝╚═╝  ╚═╝╚══════╝   '
  echo ''
  echo -e "  ${BRIGHT_YELLOW}Autonomous Bug Bounty Analyzer v2.0${NC}"
  echo -e "  ${DIM}Authorized Testing Only${NC}"
  echo ''
}

# === Interactive mode ===
interactive_mode() {
  show_banner
  
  echo -e "  ${BOLD}${BRIGHT_CYAN}Welcome to The Analyzer${NC}"
  separator
  echo ''
  echo -e "  ${GREEN}1${NC}. Quick Scan  — Fast recon + auto-vector selection"
  echo -e "  ${GREEN}2${NC}. Deep Scan   — Full recon, all vectors, exhaustive"
  echo -e "  ${GREEN}3${NC}. Custom Scan — Pick your own vectors"
  echo -e "  ${GREEN}4${NC}. List Vectors — Show all 30 attack vectors"
  echo -e "  ${GREEN}5${NC}. View Reports — Browse past results"
  echo -e "  ${DIM}q${NC}. Quit"
  echo ''
  
  read -p "  ${ICON_ARROW} Choose mode [1]: " mode
  mode="${mode:-1}"
  
  echo ''
  read -p "  ${ICON_ARROW} Target URL (e.g., https://example.com): " target
  
  # Validate
  if [ -z "$target" ]; then
    print_error "Target URL required!"
    exit 1
  fi
  
  # Add protocol if missing
  [[ "$target" != http* ]] && target="https://${target}"
  
  echo ''
  print_info "Target set: ${BOLD}$target${NC}"
  echo ''
  
  case "$mode" in
    1) quick_scan "$target" ;;
    2) deep_scan "$target" ;;
    3) custom_scan "$target" ;;
    4) list_vectors && exit 0 ;;
    5) view_reports && exit 0 ;;
    *) quick_scan "$target" ;;
  esac
}

# === Quick Scan ===
quick_scan() {
  local target="$1"
  local report=$(init_report "$target")
  local total_findings=0
  local total_vulns=0
  
  echo -e "\n${BRIGHT_CYAN}${BOLD}═══ QUICK SCAN MODE ═══${NC}\n"
  
  # Step 1: Check connectivity
  print_step 1 5 "Checking target..."
  if ! target_alive "$target"; then
    print_error "Target unreachable!"
    exit 1
  fi
  print_ok "Target is alive"
  
  # Step 2: Discovery — find real URLs, forms, params to attack
  print_step 2 5 "Discovering attack surface"
  discover_target "$target"
  
  # Step 3: Recon
  print_step 3 5 "Reconnaissance"
  recon_target "$target" "$report"
  
  # Step 4: Ollama decides
  print_step 4 5 "Ollama brain selecting vectors"
  local decision=$(ollama_decide "$target")
  echo ''
  echo -e "${MAGENTA}${ICON_BRAIN} Ollama's Strategy:${NC}"
  echo "$decision" | head -20
  
  local selected=$(parse_decision "$decision")
  
  if [ -z "$selected" ]; then
    print_warn "Ollama didn't pick specific vectors. Running default set."
    selected="21 1 2 3 4"  # nuclei + sqli + xss + lfi + cmdi
  fi
  
  echo ''
  print_info "Running vectors: $(echo $selected | tr '\n' ' ')"
  echo ''
  
  # Step 5: Run vectors
  print_step 5 5 "Executing attack vectors"
  run_vectors "$target" "$report" $selected
  
  # Generate final report
  total_findings=$(ls "$REPORTS_DIR"/.finding_*.txt 2>/dev/null | wc -l | tr -d ' ')
  total_vulns=$total_findings
  generate_report "$target" "$report" "$total_vulns"
  html_report "$report" > /dev/null
  
  cleanup_findings
}

# === Deep Scan ===
deep_scan() {
  local target="$1"
  local report=$(init_report "$target")
  
  echo -e "\n${BRIGHT_RED}${BOLD}═══ DEEP SCAN MODE — ALL VECTORS ═══${NC}\n"
  
  # Step 1: Connectivity
  print_step 1 3 "Checking target..."
  if ! target_alive "$target"; then
    print_error "Target unreachable!"
    exit 1
  fi
  print_ok "Target is alive"
  
  # Step 2: Full recon
  print_step 2 3 "Deep reconnaissance"
  recon_target "$target" "$report"
  
  # Step 3: Run ALL vectors
  print_step 3 3 "Running all 30 attack vectors"
  local all_vectors=$(seq 1 30 | tr '\n' ' ')
  run_vectors "$target" "$report" $all_vectors
  
  # Generate report
  local total_findings=$(ls "$REPORTS_DIR"/.finding_*.txt 2>/dev/null | wc -l | tr -d ' ')
  generate_report "$target" "$report" "$total_findings"
  html_report "$report" > /dev/null
  
  cleanup_findings
}

# === Custom Scan ===
custom_scan() {
  local target="$1"
  local report=$(init_report "$target")
  
  echo -e "\n${BRIGHT_BLUE}${BOLD}═══ CUSTOM SCAN MODE ═══${NC}\n"
  
  echo -e "Available vectors:"
  list_vectors
  echo ''
  read -p "  ${ICON_ARROW} Vector numbers (space-separated, e.g., 1 3 5 12): " vector_input
  
  local selected=${vector_input:-"1 2 3 4 5"}
  
  print_step 1 3 "Checking target..."
  if ! target_alive "$target"; then
    print_error "Target unreachable!"
    exit 1
  fi
  print_ok "Target is alive"
  
  print_step 2 3 "Quick recon"
  recon_target "$target" "$report"
  
  print_step 3 3 "Running selected vectors"
  run_vectors "$target" "$report" $selected
  
  local total_findings=$(ls "$REPORTS_DIR"/.finding_*.txt 2>/dev/null | wc -l | tr -d ' ')
  generate_report "$target" "$report" "$total_findings"
  html_report "$report" > /dev/null
  
  cleanup_findings
}

# === Run Vectors ===
run_vectors() {
  local target="$1"
  local report="$2"
  shift 2
  local vectors=("$@")
  
  local total=${#vectors[@]}
  local current=0
  local total_findings=0
  
  for num in "${vectors[@]}"; do
    num=$(echo "$num" | xargs)  # trim
    [ -z "$num" ] && continue
    
    current=$((current + 1))
    
    # Find the vector file
    local vf="$VECTORS_DIR/$(printf "%02d" $num)-"*.sh
    if [ ! -f "$vf" ]; then
      # Try without the glob
      vf=""
      for f in "$VECTORS_DIR"/$(printf "%02d" $num)-*.sh; do
        [ -f "$f" ] && vf="$f" && break
      done
    fi
    
    if [ ! -f "$vf" ] || [ -z "$vf" ]; then
      print_skip "Vector $num — file not found"
      continue
    fi
    
    local vec_name=$(basename "$vf" .sh | sed 's/^[0-9]*-//')
    
    echo ''
    separator
    echo -e "  ${CYAN}[${current}/${total}]${NC} ${BOLD}${vec_name}${NC}"
    separator
    
    # Source and run
    source "$vf"
    
    # The vector function name follows pattern: vector_<shortname>
    local func_name="vector_$(echo "$vec_name" | tr '-' '_' | sed 's/injection/inj/;s/traversal/trav/;s/redirect/oredir/;s/condition/race/;s/exposure/gitex/;s/misconfiguration/cors/;s/abuse/apiab/;s/upload/fileup/;s/fil/backup/')"
    
    # Map vector names to function names
    case $num in
      1) func_name="vector_sqli_v2" ;;
      2) func_name="vector_xss_v2" ;;
      3) func_name="vector_lfi_v2" ;;
      4) func_name="vector_cmdi" ;;
      5) func_name="vector_ssrf" ;;
      6) func_name="vector_oredir" ;;
      7) func_name="vector_dtrav" ;;
      8) func_name="vector_ssti" ;;
      9) func_name="vector_xxe" ;;
      10) func_name="vector_idor" ;;
      11) func_name="vector_csrf" ;;
      12) func_name="vector_jwt" ;;
      13) func_name="vector_graphql" ;;
      14) func_name="vector_apiab" ;;
      15) func_name="vector_fileup" ;;
      16) func_name="vector_backup" ;;
      17) func_name="vector_gitex" ;;
      18) func_name="vector_cors" ;;
      19) func_name="vector_race" ;;
      20) func_name="vector_nosqli" ;;
      21) func_name="vector_nuclei" ;;
      22) func_name="vector_ssrf_proof" ;;
      23) func_name="vector_prototype_pollution" ;;
      24) func_name="vector_websocket_hijack" ;;
      25) func_name="vector_mass_assignment" ;;
      26) func_name="vector_hpp" ;;
      27) func_name="vector_deserialization" ;;
      28) func_name="vector_oauth_takeover" ;;
      29) func_name="vector_cache_poisoning" ;;
      30) func_name="vector_crlf_injection" ;;
    esac
    
    if declare -f "$func_name" >/dev/null; then
      $func_name "$target" "$report"
      local vfindings=$?
      total_findings=$((total_findings + vfindings))
    else
      print_error "Function $func_name not found in $vf"
    fi
  done
  
  return $total_findings
}

# === View Reports ===
view_reports() {
  echo -e "\n${BOLD}Past Reports:${NC}\n"
  shopt -s nullglob
  local reports=("$REPORTS_DIR"/*.md)
  shopt -u nullglob
  
  if [ ${#reports[@]} -eq 0 ]; then
    print_info "No reports yet"
    return
  fi
  
  local i=0
  for r in "${reports[@]}"; do
    [ ! -f "$r" ] && continue
    i=$((i + 1))
    local name=$(basename "$r")
    local target=$(grep "^**Target:**" "$r" | sed 's/.*\*\*Target:\*\* //')
    local date=$(grep "^**Date:**" "$r" | sed 's/.*\*\*Date:\*\* //')
    local vulns=$(grep -c "^### [0-9]" "$r" 2>/dev/null || echo 0)
    echo -e "  ${CYAN}[$i]${NC} ${BOLD}$name${NC}"
    echo -e "      Target: ${target:-N/A} | Date: ${date:-N/A} | Vulns: ${BRIGHT_RED}$vulns${NC}"
  done
  
  echo ''
  read -p "  ${ICON_ARROW} Open report number (or Enter to skip): " rnum
  
  if [ -n "$rnum" ] && [ "$rnum" -ge 1 ] 2>/dev/null; then
    local idx=$((rnum - 1))
    shopt -s nullglob
    local reports_arr=("$REPORTS_DIR"/*.md)
    shopt -u nullglob
    if [ "$idx" -lt "${#reports_arr[@]}" ]; then
      cat "${reports_arr[$idx]}"
      local html="${reports_arr[$idx]%.md}.html"
      echo ''
      print_info "HTML: $html"
    fi
  fi
}

# === Cleanup ===
cleanup_findings() {
  rm -f "$REPORTS_DIR"/.finding_*.txt "$REPORTS_DIR"/.recon_*.txt "$REPORTS_DIR"/.sqlmap_*.txt 2>/dev/null
}

# === CLI Mode (non-interactive) ===
cli_mode() {
  show_banner
  case "${2:-quick}" in
    quick|q)   quick_scan "$1" ;;
    deep|d|all) deep_scan "$1" ;;
    custom|c)  
      shift
      custom_scan "$1"
      ;;
    hunt|h)    source "$ENGINE_DIR/hunter.sh" && hunter_main "${3:-500}" "${4:-auto}" ;;
    list|l)    list_vectors ;;
    *)         quick_scan "$1" ;;
  esac
}

# === Entry Point ===
check_deps

if ! check_ollama; then
  print_warn "Ollama unavailable. Running without AI brain (default vectors)."
  export NO_OLLAMA=true
fi

if [ $# -ge 1 ]; then
  # CLI mode: ./analyzer <url> [quick|deep|custom]
  cli_mode "$@"
else
  interactive_mode
fi
