#!/usr/bin/env bash
set -euo pipefail
# POS: communication telegram-sender — Send Telegram messages/files/links/stickers via Bot API (send, test, config set)
# POS_FLAGS: --type --caption --parse-mode --no-preview --token --chat-id --markdown
# POS_SUBCMDS: send test config
# POS_CONFIG: telegram | telegram.env | TELEGRAM_BOT_TOKEN=secret:Bot token from @BotFather | TELEGRAM_CHAT_ID=digits:Numeric chat id from @userinfobot

CONFIG_DIR="$HOME/.config/linux_post_install"
CONFIG_FILE="$CONFIG_DIR/telegram.env"
API="https://api.telegram.org"

usage() {
    cat <<EOF
Usage: pos communication telegram sender [command] [args]

Send Telegram messages via the Bot API.

Commands:
  send <value> [options]   Send a message, link, or media (auto-detects the type)
  test                     Send a test message using the current config
  config                   Show current config (token masked)
  config set KEY=VALUE     Set TELEGRAM_BOT_TOKEN or TELEGRAM_CHAT_ID

Types (auto-detected when --type is omitted):
  message    Plain text (default)
  link       Clickable link            (value starts with http:// https:// www.)
  file       Any document              (any other existing file)
  photo      .jpg .jpeg .png .bmp
  video      .mp4 .mkv .webm .mov .avi
  audio      .mp3 .wav .flac .m4a .aac
  voice      .ogg .opus .oga
  animation  .gif
  sticker    .webp

Options:
  --type <type>       Force a type: message|file|link|sticker|photo|video|audio|voice|animation
  --caption <text>    Caption for file/photo/video/audio/voice/animation
  --parse-mode <mode> Format mode: plain (default), markdown, html (message/link/caption)
  --markdown          Alias for --parse-mode markdown (uniform notify_send contract)
  --no-preview        Disable the link's web page preview (message/link only)
  --token <t>         Override token for one send
  --chat-id <id>      Override chat id for one send

Config file: $CONFIG_FILE
Keys: TELEGRAM_BOT_TOKEN | TELEGRAM_CHAT_ID

Precedence: CLI flags > environment > config file.

Examples:
  pos communication telegram sender send "Backup finished"
  pos communication telegram sender send "/path/to/report.pdf" --caption "Daily report"
  pos communication telegram sender send "/path/to/photo.jpg" --caption "Sunset"
  pos communication telegram sender send "/path/to/sticker.webp"
  pos communication telegram sender send "https://example.com" --no-preview
  pos communication telegram sender send "/path/to/video.mp4" --type video
  pos communication telegram sender test
EOF
    exit 0
}

err() { echo "ERROR: $*" >&2; exit 1; }

load_config() {
    [ -f "$CONFIG_FILE" ] || return 0
    local k v
    while IFS='=' read -r k v; do
        [ -n "$k" ] || continue
        case "$k" in
            \#*) continue ;;
        esac
        v="${v%\"}"; v="${v#\"}"; v="${v%\'}"; v="${v#\'}"
        if [ -z "${!k:-}" ]; then
            export "$k"="$v"
        fi
    done < <(grep -E '^[A-Z_]+=' "$CONFIG_FILE" || true)
}

mask_token() {
    local t="$1"
    [ -z "$t" ] && { echo "(not set)"; return; }
    if [ "${#t}" -le 12 ]; then
        echo "${t:0:4}... (${#t} chars)"
    else
        echo "${t:0:6}...${t: -4} (${#t} chars)"
    fi
}

send_request() {
    local endpoint="$1"; shift
    [ -z "${TELEGRAM_BOT_TOKEN:-}" ] && err "No bot token — run 'pos communication telegram config set TELEGRAM_BOT_TOKEN=...'"
    [ -z "${TELEGRAM_CHAT_ID:-}" ] && err "No chat id — run 'pos communication telegram config set TELEGRAM_CHAT_ID=...'"
    curl -fsS -m 60 -X POST "$API/bot${TELEGRAM_BOT_TOKEN}/${endpoint}" "$@" >/dev/null
}

send_message() {
    local text="$1" parse_mode="${2:-}" no_preview="${3:-}"
    local args=(--data-urlencode "chat_id=${TELEGRAM_CHAT_ID:-}" --data-urlencode "text=${text}")
    [ -n "$parse_mode" ] && args+=(--data-urlencode "parse_mode=${parse_mode}")
    [ "$no_preview" = "1" ] && args+=(--data-urlencode "disable_web_page_preview=true")
    send_request sendMessage "${args[@]}"
}

send_multipart() {
    local endpoint="$1" file_field="$2" file_path="$3" caption="${4:-}" parse_mode="${5:-}"
    [ -f "$file_path" ] && [ -r "$file_path" ] || err "File not found or unreadable: $file_path"
    local args=(-F "chat_id=${TELEGRAM_CHAT_ID:-}" -F "${file_field}=@${file_path}")
    [ -n "$caption" ] && args+=(-F "caption=${caption}")
    [ -n "$parse_mode" ] && args+=(-F "parse_mode=${parse_mode}")
    send_request "$endpoint" "${args[@]}"
}

detect_type() {
    local value="$1" ext
    if [ -f "$value" ] && [ -r "$value" ]; then
        ext="${value##*.}"
        ext="${ext,,}"
        case "$ext" in
            webp)        echo sticker ;;
            gif)         echo animation ;;
            jpg|jpeg|png|bmp) echo photo ;;
            mp4|mkv|webm|mov|avi|m4v) echo video ;;
            ogg|opus|oga) echo voice ;;
            mp3|wav|flac|m4a|aac) echo audio ;;
            *)           echo file ;;
        esac
    elif [[ "$value" =~ ^(https?://|www\.) ]]; then
        echo link
    else
        echo message
    fi
}

cmd_send() {
    local value="" type="" caption="" parse_mode="" no_preview=0 type_explicit=0 auto=""
    while [ $# -gt 0 ]; do
        case "$1" in
            --type)
                [ $# -ge 2 ] || err "--type needs a value"
                case "$2" in
                    message|file|link|sticker|photo|video|audio|voice|animation) type="$2" ;;
                    *) err "Unknown type '$2' (allowed: message, file, link, sticker, photo, video, audio, voice, animation)" ;;
                esac
                type_explicit=1
                shift 2 ;;
            --caption)
                [ $# -ge 2 ] || err "--caption needs a value"
                caption="$2"; shift 2 ;;
            --markdown)
                # Alias for --parse-mode markdown (uniform notify_send contract)
                parse_mode="markdown"; shift ;;
            --parse-mode)
                [ $# -ge 2 ] || err "--parse-mode needs a value"
                case "$2" in
                    plain|markdown|html) ;;
                    *) err "Unknown parse mode '$2' (allowed: plain, markdown, html)" ;;
                esac
                parse_mode="$2"; shift 2 ;;
            --no-preview)
                no_preview=1; shift ;;
            --token)
                [ $# -ge 2 ] || err "--token needs a value"
                TELEGRAM_BOT_TOKEN="$2"; shift 2 ;;
            --chat-id)
                [ $# -ge 2 ] || err "--chat-id needs a value"
                TELEGRAM_CHAT_ID="$2"; shift 2 ;;
            --)
                shift
                [ $# -ge 1 ] || err "No value given for send"
                value="$1"; shift
                [ $# -eq 0 ] || err "Unexpected argument '$1'"
                ;;
            -*) err "Unknown option '$1'" ;;
            *)
                [ -z "$value" ] || err "Unexpected extra argument '$1'"
                value="$1"; shift ;;
        esac
    done
    [ -n "$value" ] || err "No value given for send"

    if [ "$type_explicit" -eq 0 ]; then
        type="$(detect_type "$value")"
        auto=1
    fi

    case "$type" in
        message|link)
            [ -z "$caption" ] || err "--caption only applies to file/photo/video/audio/voice/animation"
            ;;
        sticker)
            [ -z "$caption" ] || err "--caption is not supported for stickers"
            ;;
    esac
    case "$type" in
        message|link) ;;
        *) [ "$no_preview" -eq 0 ] || err "--no-preview only applies to --type message or link" ;;
    esac
    [ "$parse_mode" = "plain" ] && parse_mode=""

    load_config
    case "$type" in
        message)   send_message "$value" "$parse_mode" "$no_preview" ;;
        link)      send_message "$value" "$parse_mode" "$no_preview" ;;
        file)      send_multipart sendDocument  document   "$value" "$caption" "$parse_mode" ;;
        sticker)   send_multipart sendSticker   sticker    "$value" "" "" ;;
        photo)     send_multipart sendPhoto     photo      "$value" "$caption" "$parse_mode" ;;
        video)     send_multipart sendVideo     video      "$value" "$caption" "$parse_mode" ;;
        audio)     send_multipart sendAudio     audio      "$value" "$caption" "$parse_mode" ;;
        voice)     send_multipart sendVoice     voice      "$value" "$caption" "$parse_mode" ;;
        animation) send_multipart sendAnimation animation "$value" "$caption" "$parse_mode" ;;
    esac
    echo "[+] $type${auto:+ (auto-detected)} sent to chat ${TELEGRAM_CHAT_ID}"
}

