#!/usr/bin/env bash
#═══════════════════════════════════════════════════════════════════════════════
# setup-bridge.sh — міст Telegram ↔ Matrix (mautrix-telegram на Go, bridgev2) для Conduit
#
# Що робить:
#   1. Завантажує бінарник mautrix-telegram з GitHub Releases (перевірка sha256)
#   2. Створює користувача і /opt/mautrix-telegram, генерує config.yaml (-e) і підставляє ваші параметри
#   3. Генерує registration.yaml (-g) і показує, що надіслати в admin-кімнату Conduit
#   4. Створює службу systemd і запускає міст
#
# Передумова: Conduit встановлено й запущено (setup-conduit.sh)
# Потрібні: api_id та api_hash з https://my.telegram.org/apps (свої, безкоштовно)
#
# Використання:
#   chmod +x setup-bridge.sh
#   sudo ./setup-bridge.sh
#
# Інструкція: https://softomania.org.ua/100001-yak-pidnyati-sviy-matrix-server-conduit-bezkoshtovno-na-oracle-cloud.html
# Версія: 2026-10-12 · mautrix-telegram v26.09 (Go). Python-версія моста більше не підтримується.
#═══════════════════════════════════════════════════════════════════════════════
set -euo pipefail

RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'

log_info()  { echo -e "${GREEN}[INFO]${NC}  $*"; }
log_warn()  { echo -e "${YELLOW}[WARN]${NC}  $*"; }
log_error() { echo -e "${RED}[ERROR]${NC} $*"; }
log_step()  { echo -e "\n${CYAN}${BOLD}══════ $* ══════${NC}\n"; }

ask() {
    local prompt="$1" default="${2:-}" result
    if [[ -n "$default" ]]; then
        read -rp "$(echo -e "${BOLD}${prompt}${NC} [${default}]: ")" result
        echo "${result:-$default}"
    else
        while true; do
            read -rp "$(echo -e "${BOLD}${prompt}${NC}: ")" result
            [[ -n "$result" ]] && break
            log_warn "Значення не може бути порожнім"
        done
        echo "$result"
    fi
}

ask_yn() {
    local prompt="$1" result
    read -rp "$(echo -e "${BOLD}${prompt}${NC} [y/N]: ")" result
    [[ "$result" =~ ^[Yy]$ ]]
}

check_root() {
    [[ $EUID -eq 0 ]] || { log_error "Запускайте від root: sudo ./setup-bridge.sh"; exit 1; }
}

# ─── Налаштування ─────────────────────────────────────────────────────────────
BRIDGE_USER="mautrix-telegram"
BRIDGE_DIR="/opt/mautrix-telegram"
BRIDGE_BIN="${BRIDGE_DIR}/mautrix-telegram"
BRIDGE_CONFIG="${BRIDGE_DIR}/config.yaml"
BRIDGE_REG="${BRIDGE_DIR}/registration.yaml"
BRIDGE_DB="${BRIDGE_DIR}/mautrix-telegram.db"
RELEASES="https://github.com/mautrix/telegram/releases/latest/download"
CONDUIT_PORT="6167"

DOMAIN=""
ADMIN_USER=""
TG_API_ID=""
TG_API_HASH=""
BRIDGE_PORT="29317"

get_arch() {
    case "$(uname -m)" in
        x86_64)  echo "amd64" ;;
        aarch64) echo "arm64" ;;
        armv7l)  echo "arm" ;;
        *) log_error "Непідтримувана архітектура: $(uname -m)"; exit 1 ;;
    esac
}

