import disnake
from disnake.ext import commands
import json
import os
from typing import Optional

# Chemins ABSOLUS
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
DATA_DIR = os.path.join(BASE_DIR, "..", "..", "data")
SETTINGS_FILE = os.path.join(DATA_DIR, "security_settings.json")

# Créer le dossier data/ s'il n'existe pas
os.makedirs(DATA_DIR, exist_ok=True)

def escape_mentions(text: str) -> str:
    """Échappe les mentions @everyone et @here pour éviter les notifications involontaires"""
    if not text:
        return text
    # Utilise un zero-width space pour briser la mention Discord
    return text.replace("@everyone", "@\u200beveryone").replace("@here", "@\u200bhere")


def load_settings(guild_id: int) -> dict:
    """Charge les paramètres de sécurité pour un serveur"""
    if not os.path.exists(SETTINGS_FILE):
        return {}
    try:
        with open(SETTINGS_FILE, "r", encoding='utf-8') as f:
            return json.load(f).get(str(guild_id), {})
    except (json.JSONDecodeError, FileNotFoundError):
        return {}


def save_settings(guild_id: int, settings: dict) -> None:
    """Sauvegarde les paramètres de sécurité"""
    data = {}
    if os.path.exists(SETTINGS_FILE):
        try:
            with open(SETTINGS_FILE, "r", encoding='utf-8') as f:
                data = json.load(f)
        except (json.JSONDecodeError, FileNotFoundError):
            pass
    
    data[str(guild_id)] = settings
    
    os.makedirs(os.path.dirname(SETTINGS_FILE), exist_ok=True)
    with open(SETTINGS_FILE, "w", encoding='utf-8') as f:
        json.dump(data, f, indent=4, ensure_ascii=False)


# --- MODALS DE CONFIGURATION DU RÈGLEMENT (BACK-END) ---

class RulesTitleModal(disnake.ui.Modal):
    """Modal pour configurer le titre du règlement"""
    title_input = disnake.ui.TextInput(
        label="Titre du règlement",
        placeholder="Ex: 📜 Règlement de [Nom du Serveur]",
        min_length=1,
        max_length=100,
        required=True
    )
    
    def __init__(self, guild_id: int, settings: dict, on_update_callback=None):
        super().__init__(title="📜 Titre du Règlement", components=[self.title_input])
        self.guild_id = guild_id
        self.settings = settings
        self.on_update_callback = on_update_callback

    async def callback(self, interaction: disnake.Interaction):
        self.settings["rules_title"] = self.title_input.value
        save_settings(self.guild_id, self.settings)
        
        if self.on_update_callback:
            await self.on_update_callback(interaction, self.settings)
        else:
            await interaction.response.edit_message(view=self._create_view(interaction))
        
        await interaction.followup.send(
            f"✅ Titre du règlement mis à jour.", 
            ephemeral=True
        )
    
    def _create_view(self, interaction):
        """Crée la vue mise à jour"""
        from commandes.security import SecurityView
        # Essayer d'obtenir le bot depuis l'interaction
        bot = getattr(interaction, 'client', None)
        view = SecurityView(interaction, self.settings, category="rules", bot=bot)
        return view


class RulesContentModal(disnake.ui.Modal):
    """Modal pour configurer le contenu du règlement"""
    content_input = disnake.ui.TextInput(
        label="Contenu du règlement",
        placeholder="Entrez les règles de votre serveur...",
        style=disnake.TextInputStyle.paragraph,
        min_length=10,
        max_length=4000,
        required=True
    )
    
    def __init__(self, guild_id: int, settings: dict, on_update_callback=None):
        super().__init__(title="📝 Contenu du Règlement", components=[self.content_input])
        self.guild_id = guild_id
        self.settings = settings
        self.on_update_callback = on_update_callback

    async def callback(self, interaction: disnake.Interaction):
        self.settings["rules_content"] = escape_mentions(self.content_input.value)
        save_settings(self.guild_id, self.settings)
        
        if self.on_update_callback:
            await self.on_update_callback(interaction, self.settings)
        else:
            await interaction.response.edit_message(view=self._create_view(interaction))
        
        await interaction.followup.send(
            f"✅ Contenu du règlement mis à jour.", 
            ephemeral=True
        )
    
    def _create_view(self, interaction):
        """Crée la vue mise à jour"""
        from commandes.security import SecurityView
        # Essayer d'obtenir le bot depuis l'interaction
        bot = getattr(interaction, 'client', None)
        view = SecurityView(interaction, self.settings, category="rules", bot=bot)
        return view


