#!/usr/bin/env bash

show_help() {
  cat <<EOF
Usage: $0 {project id} [OPTIONS]

Creates or updates a random scheduled pipeline for GitLab projects.

Arguments:
  project id              GitLab project ID (required)

Options:
  --start-time HH:mm      Start of time range for scheduling (24-hour format)
  --end-time HH:mm        End of time range for scheduling (24-hour format)
  --help                  Display this help message and exit

Notes:
  - If --start-time is used, --end-time must also be specified (and vice versa)
  - Without time range options, a random time will be selected within 24 hours
  - Time ranges can cross midnight (e.g., --start-time 22:00 --end-time 03:00)
  - If a scheduled pipeline already exists, it will be updated with the new time
  - Times are in UTC

Examples:
  $0 123                            # Create random schedule for project 123 (any time)
  $0 123 --start-time 09:00 --end-time 17:00  # Schedule between 9 AM and 5 PM
EOF
}

# Check if help is requested
if [[ $1 == "--help" ]]; then
  show_help
  exit 0
fi

# Initialize variables
PROJECT_ID=""
START_TIME=""
END_TIME=""

# Parse all arguments
while [[ $# -gt 0 ]]; do
  case $1 in
  --help)
    show_help
    exit 0
    ;;
  --start-time)
    START_TIME=$2
    shift 2
    ;;
  --end-time)
    END_TIME=$2
    shift 2
    ;;
  *)
    # If it's not a flag and project ID is not set, treat it as project ID
    if [[ -z $PROJECT_ID ]]; then
      PROJECT_ID=$1
      shift
    else
      echo "Unknown parameter: $1"
      echo "Use --help for usage information"
      exit 1
    fi
    ;;
  esac
done

# Check if project ID is provided
if [ -z "$PROJECT_ID" ]; then
  echo "Error: Missing project ID"
  echo "Use --help for usage information"
  exit 1
fi

# Validate that if one time parameter is provided, both must be provided
if [[ -n $START_TIME && -z $END_TIME ]] || [[ -z $START_TIME && -n $END_TIME ]]; then
  echo "Error: Both --start-time and --end-time must be specified together"
  echo "Use --help for usage information"
  exit 1
fi

# Function to convert HH:mm to minutes since midnight
# Function to convert HH:mm to minutes since midnight
time_to_minutes() {
  local time_str=$1
  # Remove leading zeros to avoid octal interpretation issues
  local hours
  hours=$(echo "$time_str" | cut -d':' -f1 | sed 's/^0*//')
  local minutes
  minutes=$(echo "$time_str" | cut -d':' -f2 | sed 's/^0*//')

  # Handle empty string (if hours or minutes was just "0")
  if [ -z "$hours" ]; then
    hours=0
  fi
  if [ -z "$minutes" ]; then
    minutes=0
  fi

  echo $((10#$hours * 60 + 10#$minutes))
}

# Function to validate time format
validate_time_format() {
  local time_str=$1
  if ! [[ $time_str =~ ^([0-1][0-9]|2[0-3]):[0-5][0-9]$ ]]; then
    echo "Error: Time format must be HH:mm (e.g., 09:30)"
    exit 1
  fi
}

# Generate random time
if [[ -n $START_TIME && -n $END_TIME ]]; then
  # Validate time formats
  validate_time_format "$START_TIME"
  validate_time_format "$END_TIME"

  # Convert times to minutes since midnight
  START_MINUTES=$(time_to_minutes "$START_TIME")
  END_MINUTES=$(time_to_minutes "$END_TIME")

  # Handle case where end_time is earlier than start_time (crosses midnight)
  if [ "$END_MINUTES" -lt "$START_MINUTES" ]; then
    END_MINUTES=$((END_MINUTES + 24 * 60))
  fi

  # Calculate range and generate random minutes within that range
  RANGE=$((END_MINUTES - START_MINUTES))
  if [ "$RANGE" -eq 0 ]; then
    RANDOM_MINUTES=$START_MINUTES
  else
    RANDOM_MINUTES=$((START_MINUTES + RANDOM % RANGE))
  fi

  # Convert back to hours and minutes
  RANDOM_HOUR=$(((RANDOM_MINUTES % (24 * 60)) / 60))
  RANDOM_MINUTE=$((RANDOM_MINUTES % 60))
else
  # Generate completely random hour and minute
  RANDOM_HOUR=$((RANDOM % 24))
  RANDOM_MINUTE=$((RANDOM % 60))
fi

# Format the cron expression
CRON_EXPRESSION="$RANDOM_MINUTE $RANDOM_HOUR * * *"

echo "Generated schedule: $CRON_EXPRESSION (UTC)"

# Check if the project has a .gitlab-ci.yml file in the main branch
HAS_PIPELINE=$(curl --silent --header "PRIVATE-TOKEN: $SELF_GITLAB_TOKEN" \
  "https://gitlab.ellisbs.co.uk/api/v4/projects/$PROJECT_ID/repository/files/.gitlab-ci.yml?ref=main" |
  jq -r 'if has("message") then "no" else "yes" end')

if [ "$HAS_PIPELINE" = "yes" ]; then
  # Check if a pipeline schedule already exists
  EXISTING_SCHEDULES=$(curl --silent --header "PRIVATE-TOKEN: $SELF_GITLAB_TOKEN" \
    "https://gitlab.ellisbs.co.uk/api/v4/projects/$PROJECT_ID/pipeline_schedules")

  SCHEDULE_COUNT=$(echo "$EXISTING_SCHEDULES" | jq 'length')

  if [ "$SCHEDULE_COUNT" -gt 0 ]; then
    # Get the ID of the first schedule
    SCHEDULE_ID=$(echo "$EXISTING_SCHEDULES" | jq '.[0].id')
    echo "Updating existing pipeline schedule (ID: $SCHEDULE_ID)"

    # Update the existing schedule
    curl --request PUT \
      --header "PRIVATE-TOKEN: $SELF_GITLAB_TOKEN" \
      --form description="Build packages" \
      --form ref="main" \
      --form cron="$CRON_EXPRESSION" \
      --form cron_timezone="UTC" \
      --form active="true" \
      "https://gitlab.ellisbs.co.uk/api/v4/projects/$PROJECT_ID/pipeline_schedules/$SCHEDULE_ID"
  else
    # Create a new schedule
    echo "Creating new pipeline schedule"
    curl --request POST \
      --header "PRIVATE-TOKEN: $SELF_GITLAB_TOKEN" \
      --form description="Build packages" \
      --form ref="main" \
      --form cron="$CRON_EXPRESSION" \
      --form cron_timezone="UTC" \
      --form active="true" \
      "https://gitlab.ellisbs.co.uk/api/v4/projects/$PROJECT_ID/pipeline_schedules"
  fi
else
  echo "Skipping project $PROJECT_ID: No .gitlab-ci.yml found in main branch"
fi
