from __future__ import annotations

import logging

import discord
from discord.ext import commands

from bot import commands as bot_commands
from bot import embeds as em
from db import store

logger = logging.getLogger("bot.client")


def build_bot(db, cfg) -> discord.Client:
    intents = discord.Intents.default()
    bot = commands.Bot(command_prefix="!", intents=intents)

    async def setup_hook() -> None:
        await bot_commands.setup_commands(bot, db, cfg)
        await bot.tree.sync()

    bot.setup_hook = setup_hook
    return bot


def target_channels(guild_cfg: dict | None) -> tuple[int | None, int | None]:
    cfg = guild_cfg or {}
    return (cfg.get("hits_channel_id"), cfg.get("logs_channel_id"))


async def _send(bot, channel_id: int | None, embed: discord.Embed) -> None:
    if not channel_id:
        return
    channel = bot.get_channel(channel_id)
    if channel is None:
        try:
            channel = await bot.fetch_channel(channel_id)
        except discord.DiscordException:
            logger.warning("could not resolve channel %s", channel_id)
            return
    try:
        await channel.send(embed=embed)
    except discord.DiscordException:
        logger.warning("failed to send to channel %s", channel_id, exc_info=True)


async def dispatch_result(bot, guild_id, db, result) -> None:
    guild_cfg = await store.get_guild_config(db, guild_id) if guild_id else None
    hits_channel_id, logs_channel_id = target_channels(guild_cfg)

    if result.authenticated:
        await _send(bot, hits_channel_id, em.hits_embed(result))

    status = "success" if result.authenticated else "failed"
    await _send(
        bot,
        logs_channel_id,
        em.logs_embed(guild_id, result.discord_user_id, result.method, status, result.fail_reason),
    )
