#!/usr/bin/env bash
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8

ENDPOINT="https://api.anysearch.com/mcp"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

if ! command -v jq &>/dev/null; then
  echo "Error: jq is required but not found. Install it: https://jqlang.github.io/jq/download/" >&2
  exit 1
fi

_load_env() {
  for env_path in "$SCRIPT_DIR/.env" "$SCRIPT_DIR/../.env"; do
    if [[ -f "$env_path" ]]; then
      while IFS= read -r line || [[ -n "$line" ]]; do
        line="${line%%#*}"
        line="$(echo "$line" | xargs 2>/dev/null || true)"
        [[ -z "$line" || "$line" != *=* ]] && continue
        local key="${line%%=*}"
        local val="${line#*=}"
        val="$(echo "$val" | sed 's/^["\x27]\|["\x27]$//g')"
        export "$key=$val"
      done < "$env_path"
    fi
  done
}

_load_env

API_KEY="${ANYSEARCH_API_KEY:-}"

# BEGIN GENERATED:CONSTANTS
AVAILABLE_DOMAINS=("general" "resource" "social_media" "finance" "academic" "legal" "health" "business" "security" "ip" "code" "energy" "environment" "agriculture" "travel" "film" "gaming")
# END GENERATED:CONSTANTS

_call_api() {
  local tool_name="$1"
  local arguments="$2"
  local auth_args=()
  if [[ -n "$API_KEY" ]]; then
    auth_args+=(-H "Authorization: Bearer $API_KEY")
  fi

  local payload
  payload=$(jq -n --arg name "$tool_name" --argjson args "$arguments" \
    '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":$name,"arguments":$args}}')

  local response
  response=$(curl -s -X POST "$ENDPOINT" \
    -H "Content-Type: application/json" \
    "${auth_args[@]}" \
    -d "$payload" \
    --max-time 30 2>/dev/null)

  if [[ -z "$response" ]]; then
    echo "Error: No response from API" >&2
    exit 1
  fi

  local error_msg
  error_msg=$(printf '%s' "$response" | jq -r '.error.message // empty' 2>/dev/null)
  if [[ -n "$error_msg" ]]; then
    echo "API Error: $error_msg" >&2
    exit 1
  fi

  local text_block
  text_block=$(printf '%s' "$response" | jq -r '.result.content[0].text // empty' 2>/dev/null)
  if [[ -n "$text_block" ]]; then
    printf '%s\n' "$text_block"
  else
    printf '%s\n' "$response"
  fi
}

_cmd_search() {
  local query=""
  local domain=""
  local sub_domain=""
  local sub_domain_params=""
  local max_results=""

  while [[ $# -gt 0 ]]; do
    case "$1" in
      --domain|-d)     domain="$2"; shift 2 ;;
      --sub_domain|-s) sub_domain="$2"; shift 2 ;;
      --sub_domain_params) sub_domain_params="$2"; shift 2 ;;
      --max_results|-m) max_results="$2"; shift 2 ;;
      --api_key)       API_KEY="$2"; shift 2 ;;
      -*)              echo "Unknown flag: $1" >&2; _usage; exit 1 ;;
      *)               query="$1"; shift ;;
    esac
  done

  if [[ -z "$query" ]]; then
    echo "Error: query is required" >&2
    exit 1
  fi

  local args
  args=$(jq -n --arg q "$query" '{"query":$q}')

  if [[ -n "$domain" ]]; then
    args=$(printf '%s' "$args" | jq --arg d "$domain" '. + {"domain":$d}')
    if [[ -n "$sub_domain" ]]; then
      args=$(printf '%s' "$args" | jq --arg s "$sub_domain" '. + {"sub_domain":$s}')
    fi
    if [[ -n "$sub_domain_params" ]]; then
      args=$(printf '%s' "$args" | jq --argjson p "$sub_domain_params" '. + {"sub_domain_params":$p}')
    fi
  fi

  if [[ -n "$max_results" ]]; then
    if [[ "$max_results" -gt 10 ]]; then
      max_results=10
    fi
    args=$(printf '%s' "$args" | jq --argjson m "$max_results" '. + {"max_results":$m}')
  fi

  _call_api "search" "$args"
}

_cmd_get_sub_domains() {
  local domain=""
  local domains=""

  while [[ $# -gt 0 ]]; do
    case "$1" in
      --domains)       domains="$2"; shift 2 ;;
      --domain)        domain="$2"; shift 2 ;;
      --api_key)       API_KEY="$2"; shift 2 ;;
      -*)              echo "Unknown flag: $1" >&2; exit 1 ;;
      *)               domain="$1"; shift ;;
    esac
  done

  local args
  if [[ -n "$domains" ]]; then
    local d_json
    if [[ "$domains" == \[* ]]; then
      d_json="$domains"
    else
      d_json=$(printf '%s' "$domains" | jq -R 'split(",") | map(gsub("^\\s+|\\s+$";"")) | map(select(length > 0))')
    fi
    args=$(jq -n --argjson d "$d_json" '{"domains":$d}')
  elif [[ -n "$domain" ]]; then
    args=$(jq -n --arg d "$domain" '{"domain":$d}')
  else
    echo "Error: provide --domain or --domains" >&2
    exit 1
  fi

  _call_api "get_sub_domains" "$args"
}

