"""
Decision tree / dispatcher.

Routing:

  0. `my_chat_member` update (bot's own membership in a chat changed) ->
     detect a fresh add to a group and ask its admin for a referral link.
  1. Private chat -> first match wins:
       /start                          -> channel-membership check
       callback check_membership       -> re-check membership
       main-menu "price" button        -> ask for a coin name/symbol
       main-menu "earn" button         -> add-to-group instructions
       main-menu "explorer" button     -> ask which blockchain network
       main-menu "alert" button        -> no-op (not implemented yet)
       callback explorer_network:*     -> ask for a tx hash on that network
       pending explorer tx-hash reply  -> consume as the hash, look it up
       pending referral-link reply     -> consume as the link
       any other text                  -> price/amount request
  2. Group or supergroup, while `config.GROUP_PRICE_ENABLED` is on -> first
     match wins:
       pending referral-link reply (from the admin who was asked) -> consume
       any other text starting with "/" -> ignored
       any text containing a recognizable coin name -> compact price reply
       everything else -> ignored
  3. Anything else -> ignored.
"""

from .. import config, messages
from . import handlers


def _get(d, *path):
    cur = d
    for key in path:
        if not isinstance(cur, dict):
            return None
        cur = cur.get(key)
    return cur


def _chat_type(update: dict):
    return (
        _get(update, "message", "chat", "type")
        or _get(update, "callback_query", "message", "chat", "type")
    )


def _private_intent(update: dict) -> None:
    """First-level switch (first match wins)."""
    text = _get(update, "message", "text")
    data = _get(update, "callback_query", "data")
    chat_id = _get(update, "message", "chat", "id")
    sender_id = _get(update, "message", "from", "id")

    if text == "/start":
        handlers.check_membership_for_start(update)
    elif data == "check_membership":
        handlers.check_membership_for_callback(update)
    elif text == messages.MENU_PRICE_BUTTON_TEXT:
        handlers.handle_price_menu_button(update)
    elif text == messages.MENU_EARN_BUTTON_TEXT:
        handlers.handle_earn_button(update)
    elif text == messages.MENU_EXPLORER_BUTTON_TEXT:
        handlers.handle_explorer_menu_button(update)
    elif text == messages.MENU_PRICE_ALERT_BUTTON_TEXT:
        pass  # not implemented yet
    elif data is not None and data.startswith("explorer_network:"):
        handlers.handle_explorer_network_selected(update)
    elif text is not None and handlers.handle_explorer_hash_reply(update, chat_id, text):
        pass  # consumed as a tx-hash reply
    elif text is not None and handlers.handle_referral_link_reply(update, chat_id, sender_id, text):
        pass  # consumed as a referral-link reply
    elif text is not None:  # any other text => a price/amount request
        handlers.handle_price_lookup(update)


def _group_intent(update: dict) -> None:
    """Group / supergroup flow: reply with a price only if the text names a coin."""
    text = _get(update, "message", "text")
    chat_id = _get(update, "message", "chat", "id")
    sender_id = _get(update, "message", "from", "id")

    if text and handlers.handle_referral_link_reply(update, chat_id, sender_id, text):
        return  # consumed as a referral-link reply

    if not text or text.startswith("/"):
        return
    handlers.handle_group_price_lookup(update)


def dispatch(update: dict) -> None:
    """Entry point for a single incoming update."""
    if "my_chat_member" in update:
        handlers.handle_bot_added_to_group(update)
        return

    chat_type = _chat_type(update)

    if chat_type == "private":
        _private_intent(update)
        return

    if chat_type in ("group", "supergroup") and config.GROUP_PRICE_ENABLED:
        _group_intent(update)
        return
