"""Forced channel-join membership check."""
import logging
from telegram import Bot
from telegram.error import BadRequest, Forbidden, TelegramError
from config import REQUIRED_CHANNEL_ID, FORCE_JOIN_STRICT

log = logging.getLogger(__name__)

# Treat all "present-in-chat" statuses as joined
OK_STATUSES = {"member", "administrator", "creator", "owner", "restricted"}
NOT_JOINED  = {"left", "kicked"}


async def is_member(bot: Bot, user_id: int) -> bool:
    """Return True if the user is joined, or if the channel check is misconfigured.

    Telegram returns "Chat not found" when REQUIRED_CHANNEL_ID is wrong, the bot is
    not added/admin in the channel, or the channel belongs to another bot context.
    By default we fail-open on those bot-side errors so real users/admins are not
    locked out. Set FORCE_JOIN_STRICT=true in .env to fail-closed after setup is OK.
    """
    if not REQUIRED_CHANNEL_ID:
        # No channel configured = gate disabled (intended).
        return True
    try:
        m = await bot.get_chat_member(REQUIRED_CHANNEL_ID, user_id)
    except BadRequest as e:
        msg = str(e)
        if "Chat not found" in msg or "chat not found" in msg:
            log.error(
                "REQUIRED_CHANNEL_ID is not reachable (%s). Users will be allowed until fixed. "
                "Fix: add the bot as ADMIN in the channel and set the real -100... channel ID.",
                e,
            )
            return False if FORCE_JOIN_STRICT else True
        log.warning("get_chat_member BadRequest for user %s (%s)", user_id, e)
        return False if FORCE_JOIN_STRICT else True
    except Forbidden as e:
        log.error(
            "Bot cannot access REQUIRED_CHANNEL_ID (%s). Users will be allowed until fixed. "
            "Fix: add/promote the bot as ADMIN in the required channel.",
            e,
        )
        return False if FORCE_JOIN_STRICT else True
    except TelegramError as e:
        # Network/API errors should not permanently lock out real users by default.
        log.warning(
            "get_chat_member failed for user %s (%s). FORCE_JOIN_STRICT=%s",
            user_id, e, FORCE_JOIN_STRICT,
        )
        return False if FORCE_JOIN_STRICT else True
    status = getattr(m, "status", "")
    if status in OK_STATUSES:
        return True
    if status in NOT_JOINED:
        return False
    # Unknown status → safer to require re-verification
    log.warning("Unknown chat-member status %r for user %s — treating as NOT joined", status, user_id)
    return False