class RulesChannelModal(disnake.ui.Modal):
    """Modal pour sélectionner le salon du règlement"""
    channel_input = disnake.ui.TextInput(
        label="ID du salon",
        placeholder="Entrez l'ID du salon où envoyer le règlement",
        min_length=15,
        max_length=20,
        required=True
    )
    
    def __init__(self, guild_id: int, settings: dict, on_update_callback=None):
        super().__init__(title="📌 Salon du Règlement", components=[self.channel_input])
        self.guild_id = guild_id
        self.settings = settings
        self.on_update_callback = on_update_callback

    async def callback(self, interaction: disnake.Interaction):
        if not self.channel_input.value.isdigit():
            return await interaction.response.send_message(
                "❌ Erreur : ID invalide.", 
                ephemeral=True
            )
        
        channel_id = int(self.channel_input.value)
        channel = interaction.guild.get_channel(channel_id)
        
        if not channel:
            return await interaction.response.send_message(
                "❌ Salon non trouvé. Vérifiez l'ID.", 
                ephemeral=True
            )
        
        self.settings["rules_channel_id"] = channel_id
        save_settings(self.guild_id, self.settings)
        
        if self.on_update_callback:
            await self.on_update_callback(interaction, self.settings)
        else:
            await interaction.response.edit_message(view=self._create_view(interaction))
        
        await interaction.followup.send(
            f"✅ Salon du règlement défini sur {channel.mention}.", 
            ephemeral=True
        )
    
    def _create_view(self, interaction):
        """Crée la vue mise à jour"""
        from commandes.security import SecurityView
        # Essayer d'obtenir le bot depuis l'interaction
        bot = getattr(interaction, 'client', None)
        view = SecurityView(interaction, self.settings, category="rules", bot=bot)
        return view


class RulesRoleModal(disnake.ui.Modal):
    """Modal pour configurer le rôle attribué à l'acceptation"""
    role_input = disnake.ui.TextInput(
        label="ID du rôle",
        placeholder="Entrez l'ID du rôle à attribuer",
        min_length=15,
        max_length=20,
        required=True
    )

    def __init__(self, guild_id: int, settings: dict, on_update_callback=None):
        super().__init__(title="✅ Rôle d'Acceptation", components=[self.role_input])
        self.guild_id = guild_id
        self.settings = settings
        self.on_update_callback = on_update_callback

    async def callback(self, interaction: disnake.Interaction):
        if not self.role_input.value.isdigit():
            return await interaction.response.send_message(
                "❌ Erreur : ID invalide.",
                ephemeral=True
            )

        role_id = int(self.role_input.value)
        role = interaction.guild.get_role(role_id)

        if not role:
            return await interaction.response.send_message(
                "❌ Rôle non trouvé. Vérifiez l'ID.",
                ephemeral=True
            )

        self.settings["rules_accept_role_id"] = role_id
        save_settings(self.guild_id, self.settings)

        if self.on_update_callback:
            await self.on_update_callback(interaction, self.settings)
        else:
            await interaction.response.edit_message(view=self._create_view(interaction))

        await interaction.followup.send(
            f"✅ Rôle d'acceptation défini sur **{role.name}**.",
            ephemeral=True
        )

    def _create_view(self, interaction):
        """Crée la vue mise à jour"""
        from commandes.security import SecurityView
        # Essayer d'obtenir le bot depuis l'interaction
        bot = getattr(interaction, 'client', None)
        view = SecurityView(interaction, self.settings, category="rules", bot=bot)
        return view


class RulesMessageTypeModal(disnake.ui.Modal):
    """Modal pour choisir le type de message du règlement"""
    message_type = disnake.ui.TextInput(
        label="Type de message",
        placeholder="Tapez 'embed' pour embed ou 'simple' pour message simple",
        min_length=5,
        max_length=6,
        required=True
    )

    def __init__(self, guild_id: int, settings: dict, on_update_callback=None):
        super().__init__(title="📝 Type de Message", components=[self.message_type])
        self.guild_id = guild_id
        self.settings = settings
        self.on_update_callback = on_update_callback

    async def callback(self, interaction: disnake.Interaction):
        msg_type = self.message_type.value.lower().strip()

        if msg_type not in ["embed", "simple"]:
            return await interaction.response.send_message(
                "❌ Erreur : Tapez 'embed' ou 'simple'.",
                ephemeral=True
            )

        self.settings["rules_message_type"] = msg_type
        save_settings(self.guild_id, self.settings)

        if self.on_update_callback:
            await self.on_update_callback(interaction, self.settings)
        else:
            await interaction.response.edit_message(view=self._create_view(interaction))

        type_name = "Embed" if msg_type == "embed" else "Message simple"
        await interaction.followup.send(
            f"✅ Type de message défini sur **{type_name}**.",
            ephemeral=True
        )

    def _create_view(self, interaction):
        """Crée la vue mise à jour"""
        from commandes.security import SecurityView
        # Essayer d'obtenir le bot depuis l'interaction
        bot = getattr(interaction, 'client', None)
        view = SecurityView(interaction, self.settings, category="rules", bot=bot)
        return view


