#!/usr/bin/env bash
set -euo pipefail

# Script Name: api
# Description: API testing helper with saved requests and response management
# Usage: api save login "POST https://api.com/login" -d '{"user":"test"}'
#        api run login
#        api list
#        api history login

VERSION="1.0.0"
API_DIR="$HOME/.api"
REQUESTS_DIR="$API_DIR/requests"
RESPONSES_DIR="$API_DIR/responses"
TOKENS_FILE="$API_DIR/tokens.json"

# Colors
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly RED='\033[0;31m'
readonly CYAN='\033[0;36m'
readonly BOLD='\033[1m'
readonly NC='\033[0m'

# Initialize API directory structure
init_api() {
  mkdir -p "$REQUESTS_DIR" "$RESPONSES_DIR"
  if [[ ! -f "$TOKENS_FILE" ]]; then
    echo '{}' > "$TOKENS_FILE"
  fi
}

show_help() {
  echo -e "${BOLD}api${NC} - API Testing Helper v${VERSION}"
  echo
  echo -e "${BOLD}USAGE:${NC}"
  echo "  api <command> [args]"
  echo
  echo -e "${BOLD}COMMANDS:${NC}"
  echo -e "  ${CYAN}save NAME CURL_ARGS${NC}    Save HTTP request"
  echo -e "  ${CYAN}run NAME [VARS]${NC}        Run saved request"
  echo -e "  ${CYAN}list${NC}                   List saved requests"
  echo -e "  ${CYAN}show NAME${NC}              Show request details"
  echo -e "  ${CYAN}delete NAME${NC}            Delete saved request"
  echo -e "  ${CYAN}history NAME${NC}           Show response history"
  echo -e "  ${CYAN}diff NAME${NC}              Diff last two responses"
  echo -e "  ${CYAN}token set KEY VAL${NC}      Save auth token"
  echo -e "  ${CYAN}token get KEY${NC}          Get auth token"
  echo -e "  ${CYAN}export NAME curl${NC}       Export as curl command"
  echo
  echo -e "${BOLD}EXAMPLES:${NC}"
  echo "  # Save a login request"
  echo "  api save login \"POST https://api.example.com/login\" \\"
  echo "    -H \"Content-Type: application/json\" \\"
  echo "    -d '{\"user\":\"test\",\"pass\":\"\${PASSWORD}\"}'"
  echo
  echo "  # Run with variable substitution"
  echo "  api run login PASSWORD=secret123"
  echo
  echo "  # Save auth token from response"
  echo "  api token set AUTH_TOKEN \"Bearer abc123\""
  echo
  echo "  # Use token in request"
  echo "  api save profile \"GET https://api.example.com/profile\" \\"
  echo "    -H \"Authorization: \${AUTH_TOKEN}\""
  echo
  echo -e "${BOLD}FEATURES:${NC}"
  echo "  - Variable substitution (\${VAR})"
  echo "  - Response history"
  echo "  - Pretty-print JSON"
  echo "  - Diff responses"
  echo "  - Token management"
  echo
  echo -e "${BOLD}NOTES:${NC}"
  echo "  Requests: $REQUESTS_DIR"
  echo "  Responses: $RESPONSES_DIR"
  echo "  Tokens: $TOKENS_FILE"
}

# Save request
save_request() {
  local name=$1
  shift
  local request_file="$REQUESTS_DIR/$name.sh"

  # Save the curl command
  cat > "$request_file" << EOF
#!/usr/bin/env bash
# API Request: $name
# Saved: $(date)

curl -w "\\n\\nStatus: %{http_code}\\nTime: %{time_total}s\\n" \\
  $@
EOF

  chmod +x "$request_file"
  echo -e "${GREEN}✓${NC} Saved request: $name"
  echo -e "${CYAN}File:${NC} $request_file"
}

