#!/usr/bin/env bash

set -euo pipefail
set +x

require_value() {
    local name="$1"

    if [[ -z "${!name:-}" ]]; then
        printf 'Missing required environment variable: %s\n' "$name" >&2
        exit 1
    fi
}

for key in MPESA_CONSUMER_KEY MPESA_CONSUMER_SECRET MPESA_PAYBILL MPESA_CONFIRMATION_URL MPESA_VALIDATION_URL; do
    require_value "$key"
done

BASE_URL="${MPESA_BASE_URL:-https://api.safaricom.co.ke}"
REGISTER_PATH="${MPESA_C2B_REGISTER_URL_PATH:-/mpesa/c2b/v2/registerurl}"
RESPONSE_TYPE="${MPESA_REGISTER_RESPONSE_TYPE:-Completed}"

if [[ "$MPESA_CONFIRMATION_URL" != https://* || "$MPESA_VALIDATION_URL" != https://* ]]; then
    printf 'Production confirmation and validation URLs must use HTTPS.\n' >&2
    exit 1
fi

append_callback_token() {
    local url="$1"

    if [[ -z "${MPESA_CALLBACK_TOKEN:-}" ]]; then
        printf '%s' "$url"
    elif [[ "$url" == *'?'* ]]; then
        printf '%s&token=%s' "$url" "$(php -r 'echo rawurlencode($argv[1]);' "$MPESA_CALLBACK_TOKEN")"
    else
        printf '%s?token=%s' "$url" "$(php -r 'echo rawurlencode($argv[1]);' "$MPESA_CALLBACK_TOKEN")"
    fi
}

CONFIRMATION_URL="$(append_callback_token "$MPESA_CONFIRMATION_URL")"
VALIDATION_URL="$(append_callback_token "$MPESA_VALIDATION_URL")"
TOKEN_BODY="$(mktemp)"
REGISTER_BODY="$(mktemp)"
trap 'rm -f "$TOKEN_BODY" "$REGISTER_BODY"' EXIT

TOKEN_STATUS="$(curl --silent --show-error --output "$TOKEN_BODY" --write-out '%{http_code}' \
    --user "${MPESA_CONSUMER_KEY}:${MPESA_CONSUMER_SECRET}" \
    --get "${BASE_URL%/}/oauth/v1/generate" \
    --data-urlencode 'grant_type=client_credentials')"

if [[ "$TOKEN_STATUS" != "200" ]]; then
    printf 'OAuth failed with HTTP %s\n' "$TOKEN_STATUS" >&2
    cat "$TOKEN_BODY" >&2
    exit 1
fi

ACCESS_TOKEN="$(php -r '$payload = json_decode(stream_get_contents(STDIN), true); echo is_array($payload) ? ($payload["access_token"] ?? "") : "";' < "$TOKEN_BODY")"

if [[ -z "$ACCESS_TOKEN" ]]; then
    printf 'OAuth succeeded but no access_token was returned.\n' >&2
    cat "$TOKEN_BODY" >&2
    exit 1
fi

PAYLOAD="$(php -r 'echo json_encode([
    "ShortCode" => $argv[1],
    "ResponseType" => $argv[2],
    "ConfirmationURL" => $argv[3],
    "ValidationURL" => $argv[4],
], JSON_UNESCAPED_SLASHES);' \
    "$MPESA_PAYBILL" "$RESPONSE_TYPE" "$CONFIRMATION_URL" "$VALIDATION_URL")"

REGISTER_STATUS="$(curl --silent --show-error --output "$REGISTER_BODY" --write-out '%{http_code}' \
    --request POST "${BASE_URL%/}${REGISTER_PATH}" \
    --header "Authorization: Bearer ${ACCESS_TOKEN}" \
    --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    --data "$PAYLOAD")"

printf 'C2B v2 registration returned HTTP %s\n' "$REGISTER_STATUS"
cat "$REGISTER_BODY"
printf '\n'

if [[ "$REGISTER_STATUS" -lt 200 || "$REGISTER_STATUS" -ge 300 ]]; then
    exit 1
fi
