import disnake
from disnake.ext import commands
import sqlite3
import aiohttp
import io
import os
import logging
from PIL import Image, ImageDraw, ImageFont
from datetime import datetime, timezone
from utils.premium import check_premium_tier

kuby_logger = logging.getLogger("KubyBot")

class Goodbye(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        # Chemin absolu vers la base de données
        self.base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
        self.db_path = os.path.join(self.base_dir, "config.db")
        self._init_db()

    def _init_db(self):
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        # On s'assure que la table existe au cas où (normalement gérée par welcome.py)
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS server_configs (
                server_id INTEGER PRIMARY KEY,
                welcome_channel INTEGER,
                goodbye_channel INTEGER,
                welcome_dm_message TEXT,
                welcome_server_name TEXT,
                welcome_banner_background TEXT,
                welcome_channel_message TEXT,
                goodbye_server_name TEXT,
                goodbye_message TEXT,
                goodbye_banner_background TEXT
            )
        ''')
        
        # Migration pour ajouter les colonnes si elles n'existent pas
        cursor.execute("PRAGMA table_info(server_configs)")
        columns = [col[1] for col in cursor.fetchall()]
        
        if 'goodbye_server_name' not in columns:
            cursor.execute('ALTER TABLE server_configs ADD COLUMN goodbye_server_name TEXT')
        
        if 'goodbye_message' not in columns:
            cursor.execute('ALTER TABLE server_configs ADD COLUMN goodbye_message TEXT')
        
        if 'goodbye_banner_background' not in columns:
            cursor.execute('ALTER TABLE server_configs ADD COLUMN goodbye_banner_background TEXT')
            
        conn.commit()
        conn.close()

    def humanize_time_delta(self, date):
        if date is None: return "date inconnue"
        if date.tzinfo is None: date = date.replace(tzinfo=timezone.utc)

        now = datetime.now(timezone.utc)
        delta = now - date
        total_days = delta.total_seconds() / (3600 * 24)
        rounded_days = round(total_days)

        years = rounded_days // 365
        months = rounded_days // 30
        weeks = rounded_days // 7
        days = rounded_days

        if years > 0: return f"il y a {years} {'an' if years == 1 else 'ans'}"
        elif months > 0: return f"il y a {months} mois"
        elif weeks > 0: return f"il y a {weeks} {'semaine' if weeks == 1 else 'semaines'}"
        elif days > 0: return f"il y a {days} {'jour' if days == 1 else 'jours'}"
        elif delta.seconds // 3600 > 0:
            hours = delta.seconds // 3600
            return f"il y a {hours} {'heure' if hours == 1 else 'heures'}"
        elif (delta.seconds % 3600) // 60 > 0:
            minutes = (delta.seconds % 3600) // 60
            return f"il y a {minutes} {'minute' if minutes == 1 else 'minutes'}"
        else:
            seconds = delta.seconds % 60
            return f"il y a {seconds} {'seconde' if seconds <= 1 else 'secondes'}"

    async def create_goodbye_image(self, username, avatar_url, server_name=None, banner_background=None):
        # Utiliser base_dir déjà calculé dans __init__
        try:
            # Télécharger l'avatar
            async with aiohttp.ClientSession() as session:
                async with session.get(avatar_url) as resp:
                    if resp.status != 200:
                        kuby_logger.error(f"[Goodbye] Impossible de télécharger l'avatar: {resp.status}")
                        raise ValueError(f"Impossible de télécharger l'avatar (code: {resp.status})")
                    avatar_bytes = await resp.read()

            # Vérifier et utiliser le fond personnalisé ou celui par défaut
            bg_path = None
            if banner_background:
                potential_path = os.path.join(self.base_dir, "banners", banner_background)
                if os.path.exists(potential_path):
                    bg_path = potential_path
                    kuby_logger.debug(f"[Goodbye] Fond personnalisé trouvé: {bg_path}")
            
            if not bg_path:
                default_bg = os.path.join(self.base_dir, 'background_template_goodbye.png')
                if not os.path.exists(default_bg):
                    kuby_logger.error(f"[Goodbye] Fond par défaut introuvable: {default_bg}")
                    raise FileNotFoundError(f"Fond par défaut introuvable: {default_bg}")
                bg_path = default_bg
                kuby_logger.debug(f"[Goodbye] Utilisation du fond par défaut: {bg_path}")
            
            # Charger le fond
            background = Image.open(bg_path)
            draw = ImageDraw.Draw(background)
            
            # Vérifier et charger les polices
            font_large_path = os.path.join(self.base_dir, 'custom_font_large.otf')
            font_small_path = os.path.join(self.base_dir, 'custom_font_small.otf')
            
            for font_path in [font_large_path, font_small_path]:
                if not os.path.exists(font_path):
                    kuby_logger.error(f"[Goodbye] Police introuvable: {font_path}")
                    raise FileNotFoundError(f"Police introuvable: {font_path}")
            
            # Adapter le texte pour éviter les débordements et afficher correctement le nom
            line1_text = "AU REVOIR"
            line2_text = username.upper()
            line3_text = (server_name or "OMEGA KUBE").upper()

            text_area_left = 300
            text_area_right = background.width - 20
            text_area_width = text_area_right - text_area_left
            text_area_center_x = text_area_left + text_area_width // 2

            def fit_font(font_path, text, max_size, max_width):
                size = max_size
                while size > 10:
                    font = ImageFont.truetype(font_path, size)
                    bbox = draw.textbbox((0, 0), text, font=font)
                    w = bbox[2] - bbox[0]
                    if w <= max_width:
                        h = bbox[3] - bbox[1]
                        return font, w, h
                    size -= 2
                font = ImageFont.truetype(font_path, 10)
                bbox = draw.textbbox((0, 0), text, font=font)
                return font, bbox[2] - bbox[0], bbox[3] - bbox[1]

            font1, w1, h1 = fit_font(font_large_path, line1_text, 65, text_area_width)
            font2, w2, h2 = fit_font(font_small_path, line2_text, 38, text_area_width)
            font3, w3, h3 = fit_font(font_large_path, line3_text, 65, text_area_width)

            spacing_1_2 = 12
            spacing_2_3 = 12
            total_height = h1 + spacing_1_2 + h2 + spacing_2_3 + h3
            start_y = (background.height - total_height) // 2

            y = start_y
            draw.text((text_area_center_x - w1 // 2, y), line1_text, font=font1, fill=(255, 255, 255))
            y += h1 + spacing_1_2
            draw.text((text_area_center_x - w2 // 2, y), line2_text, font=font2, fill=(255, 255, 255))
            y += h2 + spacing_2_3
            draw.text((text_area_center_x - w3 // 2, y), line3_text, font=font3, fill=(255, 255, 255))

            # Ajouter l'avatar
            avatar = Image.open(io.BytesIO(avatar_bytes)).convert("RGBA").resize((224, 224), Image.LANCZOS)
            mask = Image.new('L', avatar.size, 0)
            mask_draw = ImageDraw.Draw(mask)
            mask_draw.ellipse((12, 12, 212, 212), fill=255)
            background.paste(avatar, (40, 40), mask)

            # Retourner l'image
            img_byte_arr = io.BytesIO()
            background.save(img_byte_arr, format='PNG')
            img_byte_arr.seek(0)
            return img_byte_arr
            
        except Exception as e:
            kuby_logger.error(f"[Goodbye] Erreur lors de la création de l'image: {e}", exc_info=True)
            return None

    @commands.Cog.listener()
    async def on_member_remove(self, member):
        kuby_logger.info(f"[Goodbye] Départ détecté: {member.name} (ID: {member.id}) du serveur {member.guild.name}")
        
        self._init_db()
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            cursor.execute('SELECT goodbye_channel, goodbye_server_name, goodbye_message, goodbye_banner_background FROM server_configs WHERE server_id = ?', (member.guild.id,))
            result = cursor.fetchone()
            conn.close()

            if not result or not result[0]:
                kuby_logger.debug(f"[Goodbye] Aucune configuration de départ pour le serveur {member.guild.id}")
                return

            goodbye_channel = result[0]
            server_name = result[1]
            custom_message = result[2]
            banner_background = result[3]
            
            channel = member.guild.get_channel(goodbye_channel)
            if not channel:
                kuby_logger.warning(f"[Goodbye] Salon de départ introuvable (ID: {goodbye_channel}) pour {member.guild.name}")
                return
            
            joined_message = self.humanize_time_delta(member.joined_at)
            
            try:
                img = await self.create_goodbye_image(
                    member.name, 
                    member.avatar.url if member.avatar else member.default_avatar.url,
                    server_name=server_name,
                    banner_background=banner_background
                )
                
                # Envoyer avec image si disponible
                display_name = server_name if server_name else member.guild.name
                default_message = "Nous espérons vous revoir bientôt <a:rain:1317973615714504806>"
                message_text = custom_message if custom_message else default_message
                
                if img:
                    embed = disnake.Embed(
                        description=f"{member.mention} vient de nous quitter.\n\n{message_text}",
                        color=0x9B59B6
                    )
                    embed.set_footer(text=f"avait rejoint · {joined_message}")
                    embed.set_image(url="attachment://goodbye.png")
                    await channel.send(embed=embed, file=disnake.File(img, filename="goodbye.png"))
                    kuby_logger.info(f"[Goodbye] Message de départ avec image envoyé pour {member.name}")
                else:
                    # Fallback : image non générée
                    kuby_logger.warning(f"[Goodbye] Image non générée pour {member.name}, envoi d'un message texte")
                    embed = disnake.Embed(
                        description=f"{member.mention} vient de nous quitter.\n\n{message_text}",
                        color=0x9B59B6
                    )
                    embed.set_footer(text=f"avait rejoint · {joined_message}")
                    await channel.send(embed=embed)
                    
            except Exception as e:
                kuby_logger.error(f"[Goodbye] Erreur lors de la création ou de l'envoi du message: {e}", exc_info=True)
                # Fallback avec un message minimal
                try:
                    message_text_fb = custom_message if custom_message else "Nous espérons vous revoir bientôt"
                    await channel.send(f"{member.mention} vient de nous quitter. {message_text_fb}")
                    kuby_logger.info(f"[Goodbye] Message de fallback envoyé pour {member.name}")
                except Exception as e2:
                    kuby_logger.error(f"[Goodbye] Échec du message de fallback: {e2}", exc_info=True)
        except sqlite3.Error as e:
            kuby_logger.error(f"[Goodbye] Erreur SQLite: {e}", exc_info=True)
        except Exception as e:
            kuby_logger.error(f"[Goodbye] Erreur inattendue dans on_member_remove: {e}", exc_info=True)

    async def save_banner_attachment(self, attachment: disnake.Attachment, guild_id: int) -> str:
        """Sauvegarde l'attachment et retourne le chemin du fichier"""
        base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "banners"))
        os.makedirs(base_dir, exist_ok=True)
        
        # Vérifier que c'est une image
        if not attachment.content_type or not attachment.content_type.startswith('image/'):
            raise ValueError("Le fichier doit être une image.")
        
        # Vérifier le format PNG
        if not attachment.filename.lower().endswith('.png'):
            raise ValueError("Le fichier doit être au format PNG.")
        
        # Vérifier les dimensions
        banner_path = os.path.join(base_dir, f"banner_goodbye_{guild_id}.png")
        
        async with aiohttp.ClientSession() as session:
            async with session.get(attachment.url) as resp:
                if resp.status == 200:
                    # Vérifier les dimensions avant de sauvegarder
                    img_data = await resp.read()
                    from io import BytesIO
                    with Image.open(BytesIO(img_data)) as img:
                        width, height = img.size
                        if width != 1000 or height != 300:
                            raise ValueError(f"Les dimensions doivent être 1000x300 pixels (votre image: {width}x{height})")
                    
                    with open(banner_path, 'wb') as f:
                        f.write(img_data)
        
        return os.path.basename(banner_path)

    @commands.slash_command(name="setgoodbye", description="Définit le salon d'au revoir et les paramètres personnalisés")
    @check_premium_tier()
    @commands.has_permissions(administrator=True)
    async def set_goodbye(self, interaction: disnake.ApplicationCommandInteraction, channel: disnake.TextChannel, server_name: str = None, message: str = None, banner_file: disnake.Attachment = None):
        # ✅ DÉFÉRER LA RÉPONSE (le traitement peut prendre > 3s avec les images)
        await interaction.response.defer(ephemeral=True)
        
        banner_path = None
        error_message = None
        
        # Si un fichier est uploadé, le sauvegarder
        if banner_file:
            try:
                banner_path = await self.save_banner_attachment(banner_file, interaction.guild_id)
            except Exception as e:
                error_message = f"❌ Erreur avec le fichier: {e}"
        
        # Si pas d'erreur, sauvegarder en base de données
        if not error_message:
            try:
                conn = sqlite3.connect(self.db_path)
                cursor = conn.cursor()
                cursor.execute('''INSERT INTO server_configs (server_id, goodbye_channel, goodbye_server_name, goodbye_message, goodbye_banner_background) 
                                  VALUES (?, ?, ?, ?, ?) ON CONFLICT(server_id) 
                                  DO UPDATE SET goodbye_channel=excluded.goodbye_channel,
                                  goodbye_server_name=COALESCE(excluded.goodbye_server_name, goodbye_server_name),
                                  goodbye_message=COALESCE(excluded.goodbye_message, goodbye_message),
                                  goodbye_banner_background=COALESCE(excluded.goodbye_banner_background, goodbye_banner_background)''', 
                                (interaction.guild_id, channel.id, server_name, message, banner_path))
                conn.commit()
                conn.close()
                
                msg = f"✅ Salon d'au revoir défini sur {channel.mention}"
                if server_name: msg += f"\nNom du serveur: {server_name}"
                if message: msg += f"\nMessage: {message}"
                if banner_path: msg += f"\nBannière personnalisée activée."
                error_message = msg
            except Exception as e:
                error_message = f"❌ Erreur lors de la sauvegarde en base de données: {e}"
        
        # Envoyer la réponse finale (déferrée)
        await interaction.followup.send(error_message, ephemeral=True)

def setup(bot):
    bot.add_cog(Goodbye(bot))