# ═══════════════════════════════════════════════════════════════════════════════
# Крок 0: параметри
# ═══════════════════════════════════════════════════════════════════════════════
collect_params() {
    log_step "Крок 0: Параметри моста"

    if [[ -f /etc/matrix-conduit/.install-params ]]; then
        # shellcheck disable=SC1091
        source /etc/matrix-conduit/.install-params
        log_info "Знайдено параметри setup-conduit.sh: DOMAIN=${DOMAIN}"
    fi

    if ! systemctl is-active --quiet conduit 2>/dev/null; then
        log_error "Conduit не запущено. Спочатку виконайте setup-conduit.sh"
        exit 1
    fi
    if ! curl -sf "http://127.0.0.1:${CONDUIT_PORT}/_matrix/client/versions" > /dev/null; then
        log_error "Conduit API не відповідає на порту ${CONDUIT_PORT}"
        exit 1
    fi
    log_info "✅ Conduit API працює"

    DOMAIN=$(ask "Домен (server_name із conduit.toml)" "${DOMAIN:-}")

    echo ""
    echo "  Matrix ID адміністратора моста — ваш обліковий запис на цьому сервері (формат @ім’я:${DOMAIN})."
    ADMIN_USER=$(ask "Matrix ID адміністратора" "@admin:${DOMAIN}")

    echo ""
    log_info "Ключі Telegram API: https://my.telegram.org/apps → API development tools → Create application"
    while true; do
        TG_API_ID=$(ask "Telegram api_id (число)")
        [[ "$TG_API_ID" =~ ^[0-9]+$ ]] && break
        log_warn "api_id — це число"
    done
    while true; do
        TG_API_HASH=$(ask "Telegram api_hash (32 символи)")
        [[ "$TG_API_HASH" =~ ^[0-9a-fA-F]{32}$ ]] && break
        log_warn "api_hash — 32 шістнадцяткові символи"
    done

    echo ""
    BRIDGE_PORT=$(ask "Порт моста (слухає лише локально)" "${BRIDGE_PORT}")

    log_step "Зведення"
    echo "  Домен:        ${DOMAIN}"
    echo "  Адмін:        ${ADMIN_USER}"
    echo "  api_id:       ${TG_API_ID}"
    echo "  api_hash:     ${TG_API_HASH:0:6}…"
    echo "  Порт моста:   ${BRIDGE_PORT}"
    echo "  Каталог:      ${BRIDGE_DIR}"
    echo ""
    ask_yn "Починаємо встановлення?" || exit 0
}

# ═══════════════════════════════════════════════════════════════════════════════
# Крок 1: бінарник
# ═══════════════════════════════════════════════════════════════════════════════
install_bridge() {
    log_step "Крок 1: Бінарник mautrix-telegram"

    log_info "Встановлюю залежності (curl, python3-yaml для правки конфігу)…"
    apt-get update -qq
    apt-get install -y -qq curl python3 python3-yaml > /dev/null

    if id "$BRIDGE_USER" &>/dev/null; then
        log_info "Користувач ${BRIDGE_USER} вже є"
    else
        log_info "Створюю користувача ${BRIDGE_USER}…"
        adduser --system --home "$BRIDGE_DIR" --group "$BRIDGE_USER"
    fi
    mkdir -p "$BRIDGE_DIR"

    local arch tmp
    arch=$(get_arch)
    tmp=$(mktemp -d)
    log_info "Завантажую mautrix-telegram-${arch} з ${RELEASES}…"
    curl -fsSL -o "${tmp}/mautrix-telegram" "${RELEASES}/mautrix-telegram-${arch}"
    curl -fsSL -o "${tmp}/sha256sums.txt" "${RELEASES}/sha256sums.txt"

    local expected actual
    expected=$(grep "mautrix-telegram-${arch}\$" "${tmp}/sha256sums.txt" | awk '{print $1}')
    actual=$(sha256sum "${tmp}/mautrix-telegram" | awk '{print $1}')
    if [[ -z "$expected" || "$expected" != "$actual" ]]; then
        log_error "sha256 не збігається (очікувано ${expected:-?}, отримано ${actual}). Завантаження пошкоджене — зупиняюся."
        rm -rf "$tmp"
        exit 1
    fi
    log_info "✅ sha256 збігається"

    if systemctl is-active --quiet mautrix-telegram 2>/dev/null; then
        systemctl stop mautrix-telegram
    fi
    install -m 0755 "${tmp}/mautrix-telegram" "$BRIDGE_BIN"
    rm -rf "$tmp"
    chown -R "${BRIDGE_USER}:${BRIDGE_USER}" "$BRIDGE_DIR"

    log_info "✅ $("$BRIDGE_BIN" --version 2>/dev/null | head -1 || echo 'бінарник встановлено')"
}