class ToggleRulesButton(disnake.ui.Button):
    """Bouton de bascule pour activer/désactiver le règlement"""
    
    def __init__(self, is_enabled: bool):
        style = disnake.ButtonStyle.green if is_enabled else disnake.ButtonStyle.red
        status = "✅" if is_enabled else "❌"
        super().__init__(
            label=f"Règlement [{status}]",
            style=style,
            custom_id="rules_enabled",
            emoji="📜"
        )

    async def callback(self, interaction: disnake.Interaction):
        view = self.view
        settings = view.settings
        guild = interaction.guild
        
        # Basculer le paramètre
        settings["rules_enabled"] = not settings.get("rules_enabled", False)
        save_settings(guild.id, settings)
        
        # Reconstruire la vue
        from commandes.security import SecurityView
        # Essayer d'obtenir le bot depuis l'interaction
        bot = getattr(interaction, 'client', None)
        new_view = SecurityView(interaction, settings, category="rules", bot=bot)
        
        # Recréer l'embed
        embed = new_view.create_category_embed(
            "Configuration Règlement",
            "Créez et envoyez un règlement pour votre serveur.\n\n"
            "• **Titre** : Personnalisez le titre du règlement\n"
            "• **Contenu** : Rédigez vos règles\n"
            "• **Salon** : Choisissez où l'envoyer\n"
            "• **Rôle** : Rôle attribué à l'acceptation\n\n"
            "Les membres devront accepter le règlement pour accéder au serveur."
        )
        
        await interaction.response.edit_message(embed=embed, view=new_view)


class RulesAcceptButton(disnake.ui.View):
    """Bouton persistant pour accepter le règlement"""
    
    def __init__(self, guild_id: int, accept_role_id: int):
        super().__init__(timeout=None)  # Pas de timeout - bouton persistant
        self.guild_id = guild_id
        self.accept_role_id = accept_role_id

    @disnake.ui.button(
        label="J'accepte le règlement",
        emoji="✅",
        style=disnake.ButtonStyle.green,
        custom_id="rules_accept_button"
    )
    async def accept_rules(self, button: disnake.ui.Button, interaction: disnake.Interaction):
        """Gère le clic sur le bouton d'acceptation"""
        guild = interaction.guild
        
        # Vérifier si le bouton est toujours activé (activé dans les paramètres)
        settings = load_settings(guild.id)
        if not settings.get("rules_enabled", False):
            return await interaction.response.send_message(
                "❌ Cette fonctionnalité a été désactivée.",
                ephemeral=True
            )
        
        # Vérifier si l'utilisateur a déjà le rôle
        role = guild.get_role(self.accept_role_id)
        if not role:
            return await interaction.response.send_message(
                "❌ Le rôle d'acceptation n'est plus configuré sur ce serveur.",
                ephemeral=True
            )
        
        member = interaction.user
        
        if role in member.roles:
            return await interaction.response.send_message(
                "✅ Vous avez déjà accepté le règlement !",
                ephemeral=True
            )
        
        # Attribuer le rôle à l'utilisateur
        try:
            await member.add_roles(role)
            
            # Envoyer une confirmation éphémère
            await interaction.response.send_message(
                f"✅ {member.mention}, vous avez accepté le règlement !\n"
                f"Le rôle **{role.name}** vous a été attribué.",
                ephemeral=True
            )
        except disnake.Forbidden:
            await interaction.response.send_message(
                "❌ Je n'ai pas les permissions pour attribuer ce rôle.",
                ephemeral=True
            )
        except Exception as e:
            await interaction.response.send_message(
                f"❌ Une erreur est survenue: {e}",
                ephemeral=True
            )


