#!/usr/bin/env bash
################################################################################
# cage-send — Write a message to the trusty-cage outbox
#
# USAGE:
#   cage-send <type> <payload_json>
#
# EXAMPLES:
#   cage-send task_complete '{"summary":"Done","exit_code":0}'
#   cage-send progress_update '{"status":"working on tests","detail":"3 of 5"}'
#   cage-send error '{"error_type":"missing_dep","message":"need ffmpeg","recoverable":true}'
#   cage-send info_request '{"request_id":"req-001","description":"Need package.json","paths":["package.json"]}'
#
# The script handles the message envelope (id, timestamp, version) and
# writes to ~/.cage/outbox/ with a timestamp-based filename.
################################################################################

set -euo pipefail

OUTBOX_DIR="${HOME}/.cage/outbox"
VALID_TYPES="task_complete progress_update error info_request going_idle"

if [ $# -lt 2 ]; then
    echo "Usage: cage-send <type> <payload_json>" >&2
    echo "Types: ${VALID_TYPES}" >&2
    exit 1
fi

MSG_TYPE="$1"
PAYLOAD="$2"

# Validate message type
_valid=false
for t in ${VALID_TYPES}; do
    if [ "${MSG_TYPE}" = "${t}" ]; then
        _valid=true
        break
    fi
done

if [ "${_valid}" = "false" ]; then
    echo "Error: Invalid message type '${MSG_TYPE}'" >&2
    echo "Valid types: ${VALID_TYPES}" >&2
    exit 1
fi

# Validate payload is JSON and has required fields for the message type
_validation=$(python3 -c "
import json, sys

try:
    payload = json.loads(sys.argv[1])
except (json.JSONDecodeError, ValueError) as e:
    print(f'Error: Payload is not valid JSON: {e}', file=sys.stderr)
    sys.exit(1)

if not isinstance(payload, dict):
    print('Error: Payload must be a JSON object', file=sys.stderr)
    sys.exit(1)

msg_type = sys.argv[2]

schemas = {
    'task_complete': {'summary': str, 'exit_code': int},
    'progress_update': {'status': str},
    'error': {'error_type': str, 'message': str, 'recoverable': bool},
    'info_request': {'request_id': str, 'description': str},
    'going_idle': {'reason': str},
}

required = schemas.get(msg_type, {})
for field, expected_type in required.items():
    if field not in payload:
        print(f'Error: {msg_type} requires field \"{field}\"', file=sys.stderr)
        sys.exit(1)
    if not isinstance(payload[field], expected_type):
        actual = type(payload[field]).__name__
        print(f'Error: {msg_type}.{field} must be {expected_type.__name__}, got {actual}', file=sys.stderr)
        sys.exit(1)
" "${PAYLOAD}" "${MSG_TYPE}" 2>&1) || {
    echo "${_validation}" >&2
    exit 1
}

# Generate timestamp and ID
TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)
FILENAME=$(echo "${TIMESTAMP}" | tr ':' '-').json
MSG_ID="msg-$(date -u +%Y%m%dT%H%M%S%N | head -c19)-$(head -c2 /dev/urandom | od -An -tx1 | tr -d ' \n')"

# Ensure outbox exists
mkdir -p "${OUTBOX_DIR}"

# Write the message
python3 -c "
import json, sys
msg = {
    'id': '${MSG_ID}',
    'type': '${MSG_TYPE}',
    'timestamp': '${TIMESTAMP}',
    'payload': json.loads(sys.argv[1]),
    'version': 1,
}
print(json.dumps(msg, indent=2))
" "${PAYLOAD}" > "${OUTBOX_DIR}/${FILENAME}"

echo "Sent ${MSG_TYPE} -> ${OUTBOX_DIR}/${FILENAME}"
