import json
import time
import urllib.parse
import urllib.request

# Telegram bot token (provided by BotFather)
TOKEN = "8588784310:AAG4H41x39kX8bskkBWxB9lyVAfTjHAnR1g"
API_ROOT = f"https://api.telegram.org/bot{TOKEN}"

# Basic links for replies
TWITCH_LINK = "https://www.twitch.tv/obn4l"
# Public HTTPS for WebApp (GitHub Pages or other host)
WEBAPP_URL = "https://runvasarun128-del.github.io/tg-webapp/tg-webapp.html"
# Telegram channel to check subscription for.
# Use channel username like "@your_channel" or numeric id like -1001234567890.
# The bot must be admin in the channel to check members.
CHANNEL_ID = -1002436946838


def is_https(url: str) -> bool:
    return url.lower().startswith("https://")


def api(method: str, params: dict | None = None) -> dict:
    """Call Telegram Bot API with standard library only; print body on HTTP errors."""
    url = f"{API_ROOT}/{method}"
    data = None
    if params:
        data = urllib.parse.urlencode(params).encode()
    req = urllib.request.Request(url, data=data)
    try:
        with urllib.request.urlopen(req, timeout=60) as resp:
            return json.loads(resp.read().decode())
    except urllib.error.HTTPError as e:
        body = e.read().decode(errors="replace")
        print(f"HTTPError {e.code} on {method}: {body}")
        raise


def send_message(chat_id: int, text: str, reply_markup: dict | None = None):
    params = {
        "chat_id": chat_id,
        "text": text,
        "parse_mode": "HTML",
    }
    if reply_markup:
        params["reply_markup"] = json.dumps(reply_markup, ensure_ascii=False)
    api("sendMessage", params)


def get_chat_member(user_id: int) -> dict:
    return api("getChatMember", {"chat_id": CHANNEL_ID, "user_id": user_id})


def is_subscribed(user_id: int) -> bool:
    info = get_chat_member(user_id)
    status = (info.get("result") or {}).get("status", "")
    return status in {"creator", "administrator", "member"}


def handle_update(update: dict):
    channel_post = update.get("channel_post") or update.get("edited_channel_post")
    if channel_post:
        chat = channel_post.get("chat", {})
        print(f"Channel detected: id={chat.get('id')}, title={chat.get('title')}, username={chat.get('username')}")
        return

    callback = update.get("callback_query")
    if callback:
        user_id = callback["from"]["id"]
        chat_id = callback["message"]["chat"]["id"]
        data = callback.get("data")
        if data == "check_tg":
            try:
                ok = is_subscribed(user_id)
                send_message(chat_id, f"Telegram subscription: {'OK' if ok else 'NOT SUBSCRIBED'}")
            except Exception as e:  # noqa: BLE001
                send_message(chat_id, f"Check failed: {e}")
        api("answerCallbackQuery", {"callback_query_id": callback["id"]})
        return

    message = update.get("message") or update.get("edited_message")
    if not message:
        return
    chat_id = message["chat"]["id"]
    text = message.get("text", "") or ""

    if text.startswith("/start"):
        kb_rows = [
            [{"text": "Twitch obn4l", "url": TWITCH_LINK}],
            [{"text": "Check Telegram subscription", "callback_data": "check_tg"}],
        ]
        if is_https(WEBAPP_URL):
            kb_rows.append([{"text": "Open WebApp", "web_app": {"url": WEBAPP_URL}}])
        else:
            kb_rows.append([{"text": "Open WebApp (HTTPS required)", "url": WEBAPP_URL}])
        keyboard = {"inline_keyboard": kb_rows}
        send_message(chat_id, "Hi! Use the buttons below.", reply_markup=keyboard)
    elif text.startswith("/check"):
        try:
            ok = is_subscribed(message["from"]["id"])
            send_message(chat_id, f"Telegram subscription: {'OK' if ok else 'NOT SUBSCRIBED'}")
        except Exception as e:  # noqa: BLE001
            send_message(chat_id, f"Check failed: {e}")
    else:
        send_message(chat_id, "OK. Try /check.")


def delete_webhook():
    """Ensure long polling works even if webhook was set earlier."""
    try:
        api("deleteWebhook", {"drop_pending_updates": False})
    except Exception as e:  # noqa: BLE001
        print(f"deleteWebhook warning: {e}")


def main():
    offset = 0
    print("Bot started. Press Ctrl+C to stop.")
    delete_webhook()
    while True:
        try:
            updates = api(
                "getUpdates",
                {
                    "timeout": 25,
                    "offset": offset,
                },
            )
            if not updates.get("ok", False):
                time.sleep(2)
                continue
            for upd in updates.get("result", []):
                offset = max(offset, upd["update_id"] + 1)
                handle_update(upd)
        except KeyboardInterrupt:
            print("Stopped by user.")
            break
        except Exception as e:  # noqa: BLE001
            print(f"Error: {e}")
            time.sleep(2)


if __name__ == "__main__":
    main()
