#!/bin/bash
# This file is in the public domain.
# Send an SMS using ClickSend API

set -eu

# Check shared secrets
if [ -x "$CLICKSEND_USERNAME" ]
then
    echo "CLICKSEND_USERNAME not set in environment"
    exit 1
fi
if [ -x "$CLICKSEND_API_KEY" ]
then
    echo "CLICKSEND_API_KEY not set in environment"
    exit 1
fi

if [ $# -ne 1 ]
then
    echo "Usage: $0 <phone_number>" 1>&2
    exit 1
fi

PHONE_NUMBER="$1"
MESSAGE=$(cat -)

TMPFILE=$(mktemp /tmp/clicksend-sms-logging-XXXXXX)

RESPONSE=$(curl --silent --show-error --fail \
  --url https://rest.clicksend.com/v3/sms/send \
  --request POST \
  --header 'Content-Type: application/json' \
  --user "$CLICKSEND_USERNAME:$CLICKSEND_API_KEY" \
  --data "{
    \"messages\": [{
      \"source\": \"bash-script\",
      \"to\": \"$PHONE_NUMBER\",
      \"body\": \"$MESSAGE\"
    }]
  }")

echo "$RESPONSE" > "$TMPFILE"

RESPONSE_CODE=$(echo "$RESPONSE" | jq -r '.response_code')

if [ "$RESPONSE_CODE" != "SUCCESS" ];
then
    echo "Clicksend: failed to send SMS to $PHONE_NUMBER, got response code $RESPONSE_CODE." 1>&2
    exit 2
fi

MESSAGE_ID=$(echo "$RESPONSE" | jq -r '.data.messages[0].message_id')

if [ "$MESSAGE_ID" == "null" ];
then
    echo "Clicksend: failed to retrieve message ID for message to $PHONE_NUMBER." 1>&2
    echo "$RESPONSE" 1>&2
    exit 3
fi

MESSAGE_STATUS=$(echo "$RESPONSE" | jq -r '.data.messages[0].status')

if [ "$MESSAGE_STATUS" == "SUCCESS" ];
then
    echo "Clicksend: message delivered successfully to $PHONE_NUMBER." 1>&2
    exit 0
fi

MAX_ITERATIONS=12

# Poll message status
echo "Polling message status (message_id: $MESSAGE_ID)..." 1>&2
for N in $(seq 1 "$MAX_ITERATIONS")
do
    STATUS_RESPONSE=$(curl --silent --show-error --fail \
      --url "https://rest.clicksend.com/v3/sms/receipts/$MESSAGE_ID" \
      --user "$CLICKSEND_USERNAME:$CLICKSEND_API_KEY")

    echo "$STATUS_RESPONSE" >> "$TMPFILE"

    RESPONSE_CODE=$(echo "$RESPONSE" | jq -r '.response_code')

    if [ "$RESPONSE_CODE" != "SUCCESS" ];
    then
	echo "Clicksend: failed to get status for message to $PHONE_NUMBER, assuming failure." 1>&2
        echo "$RESPONSE" 1>&2
	exit 4
    fi

    STATUS_CODE=$(echo "$STATUS_RESPONSE" | jq -r '.data.status_code')
    STATUS_TEXT=$(echo "$STATUS_RESPONSE" | jq -r '.data.status_text')
    STATUS=$(echo "$STATUS_TEXT" | awk --field-separator ':' '{print $1}')

    case "$STATUS_CODE" in
	"200")
	    case "$STATUS" in
		"Success"|"Sent")
		    # Message sent to the network for delivery, wait a bit
		    sleep 1
		    ;;
		"Queued"|"Scheduled")
		    # queued for delivery, sleep a bit longer
		    sleep 10
		    ;;
		"WaitApproval")
		    # Human in the loop (strange), sleep even longer
		    sleep 120
		    ;;
		*)
		    # Unexpected status, keep trying
		    sleep 5
		    ;;
	    esac
	    ;;
        "201")
	    # Message delivered to the handset
	    echo "Clicksend: message delivered successfully to $PHONE_NUMBER." 1>&2
	    exit 0
	    ;;
	"300")
	    # Temporary network error, clicksend will retry automatically, sleep a bit
	    sleep 20
	    ;;
	"301")
	    # Delivery failed
            echo "Clicksend: message delivery to $PHONE_NUMBER failed: $DESCRIPTION" 1>&2
	    exit 1
	    ;;
        "FAILED"|"INVALID_RECIPIENT")
            echo "Clicksend: message delivery to $PHONE_NUMBER failed: $DESCRIPTION" 1>&2
            exit 6
            ;;
        *)
            echo "Clicksend: message delivery to $PHONE_NUMBER failed: $DESCRIPTION" 1>&2
            sleep 5
            ;;
    esac
done

echo "Clicksend: unclear message delivery status $STATUS_CODE ($DESCRIPTION) after $MAX_ITERATIONS iterations. Assuming failure." 1>&2
exit 1