# ═══════════════════════════════════════════════════════════════════════════════
# Крок 2: конфіг
# ═══════════════════════════════════════════════════════════════════════════════
configure_bridge() {
    log_step "Крок 2: Конфігурація"

    if [[ -f "$BRIDGE_CONFIG" ]]; then
        cp "$BRIDGE_CONFIG" "${BRIDGE_CONFIG}.bak.$(date +%s)"
        log_warn "config.yaml уже був — зроблено резервну копію"
    fi

    log_info "Генерую приклад конфігу (mautrix-telegram -e)…"
    sudo -u "$BRIDGE_USER" "$BRIDGE_BIN" -c "$BRIDGE_CONFIG" -e > /dev/null

    log_info "Підставляю параметри…"
    BRIDGE_CONFIG="$BRIDGE_CONFIG" DOMAIN="$DOMAIN" ADMIN_USER="$ADMIN_USER" TG_API_ID="$TG_API_ID" TG_API_HASH="$TG_API_HASH" \
    BRIDGE_PORT="$BRIDGE_PORT" BRIDGE_DB="$BRIDGE_DB" CONDUIT_PORT="$CONDUIT_PORT" \
    python3 - <<'PY'
import os, yaml

path = os.environ["BRIDGE_CONFIG"]
with open(path, encoding="utf-8") as f:
    cfg = yaml.safe_load(f) or {}

def section(name):
    cfg.setdefault(name, {})
    return cfg[name]

hs = section("homeserver")
hs["address"] = f"http://127.0.0.1:{os.environ['CONDUIT_PORT']}"
hs["domain"] = os.environ["DOMAIN"]
hs["software"] = "standard"

aps = section("appservice")
aps["address"] = f"http://127.0.0.1:{os.environ['BRIDGE_PORT']}"
aps["hostname"] = "127.0.0.1"
aps["port"] = int(os.environ["BRIDGE_PORT"])
aps["id"] = "telegram"
aps.setdefault("bot", {})["username"] = "telegrambot"

db = section("database")
db["type"] = "sqlite3-fk-wal"
db["uri"] = f"file:{os.environ['BRIDGE_DB']}?_txlock=immediate"

# Telegram: у bridgev2 ключі мережі лежать у секції network; у старих прикладах — на верхньому рівні
net = cfg["network"] if isinstance(cfg.get("network"), dict) else cfg
net["api_id"] = int(os.environ["TG_API_ID"])
net["api_hash"] = os.environ["TG_API_HASH"]

bridge = section("bridge")
bridge["permissions"] = {"*": "relay", os.environ["DOMAIN"]: "user", os.environ["ADMIN_USER"]: "admin"}
relay = bridge.setdefault("relay", {})
relay["enabled"] = True
relay["admin_only"] = True

enc = section("encryption")
enc["allow"] = True

with open(path, "w", encoding="utf-8") as f:
    yaml.safe_dump(cfg, f, allow_unicode=True, sort_keys=False, default_flow_style=False)
print("config.yaml оновлено")
PY

    chown "${BRIDGE_USER}:${BRIDGE_USER}" "$BRIDGE_CONFIG"
    chmod 600 "$BRIDGE_CONFIG"
    log_info "✅ Конфіг записано: ${BRIDGE_CONFIG}"
}

# ═══════════════════════════════════════════════════════════════════════════════
# Крок 3: реєстрація appservice у Conduit
# ═══════════════════════════════════════════════════════════════════════════════
register_appservice() {
    log_step "Крок 3: Реєстрація в Conduit"

    log_info "Генерую registration.yaml (mautrix-telegram -g)…"
    sudo -u "$BRIDGE_USER" "$BRIDGE_BIN" -c "$BRIDGE_CONFIG" -r "$BRIDGE_REG" -g > /dev/null
    chmod 600 "$BRIDGE_REG"

    echo ""
    echo -e "${BOLD}Conduit читає реєстрацію НЕ з файлу, а з admin-кімнати.${NC}"
    echo "Відкрийте в Element кімнату #admins:${DOMAIN} (ви в ній як перший користувач) і надішліть ОДНИМ повідомленням:"
    echo ""
    echo -e "${CYAN}@conduit:${DOMAIN}: register-appservice${NC}"
    echo -e "${CYAN}\`\`\`${NC}"
    cat "$BRIDGE_REG"
    echo -e "${CYAN}\`\`\`${NC}"
    echo ""
    echo "Перевірка — надішліть у ту саму кімнату:  @conduit:${DOMAIN}: list-appservices"
    echo "Очікувана відповідь: Appservices (1): telegram"
    echo ""
    echo "Файл для копіювання: ${BRIDGE_REG}  (cat ${BRIDGE_REG})"
    echo ""
    while ! ask_yn "Appservice зареєстровано в admin-кімнаті? Продовжити запуск моста?"; do
        log_warn "Зареєструйте appservice і поверніться сюди (Ctrl+C — перервати; запуск потім: sudo systemctl start mautrix-telegram)"
    done
}

