#!/bin/bash
# Sprint CLI for Gantt Board (API passthrough)
# Usage: ./sprint.sh [create|list|get|update|delete|close] [options]

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=./lib/api_client.sh
source "$SCRIPT_DIR/lib/api_client.sh"

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log_info() { echo -e "${BLUE}i${NC} $1"; }
log_success() { echo -e "${GREEN}ok${NC} $1"; }
log_warning() { echo -e "${YELLOW}warn${NC} $1"; }
log_error() { echo -e "${RED}error${NC} $1"; }

UUID_PATTERN='^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'

check_dependencies() {
  if ! command -v jq >/dev/null 2>&1; then
    log_error "jq is required. Install with: brew install jq"
    exit 1
  fi
}

show_usage() {
  cat << 'USAGE'
Sprint CLI for Gantt Board

USAGE:
  ./sprint.sh [COMMAND] [OPTIONS]

COMMANDS:
  create              Create a new sprint
  list                List all sprints
  get <id-or-name>    Get a specific sprint
  update <id-or-name> Update a sprint
  delete <id-or-name> Delete a sprint
  close <id-or-name>  Mark sprint completed

CREATE OPTIONS:
  --name "Name"               Sprint name (required)
  --goal "Goal"               Sprint goal
  --start-date "YYYY-MM-DD"   Start date
  --end-date "YYYY-MM-DD"     End date

LIST OPTIONS:
  --status <status>     Filter by status
  --active              Show sprints in progress for today (start <= today <= end)
  --json                Output as JSON
USAGE
}

