#!/bin/bash
# Sprint Rollover Script
# Sprint state is date-derived; this script only handles task rollover for ended sprints.

set -euo pipefail

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

TODAY=$(date +%Y-%m-%d)
LOG_FILE="${LOG_FILE:-/tmp/sprint-auto-status.log}"

log() {
  echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

# Get current date in ISO format
get_today() {
  date +%Y-%m-%d
}

# Get all sprints
get_all_sprints() {
  api_call GET "/sprints" | jq -r '.sprints // []'
}

# Determine what status a sprint should have based on date
get_sprint_target_status() {
  local start_date="$1"
  local end_date="$2"
  local today="${3:-$(get_today)}"
  
  if [[ "$today" < "$start_date" ]]; then
    echo "planning"
  elif [[ "$today" > "$end_date" ]]; then
    echo "completed"
  else
    echo "active"
  fi
}

# Get incomplete tasks for a sprint (status not in done, canceled, closed)
get_incomplete_tasks() {
  local sprint_id="$1"
  
  api_call GET "/tasks?scope=all" | \
    jq --arg sid "$sprint_id" '
      .tasks 
      | map(select(
        .sprintId == $sid 
        and (.status != "done" and .status != "canceled" and .status != "closed" and .status != "archived")
      ))
    '
}

# Get current active sprint (the one containing today)
get_current_active_sprint() {
  local today="${1:-$(get_today)}"
  
  api_call GET "/sprints" | \
    jq --arg today "$today" '
      .sprints 
      | map(select(.start_date <= $today and .end_date >= $today))
      | .[0]
    '
}

# Move task to new sprint
move_task_to_sprint() {
  local task_id="$1"
  local new_sprint_id="$2"
  local old_sprint_name="$3"
  
  log "Moving task $task_id to sprint $new_sprint_id (from $old_sprint_name)"
  
  # Get existing task
  local task
  task=$(api_call GET "/tasks?taskId=$(urlencode "$task_id")&include=detail" | jq '.tasks[0]')
  
  if [[ -z "$task" || "$task" == "null" ]]; then
    log "✗ Task $task_id not found"
    return 1
  fi
  
  # Update sprint ID and add comment
  local now
  now=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
  local comment
  comment="Auto-rolled over from $old_sprint_name on $(get_today)"
  
  local updated_task
  updated_task=$(echo "$task" | \
    jq --arg sid "$new_sprint_id" \
       --arg comment "$comment" \
       --arg createdAt "$now" \
       --arg commentId "$(date +%s)-$RANDOM" '
      .sprintId = $sid |
      .comments = (.comments // []) + [{
        id: $commentId,
        text: $comment,
        createdAt: $createdAt,
        commentAuthorId: "system",
        replies: []
      }]
    ')
  
  if api_call POST "/tasks" "{\"task\": $updated_task}" > /dev/null 2>&1; then
    log "✓ Successfully moved task $task_id"
    return 0
  else
    log "✗ Failed to move task $task_id"
    return 1
  fi
}

# Main function to process sprint updates
process_sprint_updates() {
  log "=== Starting Sprint Rollover Run ==="
  log "Today: $(get_today)"
  
  # Get all sprints
  local sprints
  sprints=$(get_all_sprints)
  
  if [[ -z "$sprints" || "$sprints" == "[]" ]]; then
    log "No sprints found"
    return 0
  fi
  
  local rollover_count=0
  
  # Process each sprint
  while IFS= read -r sprint; do
    [[ -z "$sprint" ]] && continue
    
    local sprint_id
    local start_date
    local end_date
    local sprint_name
    
    sprint_id=$(echo "$sprint" | jq -r '.id // empty')
    start_date=$(echo "$sprint" | jq -r '.start_date // .startDate // empty')
    end_date=$(echo "$sprint" | jq -r '.end_date // .endDate // empty')
    sprint_name=$(echo "$sprint" | jq -r '.name // "Unnamed"')
    
    [[ -z "$sprint_id" ]] && continue
    
    # Determine target status
    local target_status
    target_status=$(get_sprint_target_status "$start_date" "$end_date")
    
    log "Sprint: $sprint_name (ID: $sprint_id) - Derived status: $target_status"

    # Rollover applies only to completed (ended) sprints.
    if [[ "$target_status" == "completed" ]]; then
      log "Sprint $sprint_name has ended - checking for tasks to roll over"

      # Get the new current sprint
      local current_sprint
      current_sprint=$(get_current_active_sprint)

      if [[ -n "$current_sprint" && "$current_sprint" != "null" ]]; then
        local new_sprint_id
        new_sprint_id=$(echo "$current_sprint" | jq -r '.id')

        # Get incomplete tasks
        local incomplete_tasks
        incomplete_tasks=$(get_incomplete_tasks "$sprint_id")

        local task_count
        task_count=$(echo "$incomplete_tasks" | jq 'length')

        if [[ "$task_count" -gt 0 ]]; then
          log "Found $task_count incomplete tasks to roll over"

          # Move each task
          while IFS= read -r task_id; do
            [[ -z "$task_id" ]] && continue
            if move_task_to_sprint "$task_id" "$new_sprint_id" "$sprint_name"; then
              ((rollover_count++))
            fi
          done < <(echo "$incomplete_tasks" | jq -r '.[].id' 2>/dev/null)
        else
          log "No incomplete tasks found"
        fi
      else
        log "Warning: No current active sprint found for rollover"
      fi
    fi
    
  done < <(echo "$sprints" | jq -c '.[]' 2>/dev/null)
  
  log "=== Sprint Update Complete ==="
  log "Rolled over: $rollover_count tasks"
  
  return 0
}

# Show help
show_help() {
  cat << 'HELP'
Sprint Rollover Script

USAGE:
  ./sprint-auto-status.sh [command]

COMMANDS:
  run       Run the rollover process for ended sprints
  dry-run   Show what would happen without making changes
  cleanup   Clean up old log files
  help      Show this help message

ENVIRONMENT:
  LOG_FILE  Path to log file (default: /tmp/sprint-auto-status.log)
  API_URL   Gantt Board API URL (default: http://localhost:3000/api)

EXAMPLES:
  ./sprint-auto-status.sh run
  LOG_FILE=/var/log/sprint-status.log ./sprint-auto-status.sh run
HELP
}

# Main execution
case "${1:-}" in
  run)
    process_sprint_updates
    ;;
  dry-run)
    log "=== DRY RUN MODE - No changes will be made ==="
    # In dry-run mode, we'd print what would happen
    log "Would check all sprints and derive state from dates on $(get_today)"
    log "Would roll over incomplete tasks from ended sprints"
    ;;
  cleanup)
    rm -f /tmp/sprint-auto-status.log
    log "Cleaned up log files"
    ;;
  help|--help|-h|"")
    show_help
    ;;
  *)
    log_error "Unknown command: $1"
    show_help
    exit 1
    ;;
esac