# Run saved request
run_request() {
  local name=$1
  shift
  local request_file="$REQUESTS_DIR/$name.sh"

  if [[ ! -f "$request_file" ]]; then
    echo -e "${RED}Error:${NC} Request not found: $name" >&2
    echo "Use 'api list' to see available requests" >&2
    exit 1
  fi

  # Parse variables (KEY=VALUE format)
  declare -A vars
  for arg in "$@"; do
    if [[ "$arg" =~ ^([A-Z_]+)=(.+)$ ]]; then
      vars[${BASH_REMATCH[1]}]="${BASH_REMATCH[2]}"
    fi
  done

  # Read request, substitute variables
  request_content=$(cat "$request_file")
  for var in "${!vars[@]}"; do
    request_content="${request_content//\$\{$var\}/${vars[$var]}}"
  done

  # Also substitute from tokens file
  if command -v jq &>/dev/null && [[ -f "$TOKENS_FILE" ]]; then
    while IFS= read -r line; do
      key=$(echo "$line" | jq -r '.key')
      val=$(echo "$line" | jq -r '.value')
      request_content="${request_content//\$\{$key\}/$val}"
    done < <(jq -c 'to_entries[]' "$TOKENS_FILE")
  fi

  # Save response with timestamp
  timestamp=$(date '+%Y%m%d-%H%M%S')
  response_file="$RESPONSES_DIR/${name}_${timestamp}.txt"

  echo -e "${BOLD}${CYAN}Running: $name${NC}"
  echo

  # Execute and save response
  echo "$request_content" | bash | tee "$response_file"

  echo
  echo -e "${GREEN}✓${NC} Response saved: $response_file"

  # Pretty-print JSON if possible
  if command -v jq &>/dev/null; then
    if head -1 "$response_file" | jq empty 2>/dev/null; then
      echo
      echo -e "${BOLD}${CYAN}JSON Response:${NC}"
      head -n -3 "$response_file" | jq .
    fi
  fi
}