class RulesCog(commands.Cog):
    """Cog pour la gestion du règlement"""
    
    def __init__(self, bot):
        self.bot = bot
        self.persistent_views_added = False

    async def cog_load(self):
        """Called when cog is loaded - setup persistent views"""
        await self.setup_persistent_views()

    async def setup_persistent_views(self):
        """Configure les views persistantes pour les règlements existants"""
        if self.persistent_views_added:
            return
        
        # Charger les paramètres de tous les serveurs
        if not os.path.exists(SETTINGS_FILE):
            return
            
        try:
            with open(SETTINGS_FILE, "r", encoding='utf-8') as f:
                all_settings = json.load(f)
            
            # Pour chaque serveur avec le règlement activé
            for guild_id_str, settings in all_settings.items():
                if settings.get("rules_enabled", False) and settings.get("rules_accept_role_id"):
                    # Ajouter la view persistente
                    view = RulesAcceptButton(int(guild_id_str), settings["rules_accept_role_id"])
                    self.bot.add_view(view)
                    print(f"[Rules] View registered for guild {guild_id_str}")
                    
            self.persistent_views_added = True
        except (json.JSONDecodeError, FileNotFoundError):
            pass

    @commands.Cog.listener()
    async def on_ready(self):
        """Appelé quand le bot est prêt"""
        print("🎫 Module Règles chargé avec succès!")

    async def send_rules_message(self, channel: disnake.TextChannel, settings: dict) -> Optional[disnake.Message]:
        """Envoie le message du règlement dans un salon"""
        title = settings.get("rules_title", "📜 Règlement du Serveur")
        content = settings.get("rules_content", "")
        accept_role_id = settings.get("rules_accept_role_id")
        message_type = settings.get("rules_message_type", "embed")  # Par défaut embed

        if not accept_role_id:
            return None

        # Créer la view avec le bouton persistant
        view = RulesAcceptButton(channel.guild.id, accept_role_id)

        if message_type == "simple":
            # Message simple - échappe les mentions @everyone/@here pour éviter les notifications involontaires
            safe_content = content.replace("@everyone", "@\u200beveryone").replace("@here", "@\u200bhere")
            text_message = (
                f"📜 **{title}**\n\n"
                f"{safe_content}\n\n"
                "Bienvenue ! Pour accéder à l'ensemble des canaux du serveur, "
                "vous devez accepter le règlement en cliquant sur le bouton ci-dessous.\n\n"
                "En acceptant, vous confirmez avoir lu et compris les règles du serveur."
            )

            # Envoyer le message simple
            try:
                message = await channel.send(
                    content=text_message,
                    view=view
                )
                return message
            except Exception as e:
                print(f"Erreur lors de l'envoi du règlement simple: {e}")
                return None

        else:  # embed
            # Échappe les mentions @everyone/@here pour éviter les notifications involontaires
            safe_content = content.replace("@everyone", "@\u200beveryone").replace("@here", "@\u200bhere")

            # Utilise un Container avec TextDisplay pour un meilleur rendu du texte (markdown supporté)
            components = [
                disnake.ui.Container(
                    disnake.ui.TextDisplay(safe_content)
                )
            ]

            # Créer l'embed
            embed = disnake.Embed(
                title=title,
                color=0x2b2d31
            )

            embed.set_footer(text="Cliquez sur le bouton ci-dessous pour accepter le règlement")

            # Envoyer l'embed avec le container et la view
            try:
                message = await channel.send(
                    embed=embed,
                    components=components,
                    view=view
                )
                return message
            except Exception as e:
                print(f"Erreur lors de l'envoi du règlement embed: {e}")
                return None

    def format_default_rules(self, guild_name: str) -> tuple:
        """Retourne le titre et contenu par défaut du règlement"""
        title = f"📜 Règlement de {guild_name}"
        content = (
            "Bienvenue sur notre serveur ! Avant de commencer à interagir avec la communauté, "
            "veuille lire et accepter notre règlement.\n\n"
            "**📌 Règles à respecter :**\n\n"
            "1. **Respectez les autres membres** - Pas d'insultes, de harcèlement ou de discrimination.\n"
            "2. **Pas de contenu inapproprié** - Aucun contenu NSFW, violent ou choquant.\n"
            "3. **Pas de spam ou de flood** - Évitez les messages répétitifs ou les emojis excessifs.\n"
            "4. **Pas de publicité** - Ne partagez pas de liens vers d'autres serveurs sans autorisation.\n"
            "5. **Restez dans les salons appropriés** - Respectez la thématique de chaque canal.\n\n"
            "**⚠️ Sanctions :**\n"
            "Le non-respect de ces règles peut entraîner des avertissements, des mute temporaires, "
            "ou un banissement définitif selon la gravité des infractions.\n\n"
            "*En cliquant sur \"J'accepte\", vous confirmez avoir lu et accepter ce règlement.*"
        )
        return title, content


def setup(bot):
    """Setup du cog de règlement"""
    cog = RulesCog(bot)
    bot.add_cog(cog)