resolve_sprint_id() {
  local identifier="$1"

  if [[ "$identifier" =~ $UUID_PATTERN ]]; then
    echo "$identifier"
    return 0
  fi

  local response
  response=$(api_call GET "/sprints")

  local sprint_id
  sprint_id=$(echo "$response" | jq -r --arg q "$identifier" '
    .sprints
    | map(select((.name // "") | ascii_downcase | contains($q | ascii_downcase)))
    | .[0].id // empty
  ')

  if [[ -n "$sprint_id" ]]; then
    echo "$sprint_id"
    return 0
  fi

  log_error "Sprint '$identifier' not found"
  return 1
}

cmd_create() {
  local name=""
  local goal=""
  local start_date=""
  local end_date=""

  while [[ $# -gt 0 ]]; do
    case "${1:-}" in
      --name) name="${2:-}"; shift 2 ;;
      --goal) goal="${2:-}"; shift 2 ;;
      --start-date) start_date="${2:-}"; shift 2 ;;
      --end-date) end_date="${2:-}"; shift 2 ;;
      *) shift ;;
    esac
  done

  if [[ -z "$name" ]]; then
    log_error "Name is required (use --name)"
    exit 1
  fi

  local payload
  payload=$(jq -n \
    --arg name "$name" \
    --arg goal "$goal" \
    --arg startDate "$start_date" \
    --arg endDate "$end_date" \
    '{
      name: $name,
      goal: (if $goal == "" then null else $goal end),
      startDate: (if $startDate == "" then null else $startDate end),
      endDate: (if $endDate == "" then null else $endDate end)
    }')

  log_info "Creating sprint..."
  api_call POST "/sprints" "$payload" | jq .
}

cmd_list() {
  local filter_status=""
  local active_only=false
  local output_json=false

  while [[ $# -gt 0 ]]; do
    case "${1:-}" in
      --status) filter_status="${2:-}"; shift 2 ;;
      --active) active_only=true; shift ;;
      --json) output_json=true; shift ;;
      *) shift ;;
    esac
  done

  local endpoint="/sprints"
  local query_params=()
  if [[ -n "$filter_status" ]]; then
    query_params+=("status=$(urlencode "$filter_status")")
  fi
  if [[ "$active_only" == true ]]; then
    query_params+=("inProgress=true")
  fi
  if [[ ${#query_params[@]} -gt 0 ]]; then
    endpoint+="?$(IFS='&'; echo "${query_params[*]}")"
  fi

  local response
  response=$(api_call GET "$endpoint")

  local sprints_json
  sprints_json=$(echo "$response" | jq '.sprints')

  if [[ "$output_json" == true ]]; then
    echo "$sprints_json" | jq .
    return
  fi

  local count
  count=$(echo "$sprints_json" | jq 'length')
  log_success "Found $count sprint(s)"

  printf "%-36s %-25s %-10s %-12s %-12s\n" "ID" "NAME" "STATUS" "START" "END"
  printf "%-36s %-25s %-10s %-12s %-12s\n" "------------------------------------" "-------------------------" "----------" "------------" "------------"

  echo "$sprints_json" | jq -r '.[] | [.id, (.name // "" | tostring | .[0:23]), (.status // "N/A"), (.start_date // .startDate // "N/A"), (.end_date // .endDate // "N/A")] | @tsv' \
    | while IFS=$'\t' read -r id name status start end; do
        printf "%-36s %-25s %-10s %-12s %-12s\n" "$id" "$name" "$status" "$start" "$end"
      done
}

cmd_get() {
  local identifier="${1:-}"
  if [[ -z "$identifier" ]]; then
    log_error "Sprint ID or name required"
    exit 1
  fi

  local sprint_id
  sprint_id=$(resolve_sprint_id "$identifier")

  log_info "Fetching sprint $sprint_id..."
  api_call GET "/sprints/$sprint_id" | jq '.sprint'
}

cmd_update() {
  local identifier="${1:-}"
  shift || true

  if [[ -z "$identifier" ]]; then
    log_error "Sprint ID or name required"
    exit 1
  fi

  local sprint_id
  sprint_id=$(resolve_sprint_id "$identifier")

  local updates='{}'
  while [[ $# -gt 0 ]]; do
    case "${1:-}" in
      --name) updates=$(echo "$updates" | jq --arg v "${2:-}" '. + {name: $v}'); shift 2 ;;
      --goal) updates=$(echo "$updates" | jq --arg v "${2:-}" '. + {goal: $v}'); shift 2 ;;
      --start-date) updates=$(echo "$updates" | jq --arg v "${2:-}" '. + {startDate: $v}'); shift 2 ;;
      --end-date) updates=$(echo "$updates" | jq --arg v "${2:-}" '. + {endDate: $v}'); shift 2 ;;
      *) shift ;;
    esac
  done

  if [[ "$updates" == "{}" ]]; then
    log_warning "No update fields specified"
    exit 0
  fi

  local payload
  payload=$(echo "$updates" | jq --arg id "$sprint_id" '. + {id: $id}')

  log_info "Updating sprint $sprint_id..."
  api_call PATCH "/sprints" "$payload" | jq .
}

cmd_close() {
  local identifier="${1:-}"
  if [[ -z "$identifier" ]]; then
    log_error "Sprint ID or name required"
    exit 1
  fi

  local sprint_id
  sprint_id=$(resolve_sprint_id "$identifier")

  log_info "Closing sprint $sprint_id..."
  api_call POST "/sprints/close" "{\"id\": \"$sprint_id\"}" | jq .
}

cmd_delete() {
  local identifier="${1:-}"
  if [[ -z "$identifier" ]]; then
    log_error "Sprint ID or name required"
    exit 1
  fi

  local sprint_id
  sprint_id=$(resolve_sprint_id "$identifier")

  log_info "Deleting sprint $sprint_id..."
  api_call DELETE "/sprints" "{\"id\": \"$sprint_id\"}" | jq .
}

check_dependencies

COMMAND="${1:-}"
shift || true

case "$COMMAND" in
  create) cmd_create "$@" ;;
  list) cmd_list "$@" ;;
  get) cmd_get "$@" ;;
  update) cmd_update "$@" ;;
  close) cmd_close "$@" ;;
  delete) cmd_delete "$@" ;;
  help|--help|-h|"") show_usage ;;
  *)
    log_error "Unknown command: $COMMAND"
    show_usage
    exit 1
    ;;
esac