# ═══════════════════════════════════════════════════════════════════════════════
# Крок 4: systemd
# ═══════════════════════════════════════════════════════════════════════════════
setup_systemd() {
    log_step "Крок 4: Служба systemd"

    cat > /etc/systemd/system/mautrix-telegram.service <<UNIT
[Unit]
Description=mautrix-telegram bridge (Go)
After=network-online.target conduit.service
Wants=network-online.target

[Service]
User=${BRIDGE_USER}
Group=${BRIDGE_USER}
WorkingDirectory=${BRIDGE_DIR}
ExecStart=${BRIDGE_BIN} -c ${BRIDGE_CONFIG} -r ${BRIDGE_REG}
Restart=on-failure
RestartSec=5
Environment=HOME=${BRIDGE_DIR}

ProtectSystem=strict
ProtectHome=true
ReadWritePaths=${BRIDGE_DIR}
PrivateTmp=true
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target
UNIT

    systemctl daemon-reload
    systemctl enable --now mautrix-telegram
    sleep 3

    if systemctl is-active --quiet mautrix-telegram; then
        log_info "✅ mautrix-telegram запущено"
    else
        log_error "Міст не запустився. Останні рядки логу:"
        journalctl -u mautrix-telegram -n 20 --no-pager
        log_warn "Типові причини: appservice не зареєстровано в admin-кімнаті, помилка в api_id/api_hash, зайнятий порт ${BRIDGE_PORT}"
    fi
}

final_checks() {
    log_step "Фінальна перевірка"

    systemctl is-active --quiet conduit && log_info "✅ conduit — працює" || log_error "❌ conduit — не працює"
    systemctl is-active --quiet mautrix-telegram && log_info "✅ mautrix-telegram — працює" || log_error "❌ mautrix-telegram — не працює"
    if ss -tlnp | grep -q ":${BRIDGE_PORT} "; then
        log_info "✅ Порт ${BRIDGE_PORT} (міст) — слухає"
    else
        log_error "❌ Порт ${BRIDGE_PORT} — не слухає"
    fi

    echo ""
    log_step "🎉 Міст налаштовано"
    echo -e "${BOLD}Як увійти в Telegram через міст:${NC}"
    echo "  1. В Element відкрийте особистий чат із @telegrambot:${DOMAIN}"
    echo "  2. Надішліть:  login phone +380XXXXXXXXX   (код прийде в інший клієнт Telegram, не SMS)"
    echo "     або:        login qr                    (Telegram → Settings → Devices → Link Desktop Device)"
    echo "  3. Якщо є пароль 2FA — надішліть його в той самий чат, коли бот попросить"
    echo "  4. help — список команд моста; чати Telegram з’являться як кімнати Matrix"
    echo ""
    echo -e "${BOLD}Корисне:${NC}"
    echo "  journalctl -u mautrix-telegram -f     # логи моста"
    echo "  sudo systemctl restart mautrix-telegram"
    echo "  Оновлення: завантажте новий ${RELEASES}/mautrix-telegram-$(get_arch) у ${BRIDGE_BIN} і перезапустіть службу"
    echo ""
    echo -e "${BOLD}Файли:${NC}"
    echo "  Конфіг:        ${BRIDGE_CONFIG}"
    echo "  Реєстрація:    ${BRIDGE_REG}"
    echo "  База моста:    ${BRIDGE_DB}"
}

main() {
    echo ""
    echo -e "${CYAN}${BOLD}"
    echo "  ╔═══════════════════════════════════════════════════════╗"
    echo "  ║  mautrix-telegram (Go) — встановлювач для Conduit     ║"
    echo "  ╚═══════════════════════════════════════════════════════╝"
    echo -e "${NC}"

    check_root
    collect_params
    install_bridge
    configure_bridge
    register_appservice
    setup_systemd
    final_checks
}

main "$@"