cmd_config() {
    load_config
    echo "Config: $CONFIG_FILE"
    echo "  TELEGRAM_BOT_TOKEN = $(mask_token "${TELEGRAM_BOT_TOKEN:-}")"
    echo "  TELEGRAM_CHAT_ID   = ${TELEGRAM_CHAT_ID:-}"
}

cmd_config_set() {
    local kv="$1"
    local key="${kv%%=*}"
    local val="${kv#*=}"
    case "$key" in
        TELEGRAM_BOT_TOKEN|TELEGRAM_CHAT_ID) ;;
        *) err "Unknown key '$key' (allowed: TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID)" ;;
    esac
    [ -z "$val" ] && err "No value given (expected $key=...)"

    mkdir -p "$CONFIG_DIR"
    if [ -f "$CONFIG_FILE" ]; then
        if grep -q "^${key}=" "$CONFIG_FILE"; then
            sed -i "s|^${key}=.*|${key}=${val}|" "$CONFIG_FILE"
        else
            echo "${key}=${val}" >>"$CONFIG_FILE"
        fi
    else
        echo "${key}=${val}" >"$CONFIG_FILE"
    fi
    chmod 600 "$CONFIG_FILE"
    echo "[+] $key saved to $CONFIG_FILE"
}

cmd="${1:-}"

case "$cmd" in
    -h|--help) usage ;;
    send)
        shift
        cmd_send "$@"
        ;;
    test)
        load_config
        send_message "Test message from pos $(date '+%Y-%m-%d %H:%M:%S')"
        echo "[+] test message sent to chat ${TELEGRAM_CHAT_ID}"
        ;;
    config)
        shift
        case "${1:-}" in
            set) shift; [ $# -eq 1 ] || usage; cmd_config_set "$1" ;;
            *) cmd_config ;;
        esac
        ;;
    *)
        echo "ERROR: Unknown telegram command '$cmd'"
        echo "Run 'pos communication telegram-sender --help' for usage."
        exit 1
        ;;
esac