# List saved requests
list_requests() {
  if [[ ! -d "$REQUESTS_DIR" ]] || [[ -z "$(ls -A "$REQUESTS_DIR" 2>/dev/null)" ]]; then
    echo -e "${YELLOW}No saved requests${NC}"
    exit 0
  fi

  echo -e "${BOLD}${CYAN}Saved Requests:${NC}"
  echo

  for file in "$REQUESTS_DIR"/*.sh; do
    name=$(basename "$file" .sh)
    method=$(grep -oP 'POST|GET|PUT|DELETE|PATCH' "$file" | head -1 || echo "?")
    url=$(grep -oP 'https?://[^\s"]+' "$file" | head -1 || echo "?")

    printf "  %-20s ${CYAN}%-7s${NC} %s\n" "$name" "$method" "$url"
  done
}

# Show request details
show_request() {
  local name=$1
  local request_file="$REQUESTS_DIR/$name.sh"

  if [[ ! -f "$request_file" ]]; then
    echo -e "${RED}Error:${NC} Request not found: $name" >&2
    exit 1
  fi

  echo -e "${BOLD}${CYAN}Request: $name${NC}"
  echo

  # Use bat if available for syntax highlighting
  if command -v bat &>/dev/null; then
    bat "$request_file"
  else
    cat "$request_file"
  fi
}

# Delete request
delete_request() {
  local name=$1
  local request_file="$REQUESTS_DIR/$name.sh"

  if [[ ! -f "$request_file" ]]; then
    echo -e "${RED}Error:${NC} Request not found: $name" >&2
    exit 1
  fi

  echo -n "Delete request '$name'? (y/N) "
  read -r response
  if [[ "$response" =~ ^[Yy]$ ]]; then
    rm "$request_file"
    echo -e "${GREEN}✓${NC} Deleted: $name"
  else
    echo "Cancelled"
  fi
}

# Show response history
show_history() {
  local name=$1

  responses=$(find "$RESPONSES_DIR" -name "${name}_*.txt" 2>/dev/null | sort -r)

  if [[ -z "$responses" ]]; then
    echo -e "${YELLOW}No response history for: $name${NC}"
    exit 0
  fi

  echo -e "${BOLD}${CYAN}Response History: $name${NC}"
  echo

  echo "$responses" | while read -r file; do
    timestamp=$(basename "$file" | sed "s/${name}_//" | sed 's/.txt//')
    status=$(tail -3 "$file" | grep "Status:" | awk '{print $2}')
    time=$(tail -3 "$file" | grep "Time:" | awk '{print $2}')

    # Color status
    if [[ "$status" =~ ^2 ]]; then
      status_colored="${GREEN}$status${NC}"
    elif [[ "$status" =~ ^4 ]]; then
      status_colored="${YELLOW}$status${NC}"
    elif [[ "$status" =~ ^5 ]]; then
      status_colored="${RED}$status${NC}"
    else
      status_colored="$status"
    fi

    echo -e "  $timestamp - Status: $status_colored - Time: $time"
  done

  echo
  echo -e "${CYAN}Tip:${NC} Use 'api diff $name' to compare last two responses"
}

# Diff last two responses
diff_responses() {
  local name=$1

  responses=$(find "$RESPONSES_DIR" -name "${name}_*.txt" 2>/dev/null | sort -r | head -2)
  count=$(echo "$responses" | wc -l)

  if [[ $count -lt 2 ]]; then
    echo -e "${YELLOW}Need at least 2 responses to diff${NC}"
    exit 0
  fi

  file1=$(echo "$responses" | sed -n 1p)
  file2=$(echo "$responses" | sed -n 2p)

  echo -e "${BOLD}${CYAN}Diff: $name${NC}"
  echo -e "${CYAN}Latest:${NC} $(basename "$file1")"
  echo -e "${CYAN}Previous:${NC} $(basename "$file2")"
  echo

  # Remove status/time lines before diff
  diff -u <(head -n -3 "$file2") <(head -n -3 "$file1") || true
}

# Token management
manage_token() {
  local action=$1
  shift

  case "$action" in
    set)
      if [[ $# -lt 2 ]]; then
        echo -e "${RED}Error:${NC} Usage: api token set KEY VALUE" >&2
        exit 1
      fi
      key=$1
      value=$2

      # Update JSON file
      if command -v jq &>/dev/null; then
        jq --arg k "$key" --arg v "$value" '. + {($k): $v}' "$TOKENS_FILE" > "$TOKENS_FILE.tmp"
        mv "$TOKENS_FILE.tmp" "$TOKENS_FILE"
        echo -e "${GREEN}✓${NC} Token saved: $key"
      else
        echo -e "${RED}Error:${NC} jq required for token management" >&2
        exit 1
      fi
      ;;

    get)
      if [[ $# -lt 1 ]]; then
        echo -e "${RED}Error:${NC} Usage: api token get KEY" >&2
        exit 1
      fi
      key=$1

      if command -v jq &>/dev/null; then
        value=$(jq -r ".$key // empty" "$TOKENS_FILE")
        if [[ -n "$value" ]]; then
          echo "$value"
        else
          echo -e "${YELLOW}Token not found: $key${NC}" >&2
          exit 1
        fi
      fi
      ;;

    list)
      if command -v jq &>/dev/null; then
        echo -e "${BOLD}${CYAN}Saved Tokens:${NC}"
        jq -r 'keys[]' "$TOKENS_FILE"
      fi
      ;;

    *)
      echo -e "${RED}Error:${NC} Unknown token action: $action" >&2
      echo "Use: set, get, list" >&2
      exit 1
      ;;
  esac
}

# Export request
export_request() {
  local name=$1
  local format=${2:-curl}
  local request_file="$REQUESTS_DIR/$name.sh"

  if [[ ! -f "$request_file" ]]; then
    echo -e "${RED}Error:${NC} Request not found: $name" >&2
    exit 1
  fi

  case "$format" in
    curl)
      # Extract the curl command
      grep -A 999 'curl' "$request_file" | grep -v '^#'
      ;;
    *)
      echo -e "${RED}Error:${NC} Unknown format: $format" >&2
      echo "Supported: curl" >&2
      exit 1
      ;;
  esac
}

# Initialize
init_api

# Parse command
if [[ $# -eq 0 ]]; then
  show_help
  exit 0
fi

case $1 in
  -h|--help|help)
    show_help
    ;;
  save)
    if [[ $# -lt 3 ]]; then
      echo -e "${RED}Error:${NC} Usage: api save NAME CURL_ARGS" >&2
      exit 1
    fi
    shift
    save_request "$@"
    ;;
  run)
    if [[ $# -lt 2 ]]; then
      echo -e "${RED}Error:${NC} Usage: api run NAME [VARS]" >&2
      exit 1
    fi
    shift
    run_request "$@"
    ;;
  list|ls)
    list_requests
    ;;
  show)
    if [[ $# -lt 2 ]]; then
      echo -e "${RED}Error:${NC} Usage: api show NAME" >&2
      exit 1
    fi
    show_request "$2"
    ;;
  delete|rm)
    if [[ $# -lt 2 ]]; then
      echo -e "${RED}Error:${NC} Usage: api delete NAME" >&2
      exit 1
    fi
    delete_request "$2"
    ;;
  history)
    if [[ $# -lt 2 ]]; then
      echo -e "${RED}Error:${NC} Usage: api history NAME" >&2
      exit 1
    fi
    show_history "$2"
    ;;
  diff)
    if [[ $# -lt 2 ]]; then
      echo -e "${RED}Error:${NC} Usage: api diff NAME" >&2
      exit 1
    fi
    diff_responses "$2"
    ;;
  token)
    if [[ $# -lt 2 ]]; then
      echo -e "${RED}Error:${NC} Usage: api token <set|get|list> ..." >&2
      exit 1
    fi
    shift
    manage_token "$@"
    ;;
  export)
    if [[ $# -lt 2 ]]; then
      echo -e "${RED}Error:${NC} Usage: api export NAME [FORMAT]" >&2
      exit 1
    fi
    export_request "$2" "${3:-curl}"
    ;;
  *)
    echo -e "${RED}Error:${NC} Unknown command: $1" >&2
    echo "Run 'api --help' for usage" >&2
    exit 1
    ;;
esac
