"""Discord cogs for recruiter workflows and manual user sync actions.

This module intentionally keeps recruitment-thread commands and user-sync commands
in separate cogs to keep responsibilities clear.
"""

import logging

import discord
from discord.embeds import Embed
from discord.ext import commands
from django.conf import settings
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from .. import app_settings
from ..tasks import sync_user_esi_and_discord

logger = logging.getLogger(__name__)


def _get_auth_user_from_discord_user_id(discord_user_id: int):
    """Resolve an Alliance Auth user from a Discord user ID.

    Returns None when Discord service is unavailable or no linked account exists.
    """
    try:
        from allianceauth.services.modules.discord.models import DiscordUser  # pylint: disable=import-outside-toplevel
    except ModuleNotFoundError:
        return None

    linked = DiscordUser.objects.filter(uid=discord_user_id).select_related("user").first()
    return linked.user if linked else None


class RecruitmentThreadCommands(commands.Cog):
    """Commands that create and manage recruitment discussion threads."""

    def __init__(self, bot):
        self.bot = bot

    async def open_ticket(self, ctx: discord.Interaction, member: discord.Member):
        """Create a private recruitment thread and post onboarding guidance."""

        sup_channel = settings.RECRUIT_CHANNEL_ID
        ch = ctx.guild.get_channel(sup_channel)
        th = await ch.create_thread(
            name=f"{member.display_name} | {timezone.now().strftime('%Y-%m-%d %H:%M')}",
            auto_archive_duration=10080,
            type=discord.ChannelType.private_thread,
            reason=None
        )
        msg = (f"<@{member.id}> recherche un recruteur !\n\n"
               f"Quelqu'un du groupe <@&{settings.RECRUITER_GROUP_ID}> te contactera rapidement !")
        embd = Embed(
            title="Guide des Fils de Recrutement",
            description="Pour ajouter une personne à ce fil vous pouvez simplement les '@ping'. Cela fonctionne avec les `@groupes` aussi pour ajouter plusieurs personnes d'un seul coup. Utilisez ça avec sagesse, aucun abus ne sera toléré.\n\nCeci est une fonction en béta, si vous rencontrez des ennuis veuillez contacter l'admin. :heart:"
        )

        await th.send(msg, embed=embd)
        await ctx.response.send_message(content=_("Fil de recrutement créé !"), view=None, ephemeral=True)

    @commands.slash_command(
        name="me_recruter",
        guild_ids=app_settings.get_all_servers()
    )
    async def slash_halp(self, ctx):
        """Create a recruitment thread for the command author."""

        await self.open_ticket(ctx, ctx.user)

    @commands.message_command(
        name="Créer un fil de recrutement",
        guild_ids=app_settings.get_all_servers()
    )
    async def reverse_recruit_msg_context(self, ctx, message):
        """Create a recruitment thread for the author of the selected message."""

        await self.open_ticket(ctx, message.author)

    @commands.user_command(
        name="Me Recruter",
        guild_ids=app_settings.get_all_servers()
    )
    async def reverse_recruit_user_context(self, ctx, user):
        """Create a recruitment thread for the selected user."""

        await self.open_ticket(ctx, user)


class UserSyncCommands(commands.Cog):
    """Commands that trigger a manual character/user synchronization flow."""

    def __init__(self, bot):
        self.bot = bot

    async def _queue_sync_for_discord_user_id(self, ctx, discord_user_id: int) -> None:
        """Queue a full user sync for one Discord user ID."""

        auth_user = _get_auth_user_from_discord_user_id(discord_user_id)
        if auth_user is None:
            await ctx.response.send_message(
                content=_("Impossible de trouver un compte Alliance Auth lié à cet utilisateur Discord."),
                ephemeral=True,
            )
            return

        main_character = getattr(auth_user.profile, "main_character", None)
        if main_character is None:
            await ctx.response.send_message(
                content=_("Cet utilisateur n'a pas de personnage principal configuré dans Auth."),
                ephemeral=True,
            )
            return

        actor_auth_user = _get_auth_user_from_discord_user_id(getattr(ctx.user, "id", 0))

        sync_user_esi_and_discord.delay(
            user_pk=auth_user.pk,
            triggered_by_user_pk=getattr(actor_auth_user, "pk", None),
        )

        await ctx.response.send_message(
            content=_(
                "Synchronisation lancée pour %(character)s. "
                "Les mises à jour ESI, groupes et Discord seront appliquées en arrière-plan."
            ) % {"character": main_character.character_name},
            ephemeral=True,
        )

    @commands.slash_command(
        name="sync_user_esi",
        description="Force la resynchronisation ESI/Auth/Discord d'un utilisateur",
        guild_ids=app_settings.get_all_servers(),
    )
    async def sync_user_esi(self, ctx, member: discord.Member):
        """Queue a full user sync for one linked Discord member.

        Access control is expected to be managed in Discord command permissions.
        """
        await self._queue_sync_for_discord_user_id(ctx, member.id)

    @commands.user_command(
        name="Sync ESI de l'utilisateur",
        guild_ids=app_settings.get_all_servers(),
    )
    async def sync_user_esi_user_context(self, ctx, user: discord.User):
        """Run manual ESI/Auth/Discord sync from a user context-menu action."""

        await self._queue_sync_for_discord_user_id(ctx, getattr(user, "id", 0))

    @commands.message_command(
        name="Sync ESI Auteur",
        guild_ids=app_settings.get_all_servers(),
    )
    async def sync_user_esi_message_context(self, ctx, message: discord.Message):
        """Run manual ESI/Auth/Discord sync from a message context-menu action."""

        await self._queue_sync_for_discord_user_id(ctx, getattr(message.author, "id", 0))


def setup(bot):
    """Register cogs for recruitment and manual sync actions."""

    bot.add_cog(RecruitmentThreadCommands(bot))
    bot.add_cog(UserSyncCommands(bot))
