import asyncio
import logging

import safe_radix32
from clarabot_nano_common.common.error import maybe_rad32
from clarabot_nano_common.gateway.utility import check_single_response, GatewayServerError

from clarabot_nano.gateway.errors import SERVER_ERROR_NO_SESSION_BIND, SERVER_ERROR_TOO_MANY_REQUESTS
from clarabot_nano.gateway.state.gateway import GatewayState

logger = logging.getLogger(__name__)


async def state_miscellaneous_job(gws: GatewayState, job_queue: asyncio.Queue):
    """
    Processing of data that is not critical.
    """
    while True:
        job = await job_queue.get()
        t = job["type"]
        if t == "load-avatar":
            await _load_avatar(gws, job["id"], job["future"])
        else:
            raise Exception(f"Unknown miscellaneous job: {t}")


async def _load_avatar(gws: GatewayState, account_id: int, result_future: asyncio.Future):
    """
    Request a user-friendly avatar name and image-key from the server for an account.
    Errors are ignored, this is not a mission-critical data.
    """
    avatar = None
    try:
        async with gws.server_request({"type": "account-avatar", "account_id": account_id}) as future:
            resp = check_single_response(await future, dict, "query account avatar")
        if isinstance(name := resp.get("name"), str):
            name = name[:48]  # limit length for safety; currently server has a lower limit (32)
            image_key = resp.get("image_key")
            if isinstance(image_key, int):
                try:
                    image_key = safe_radix32.encode_fw(image_key)
                except Exception:
                    image_key = None
            else:
                image_key = None
            avatar = (name, image_key)
        else:
            avatar = ("", None)  # cache marker to avoid frequent repeated queries
    except GatewayServerError as e:
        if e.error in (SERVER_ERROR_NO_SESSION_BIND, SERVER_ERROR_TOO_MANY_REQUESTS):
            pass
        else:
            logger.exception(f"Error while loading account avatar name ({maybe_rad32(account_id)})")
    except Exception:
        logger.exception(f"Error while loading account avatar name ({maybe_rad32(account_id)})")
    finally:
        if not result_future.done():
            result_future.set_result(avatar)
        if avatar is not None:
            gws.avatar_cache[account_id] = avatar