_cmd_extract() {
  local url=""

  while [[ $# -gt 0 ]]; do
    case "$1" in
      --url|-u)        url="$2"; shift 2 ;;
      --api_key)       API_KEY="$2"; shift 2 ;;
      -*)              echo "Unknown flag: $1" >&2; exit 1 ;;
      *)               url="$1"; shift ;;
    esac
  done

  if [[ -z "$url" ]]; then
    echo "Error: url is required" >&2
    exit 1
  fi

  local args
  args=$(jq -n --arg u "$url" '{"url":$u}')
  _call_api "extract" "$args"
}

_cmd_batch_search() {
  local queries=""
  local query_items=()

  while [[ $# -gt 0 ]]; do
    case "$1" in
      --queries|-q)    queries="$2"; shift 2 ;;
      --query)         query_items+=("$2"); shift 2 ;;
      --api_key)       API_KEY="$2"; shift 2 ;;
      -*)              echo "Unknown flag: $1" >&2; exit 1 ;;
      *)               queries="$1"; shift ;;
    esac
  done

  local args
  if [[ ${#query_items[@]} -gt 0 ]]; then
    if [[ ${#query_items[@]} -gt 5 ]]; then
      echo "Error: batch_search supports a maximum of 5 queries" >&2
      exit 1
    fi
    local items_json="[]"
    for q in "${query_items[@]}"; do
      items_json=$(printf '%s' "$items_json" | jq --arg q "$q" '. + [{"query":$q}]')
    done
    args=$(jq -n --argjson q "$items_json" '{"queries":$q}')
  elif [[ -n "$queries" ]]; then
    local raw="$queries"
    if [[ "$raw" == @* ]]; then
      local fpath="${raw:1}"
      if [[ ! -f "$fpath" ]]; then
        echo "Error: file not found: $fpath" >&2
        exit 1
      fi
      raw=$(cat "$fpath")
    fi
    if [[ "$raw" == \[* || "$raw" == \{* ]]; then
      if [[ "$raw" == \[* ]]; then
        args=$(jq -n --argjson q "$raw" '{"queries":$q}')
      else
        args=$(jq -n --argjson q "[$raw]" '{"queries":$q}')
      fi
    else
      local items_json
      items_json=$(printf '%s' "$raw" | jq -R 'split(",") | map(gsub("^\\s+|\\s+$";"")) | map(select(length > 0)) | map({"query":.})')
      args=$(jq -n --argjson q "$items_json" '{"queries":$q}')
    fi
  else
    echo "Error: provide --queries or --query" >&2
    exit 1
  fi

  local count
  count=$(printf '%s' "$args" | jq '.queries | length')
  if [[ "$count" -lt 1 ]]; then
    echo "Error: queries must contain at least 1 item" >&2
    exit 1
  fi
  if [[ "$count" -gt 5 ]]; then
    echo "Error: batch_search supports a maximum of 5 queries" >&2
    exit 1
  fi

  _call_api "batch_search" "$args"
}

# BEGIN GENERATED:DOC_SPEC
_cmd_doc() {
  local shared="$SCRIPT_DIR/shared"
  local tpl
  tpl=$(cat "$shared/doc_spec.md")
  local domains
  domains=$(jq -r '.available_domains | join(" ")' "$shared/constants.json")
  tpl="${tpl//\{\{LANG_NAME\}\}/Bash}"
  tpl="${tpl//\{\{LANG_CODEBLOCK\}\}/bash}"
  tpl="${tpl//\{\{LANG_INVOKE\}\}\}/bash scripts/anysearch_cli.sh}"
  tpl="${tpl//\{\{DOMAINS_SPACE\}\}/$domains}"
  printf '%s\n' "$tpl"
}
# END GENERATED:DOC_SPEC

_usage() {
  _cmd_doc
}

main() {
  local command="${1:-}"
  shift || true

  case "$command" in
    search)         _cmd_search "$@" ;;
    get_sub_domains)   _cmd_get_sub_domains "$@" ;;
    extract)        _cmd_extract "$@" ;;
    batch_search)   _cmd_batch_search "$@" ;;
    doc)            _cmd_doc ;;
    -h|--help|help) _usage ;;
    "")             _usage ;;
    *)              echo "Unknown command: $command" >&2; _usage; exit 1 ;;
  esac
}

main "$@"
