#!/bin/bash
# ─────────────────────────────────────────────────────────────────
#  patch-remnashop-hwid-useruuid.sh
#  Патч совместимости Remnashop 0.8.2 с новым контрактом панели
#  Remnawave по HWID-устройствам.
# ─────────────────────────────────────────────────────────────────
#
#  Проблема: в свежей версии панели Remnawave в таблице
#  hwid_user_devices столбец `userUuid` переименован в `userId`
#  (BigInt). Соответственно в JSON ответа эндпоинта
#  GET /api/hwid/devices/{uuid} поля `userUuid` больше нет.
#
#  Модель SDK remnapy 2.7.0 (HwidDeviceDto) требует `userUuid`
#  как обязательное поле без default:
#      user_uuid: UUID = Field(alias="userUuid")
#  → pydantic роняет ValidationError ("devices.0.userUuid
#  Field required") при разборе ответа, и падает рендер экрана
#  MainMenu:DEVICES. Проявляется только когда у пользователя есть
#  ≥1 устройство (пустой список валидируется без ошибок).
#
#  Поднять remnapy нельзя: на текущем HEAD коммит тот же (95e15ed),
#  поле не переименовано, поддержки `userId` в SDK пока нет.
#
#  Remnashop поле user_uuid/user_id устройства нигде не читает
#  (используются только hwid, platform, device_model, user_agent,
#  created_at), поэтому достаточно сделать поле необязательным.
#
#  Что делает скрипт:
#    1. remnapy/models/hwid.py — в классе HwidDeviceDto делает
#       user_uuid опциональным и добавляет новое поле user_id:
#           user_uuid: Optional[UUID] = Field(None, alias="userUuid")
#           user_id:   Optional[int]  = Field(None, alias="userId")
#       Валидация проходит на любой версии панели (старой с
#       userUuid и новой с userId). Покрывает все три места, где
#       парсится HwidDeviceDto: get_hwid_user, delete_hwid_to_user,
#       delete_all_hwid_user.
#    2. Сброс __pycache__ для models/hwid.py
#    3. Перезапуск всех контейнеров remnashop
#
#  ⚠️  Патч живёт внутри контейнера (правит файл в venv) и пропадёт
#      при пересборке/обновлении образа. Постоянное решение —
#      форк remnapy с этой правкой и пин на свой git rev, либо
#      обновление remnapy, когда автор поддержит `userId`.
#
#  Идемпотентность: скрипт можно прогонять повторно — уже
#  применённый патч пропускается.
#
#  Использование:
#    chmod +x patch-remnashop-hwid-useruuid.sh && ./patch-remnashop-hwid-useruuid.sh
# ─────────────────────────────────────────────────────────────────

set -e

CONTAINERS=(remnashop remnashop-taskiq-worker remnashop-taskiq-scheduler)

echo "🔧 Патч Remnashop: HwidDeviceDto.userUuid → optional (+ userId)"
echo ""

# ──────────────────────────────────────────────────────────────────
#  Блок 1: правка модели HwidDeviceDto во всех контейнерах
# ──────────────────────────────────────────────────────────────────

echo "[1/2] remnapy/models/hwid.py — user_uuid → optional, +user_id..."

patch_hwid() {
  local C="$1"
  echo "  → $C"
  docker exec -i "$C" python3 - << 'PYEOF'
import os

# Локализуем файл модели через сам пакет — не хардкодим путь с версией Python.
try:
    import remnapy
except ImportError:
    print("    ⚠️  remnapy не установлен в этом контейнере — пропускаем")
    raise SystemExit(0)

path = os.path.join(os.path.dirname(remnapy.__file__), "models", "hwid.py")

with open(path) as f:
    content = f.read()

# Маркер уже применённого патча
PATCHED_MARKER = 'user_id: Optional[int] = Field(None, alias="userId")'

# Старый блок: матчим вместе с заголовком класса и полем hwid,
# чтобы зацепить именно HwidDeviceDto, а НЕ TopUserByHwidDevicesDto
# (там та же строка user_uuid, но другое окружение).
old_block = '''class HwidDeviceDto(BaseModel):
    hwid: str
    user_uuid: UUID = Field(alias="userUuid")'''

new_block = '''class HwidDeviceDto(BaseModel):
    hwid: str
    # Панель переименовала userUuid → userId (BigInt); делаем оба поля
    # опциональными для совместимости со старым и новым контрактом.
    user_uuid: Optional[UUID] = Field(None, alias="userUuid")
    user_id: Optional[int] = Field(None, alias="userId")'''

if PATCHED_MARKER in content:
    print("    ~ уже применено — пропускаем")
elif old_block in content:
    content = content.replace(old_block, new_block, 1)
    with open(path, "w") as f:
        f.write(content)
    print("    ✓ HwidDeviceDto.user_uuid → Optional, добавлено user_id")
else:
    print("    ⚠️  Ожидаемый блок HwidDeviceDto не найден!")
    print("    ⚠️  Возможно, версия remnapy отличается от 2.7.0.")
    print("    ⚠️  Применять патч автоматически небезопасно — выходим.")
    raise SystemExit(1)

# Сброс кэша байт-кода для models/hwid.py
import glob
cache_dir = os.path.join(os.path.dirname(path), "__pycache__")
for pyc in glob.glob(os.path.join(cache_dir, "hwid.*.pyc")):
    os.remove(pyc)
    print(f"    ✓ Удалён кэш: {os.path.basename(pyc)}")
PYEOF
}

for C in "${CONTAINERS[@]}"; do
  patch_hwid "$C"
done

# ──────────────────────────────────────────────────────────────────
#  Блок 2: перезапуск контейнеров
# ──────────────────────────────────────────────────────────────────

echo "[2/2] Перезапуск контейнеров..."
for C in remnashop-taskiq-scheduler remnashop-taskiq-worker remnashop; do
  echo "  → $C"
  docker restart "$C" > /dev/null
done

echo ""
echo "✅ Готово! Патч применён, все контейнеры перезапущены."
echo ""
echo "   Проверить: открой в боте меню «Устройства» у пользователя,"
echo "   у которого есть хотя бы одно устройство — экран должен"
echo "   отрендериться без падения."
echo ""
echo "   В логах основного контейнера НЕ должно быть:"
echo "     ValidationError ... devices.0.userUuid ... Field required"
echo "   docker logs -f remnashop 2>&1 | grep -i 'userUuid\\|ValidationError'"
