import discord
import os
import aiohttp
from datetime import datetime
import re
import asyncio
from aiohttp import ClientTimeout
import json 

# Replace 'YOUR_BOT_TOKEN_HERE' with your actual Discord bot token
TOKEN = 'MTM5MTM0MzAwOTA0MzMyMDkwMg.GRm_A7.Hf7FE1IxcPBuTdK0tiY3tSeVfMzK7z9MCZiYrU'

# Optional: Add your test guild ID for faster command sync (remove for global commands)
TEST_GUILD_ID = 1387778361438371941  # Replace with your actual server ID

# Configuration
API_BASE_URL = 'http://135.181.201.82/Attributes'

class LicensePaginationView(discord.ui.View):
    def __init__(self, licenses, licenses_per_page=5, title="\ud83d\udccb License Database", expired_mode=False):
        super().__init__(timeout=300)  # 5 minutes timeout
        self.licenses = licenses
        self.licenses_per_page = licenses_per_page
        self.current_page = 0
        self.total_pages = (len(licenses) + licenses_per_page - 1) // licenses_per_page
        # display options
        self.title = title
        self.expired_mode = expired_mode
        
        # Update button states
        self.update_buttons()
    
    def update_buttons(self):
        # Disable/enable buttons based on current page
        self.previous_button.disabled = (self.current_page == 0)
        self.next_button.disabled = (self.current_page >= self.total_pages - 1)
        
        # Update button labels with page info
        self.previous_button.label = f"◀ Previous"
        self.next_button.label = f"Next ▶"
    
    def get_embed(self):
        start_index = self.current_page * self.licenses_per_page
        end_index = min(start_index + self.licenses_per_page, len(self.licenses))
        current_licenses = self.licenses[start_index:end_index]
        
        embed = discord.Embed(
            title=self.title,
            description=f"Page {self.current_page + 1} of {self.total_pages} • Showing {len(current_licenses)} of {len(self.licenses)} total licenses",
            color=discord.Color.greyple() if getattr(self, 'expired_mode', False) else discord.Color.light_grey()
        )
        
        for i, license_data in enumerate(current_licenses, start=start_index + 1):
            # Safely get values with defaults
            license_key = license_data.get('license_key', 'N/A')
            username = license_data.get('username', 'N/A')
            password = license_data.get('password', 'N/A')
            valid_until = license_data.get('valid_until', 'N/A')
            created_at = license_data.get('created_at', 'N/A')
            hwid = license_data.get('hwid', 'Not Set')
            last_logon = license_data.get('last_logon', 'N/A')
            discord_uid = license_data.get('discord_uid', 'N/A')
            discord_uid_alt = license_data.get('discord_uid_alt', 'N/A')
            
            
            display_key = license_key if len(license_key) <= 30 else f"{license_key[:27]}..."
            
            
            field_value = f"**Username:** {username}\n**License Key**: `{display_key}`\n**Password**: {password}\n**Expiration Date**: {valid_until}\n **HWID**: {hwid if hwid else 'Not Set'}\n**Created**: {created_at}\n**Last Logon**: {last_logon}\n**Discord UID:** {discord_uid}\n**Discord UID Alt:** {discord_uid_alt}"
            
            
            if len(field_value) > 1024:
                field_value = field_value[:1021] + "..."
            
            embed.add_field(
                name=f"🔑 License #{i}",
                value=field_value,
                inline=False
            )
        
        # Add footer with navigation info
        embed.set_footer(
            text=f"Use the buttons below to navigate • Expires in {int(self.timeout/60)} minutes"
        )
        
        return embed
    
    @discord.ui.button(label="◀ Previous", style=discord.ButtonStyle.secondary, disabled=True)
    async def previous_button(self, button: discord.ui.Button, interaction: discord.Interaction):
        if self.current_page > 0:
            self.current_page -= 1
            self.update_buttons()
            await interaction.response.edit_message(embed=self.get_embed(), view=self)
    
    @discord.ui.button(label="Next ▶", style=discord.ButtonStyle.secondary)
    async def next_button(self, button: discord.ui.Button, interaction: discord.Interaction):
        if self.current_page < self.total_pages - 1:
            self.current_page += 1
            self.update_buttons()
            await interaction.response.edit_message(embed=self.get_embed(), view=self)
    
    @discord.ui.button(label="🔄 Refresh", style=discord.ButtonStyle.primary)
    async def refresh_button(self, button: discord.ui.Button, interaction: discord.Interaction):
        await interaction.response.defer()
        
        # Fetch fresh data from API
        api_url = f'{API_BASE_URL}/get_all_licenses.php'
        try:
            timeout = ClientTimeout(total=30)
            async with aiohttp.ClientSession(timeout=timeout) as session:
                async with session.get(api_url) as resp:
                    if resp.status == 200:
                        try:
                            response_data = await resp.json()
                            if response_data.get('success') and response_data.get('licenses'):
                                self.licenses = response_data['licenses']
                                self.total_pages = (len(self.licenses) + self.licenses_per_page - 1) // self.licenses_per_page
                                
                                # Reset to first page if current page is now out of range
                                if self.current_page >= self.total_pages:
                                    self.current_page = 0
                                
                                self.update_buttons()
                                await interaction.followup.edit_message(
                                    interaction.message.id, 
                                    embed=self.get_embed(), 
                                    view=self
                                )
                            else:
                                await interaction.followup.send("❌ No licenses found after refresh.", ephemeral=True)
                        except:
                            await interaction.followup.send("❌ Failed to refresh data.", ephemeral=True)
                    else:
                        await interaction.followup.send("❌ Failed to connect to server for refresh.", ephemeral=True)
        except:
            await interaction.followup.send("❌ Network error during refresh.", ephemeral=True)
    
    @discord.ui.button(label="📊 Jump to Page", style=discord.ButtonStyle.secondary)
    async def jump_page_button(self, button: discord.ui.Button, interaction: discord.Interaction):
        modal = JumpToPageModal(self)
        await interaction.response.send_modal(modal)
    
    @discord.ui.button(label="❌ Close", style=discord.ButtonStyle.danger)
    async def close_button(self, button: discord.ui.Button, interaction: discord.Interaction):
        embed = discord.Embed(
            title="📋 License Database",
            description="✅ License viewer closed.",
            color=discord.Color.red()
        )
        await interaction.response.edit_message(embed=embed, view=None)
        self.stop()
    
    async def on_timeout(self):
        # Disable all buttons when timeout occurs
        for item in self.children:
            item.disabled = True


class JumpToPageModal(discord.ui.Modal):
    def __init__(self, pagination_view):
        super().__init__(title="Jump to Page")
        self.pagination_view = pagination_view
        
        self.page_input = discord.ui.InputText(
            label="Page Number",
            placeholder=f"Enter page number (1-{pagination_view.total_pages})",
            required=True,
            max_length=3
        )
        self.add_item(self.page_input)
    
    async def callback(self, interaction: discord.Interaction):
        try:
            page_num = int(self.page_input.value)
            if 1 <= page_num <= self.pagination_view.total_pages:
                self.pagination_view.current_page = page_num - 1
                self.pagination_view.update_buttons()
                await interaction.response.edit_message(
                    embed=self.pagination_view.get_embed(), 
                    view=self.pagination_view
                )
            else:
                await interaction.response.send_message(
                    f"❌ Invalid page number. Please enter a number between 1 and {self.pagination_view.total_pages}.",
                    ephemeral=True
                )
        except ValueError:
            await interaction.response.send_message(
                "❌ Please enter a valid number.",
                ephemeral=True
            )


class MissingHWIDPaginationView(discord.ui.View):
    def __init__(self, rows, per_page=6, total_count=None):
        super().__init__(timeout=300)
        self.rows = rows
        self.per_page = per_page
        self.current_page = 0
        # total_count is the DB total returned by the API (may be larger than len(rows))
        self.total_count = total_count if total_count is not None else len(rows)
        self.total_pages = (len(rows) + per_page - 1) // per_page
        self.update_buttons()

    def update_buttons(self):
        self.previous_button.disabled = (self.current_page == 0)
        self.next_button.disabled = (self.current_page >= self.total_pages - 1)
        self.previous_button.label = "◀ Previous"
        self.next_button.label = "Next ▶"

    def get_embed(self):
        start = self.current_page * self.per_page
        end = min(start + self.per_page, len(self.rows))
        page_rows = self.rows[start:end]

        embed = discord.Embed(
            title="📋 Missing HWID Users",
            description=f"Page {self.current_page+1} of {self.total_pages} • Showing {len(page_rows)} of {self.total_count} total",
            color=discord.Color.dark_grey()
        )

        for i, r in enumerate(page_rows, start=start+1):
            username = r.get('username', 'N/A')
            license_key = r.get('license_key', 'N/A')
            hwid_val = r.get('hwid')
            display_key = license_key if len(license_key) <= 40 else license_key[:37] + '...'
            # Present the hwid exactly as the DB has it, but make invisible values visible
            if hwid_val is None:
                hwid_display = 'NULL'
            else:
                # it's a string (could be empty or whitespace)
                s = str(hwid_val)
                if s == '':
                    hwid_display = '<empty>'
                elif s.strip() == '':
                    hwid_display = '<whitespace>'
                else:
                    hwid_display = s

            value = f"**Username:** `{username}`\n**License Key:** `{display_key}`\n**HWID ID:** `{hwid_display}`"
            embed.add_field(name=f"🔎 Missing HWID #{i}", value=value, inline=False)

        embed.set_footer(text=f"Use the buttons below to navigate • Expires in {int(self.timeout/60)} minutes ")
        embed.set_footer(text=f"Please contact the users with Missing HWID details and either ask them to register or create a new license for them <3• Expires in {int(self.timeout/60)} minutes ")
        return embed

    @discord.ui.button(label="◀ Previous", style=discord.ButtonStyle.secondary, disabled=True)
    async def previous_button(self, button: discord.ui.Button, interaction: discord.Interaction):
        if self.current_page > 0:
            self.current_page -= 1
            self.update_buttons()
            await interaction.response.edit_message(embed=self.get_embed(), view=self)

    @discord.ui.button(label="Next ▶", style=discord.ButtonStyle.secondary)
    async def next_button(self, button: discord.ui.Button, interaction: discord.Interaction):
        if self.current_page < self.total_pages - 1:
            self.current_page += 1
            self.update_buttons()
            await interaction.response.edit_message(embed=self.get_embed(), view=self)

    @discord.ui.button(label="🔄 Refresh", style=discord.ButtonStyle.primary)
    async def refresh_button(self, button: discord.ui.Button, interaction: discord.Interaction):
        await interaction.response.defer()
        api_url = f"{API_BASE_URL}/missinghwid_count.php?limit=1000"
        try:
            timeout = ClientTimeout(total=30)
            async with aiohttp.ClientSession(timeout=timeout) as session:
                async with session.get(api_url) as resp:
                    if resp.status == 200:
                        try:
                            data = await resp.json()
                            rows = data.get('rows', []) if isinstance(data, dict) else []
                            self.rows = rows
                            self.total_count = data.get('missing_hwid', self.total_count)
                            self.total_pages = (len(self.rows) + self.per_page - 1) // self.per_page
                            if self.current_page >= self.total_pages:
                                self.current_page = 0
                            self.update_buttons()
                            await interaction.followup.edit_message(interaction.message.id, embed=self.get_embed(), view=self)
                        except Exception:
                            await interaction.followup.send("❌ Failed to refresh missing hwid data.", ephemeral=True)
                    else:
                        await interaction.followup.send("❌ Failed to fetch missing hwid data.", ephemeral=True)
        except Exception:
            await interaction.followup.send("❌ Network error during refresh.", ephemeral=True)

    @discord.ui.button(label="📊 Jump to Page", style=discord.ButtonStyle.secondary)
    async def jump_page_button(self, button: discord.ui.Button, interaction: discord.Interaction):
        modal = JumpToPageModal(self)
        await interaction.response.send_modal(modal)

    @discord.ui.button(label="❌ Close", style=discord.ButtonStyle.danger)
    async def close_button(self, button: discord.ui.Button, interaction: discord.Interaction):
        embed = discord.Embed(title="📋 Missing HWID Users", description="✅ Viewer closed.", color=discord.Color.dark_red())
        await interaction.response.edit_message(embed=embed, view=None)
        self.stop()

    async def on_timeout(self):
        for item in self.children:
            item.disabled = True


class BlacklistPaginationView(discord.ui.View):
    def __init__(self, rows, per_page=6):
        super().__init__(timeout=300)
        self.rows = rows
        self.per_page = per_page
        self.current_page = 0
        self.total_pages = (len(rows) + per_page - 1) // per_page if rows else 1
        self.update_buttons()

    def update_buttons(self):
        self.previous_button.disabled = (self.current_page == 0)
        self.next_button.disabled = (self.current_page >= self.total_pages - 1)
        self.previous_button.label = "◀ Previous"
        self.next_button.label = "Next ▶"

    def get_embed(self):
        start = self.current_page * self.per_page
        end = min(start + self.per_page, len(self.rows))
        page_rows = self.rows[start:end]

        embed = discord.Embed(
            title="🦈Blacklisted UIDs",
            description=f"Page {self.current_page+1} of {self.total_pages} • Showing {len(page_rows)} of {len(self.rows)} total",
            color=discord.Color.dark_gray()
        )

        for i, r in enumerate(page_rows, start=start+1):
            discord_id = str(r.get('discord_id', 'N/A'))
            reason = r.get('reason', 'N/A')
            added_by = str(r.get('added_by', 'N/A'))
            embed.add_field(
                name=f"UID:{i} | `{discord_id}`",
                value=f"**Reason:** {reason}\n**Added by:** <@{added_by}>",
                inline=False
            )

        embed.set_footer(text=f"Use the buttons below to navigate • Expires in {int(self.timeout/60)} minutes ")
        return embed

    @discord.ui.button(label="◀ Previous", style=discord.ButtonStyle.secondary, disabled=True)
    async def previous_button(self, button: discord.ui.Button, interaction: discord.Interaction):
        if self.current_page > 0:
            self.current_page -= 1
            self.update_buttons()
            await interaction.response.edit_message(embed=self.get_embed(), view=self)

    @discord.ui.button(label="Next ▶", style=discord.ButtonStyle.secondary)
    async def next_button(self, button: discord.ui.Button, interaction: discord.Interaction):
        if self.current_page < self.total_pages - 1:
            self.current_page += 1
            self.update_buttons()
            await interaction.response.edit_message(embed=self.get_embed(), view=self)

    @discord.ui.button(label="❌ Close", style=discord.ButtonStyle.danger)
    async def close_button(self, button: discord.ui.Button, interaction: discord.Interaction):
        embed = discord.Embed(title="🦈 Blacklisted Discord UIDS", description="✅ Viewer closed.", color=discord.Color.dark_grey())
        await interaction.response.edit_message(embed=embed, view=None)
        self.stop()

class UpdateInfoModal(discord.ui.Modal):
    def __init__(self):
        super().__init__(title="Update License Info")
        self.license_key_input = discord.ui.InputText(label="License Key", placeholder="Target license key", required=True)
        self.username_input = discord.ui.InputText(label="Username", placeholder="New username (leave blank to keep unchanged)", required=False)
        self.password_input = discord.ui.InputText(label="Password", placeholder="New password (leave blank to keep unchanged)", required=False)
        self.valid_until_input = discord.ui.InputText(label="Valid Until", placeholder="YYYY-MM-DD (leave blank to keep unchanged)", required=False)
        self.hwid_input = discord.ui.InputText(label="HWID", placeholder="New HWID, 'RESET' to clear, or leave blank", required=False)

        self.add_item(self.license_key_input)
        self.add_item(self.username_input)
        self.add_item(self.password_input)
        self.add_item(self.valid_until_input)
        self.add_item(self.hwid_input)

    async def callback(self, interaction: discord.Interaction):
        license_key = self.license_key_input.value.strip()
        username = self.username_input.value.strip()
        password = self.password_input.value.strip()
        valid_until = self.valid_until_input.value.strip()
        hwid = self.hwid_input.value.strip()

        # Build payload with license_key as identifier
        payload = {'license_key': license_key}
        
        # Only add username if it's not empty
        if username:
            payload['username'] = username
        
        # Only add password if it's not empty
        if password:
            payload['password'] = password
            
        # Only add valid_until if it's not empty
        if valid_until:
            # Validate date
            try:
                datetime.strptime(valid_until, '%Y-%m-%d')
                payload['valid_until'] = valid_until
            except ValueError:
                await interaction.response.send_message("❌ Invalid date format. Use YYYY-MM-DD.", ephemeral=True)
                return
        
        # HWID LOGIC - Send empty string to clear/reset HWID
        hwid_raw = self.hwid_input.value
        
        # Only process hwid if the user actually typed something
        if hwid_raw is not None and hwid_raw.strip() != "":
            hwid_value = hwid_raw.strip()
            
            # Check if user wants to reset HWID (typed "RESET", "NULL", "CLEAR")
            if hwid_value.upper() in ["RESET", "NULL", "CLEAR"]:
                payload['hwid'] = ""  # Send empty string to clear HWID
            else:
                # User provided a new HWID value
                payload['hwid'] = hwid_value

        # Call your API
        api_url = f'{API_BASE_URL}/update_license.php'
        try:
            timeout = ClientTimeout(total=30)
            async with aiohttp.ClientSession(timeout=timeout) as session:
                async with session.post(api_url, json=payload) as resp:
                    response_text = await resp.text()
                    
                    if resp.status == 200:
                        try:
                            data = await resp.json()
                            if data.get('success'):
                                await interaction.response.send_message(
                                    f"✅ {data.get('message', 'License updated successfully!')}",
                                    ephemeral=True
                                )
                            else:
                                await interaction.response.send_message(
                                    f"❌ {data.get('message', 'Failed to update license.')}",
                                    ephemeral=True
                                )
                        except Exception as e:
                            await interaction.response.send_message(
                                f"✅ License updated for license key: {license_key}",
                                ephemeral=True
                            )
                    else:
                        await interaction.response.send_message(
                            f"❌ Server error (Status {resp.status}). Please try again later.", 
                            ephemeral=True
                        )
        except aiohttp.ClientError:
            await interaction.response.send_message(
                "❌ Network error. Unable to connect to the server.", 
                ephemeral=True
            )
        except asyncio.TimeoutError:
            await interaction.response.send_message(
                "❌ Request timed out. Please try again.", 
                ephemeral=True
            )
        except Exception as e:
            await interaction.response.send_message(
                "❌ An unexpected error occurred. Please try again.", 
                ephemeral=True
            )
class GenerateModal(discord.ui.Modal):
    def __init__(self):
        super().__init__(title="Create License")
        
        self.add_item(discord.ui.InputText(
            label="License Key",
            placeholder="Auto-generate or input",
            required=True
        ))
        self.add_item(discord.ui.InputText(
            label="Username", 
            placeholder="Username (optional - customer can set later)",
            required=False
        ))
        self.add_item(discord.ui.InputText(
            label="Password",
            placeholder="Password (optional - customer can set later)", 
            required=False
        ))
        self.add_item(discord.ui.InputText(
            label="Expiration Date",
            placeholder="YYYY-MM-DD",
            required=True
        ))

    def validate_date_format(self, date_string):
        """Validate that the date string is in YYYY-MM-DD format"""
        try:
            datetime.strptime(date_string, '%Y-%m-%d')
            return True
        except ValueError:
            return False

    def validate_username(self, username):
        """Validate username format (only if provided)"""
        if not username or username.strip() == "":
            return True  # Empty username is valid (optional field)
        pattern = r'^[a-zA-Z0-9_]{3,20}$'
        return bool(re.match(pattern, username))

    async def callback(self, interaction: discord.Interaction):
        # Get values from the input fields
        license_key = self.children[0].value.strip()
        username = self.children[1].value.strip() 
        password = self.children[2].value.strip()
        valid_until = self.children[3].value.strip()

        # Input validation
        if not self.validate_username(username):
            await interaction.response.send_message(
                "❌ Invalid username format. Username must be 3-20 characters long and contain only letters, numbers, and underscores.",
                ephemeral=True
            )
            return

        if not self.validate_date_format(valid_until):
            await interaction.response.send_message(
                "❌ Invalid date format. Please use YYYY-MM-DD format (e.g., 2024-12-31).",
                ephemeral=True
            )
            return

        # Check if date is in the future
        try:
            expiration_date = datetime.strptime(valid_until, '%Y-%m-%d')
            if expiration_date <= datetime.now():
                await interaction.response.send_message(
                    "❌ Expiration date must be in the future.",
                    ephemeral=True
                )
                return
        except ValueError:
            await interaction.response.send_message(
                "❌ Invalid date format. Please use YYYY-MM-DD format.",
                ephemeral=True
            )
            return

        # Prepare API request - only include username/password if provided
        api_url = f'{API_BASE_URL}/create_license.php'
        payload = {
            'license_key': license_key,
            'valid_until': valid_until
        }
        
        # Add optional fields only if they have values
        if username and username.strip():
            payload['username'] = username
        if password and password.strip():
            payload['password'] = password

        try:
            timeout = ClientTimeout(total=30)
            async with aiohttp.ClientSession(timeout=timeout) as session:
                async with session.post(api_url, json=payload) as resp:
                    
                    
                    if resp.status == 200:
                        try:
                            response_data = await resp.json()
                            if response_data.get('success'):
                                success_msg = f"✅ License created successfully!\n{response_data['message']}"
                                if not username or not password:
                                    success_msg += "\n\n📝 Note: Username/password were left empty. Customer can set these during registration."
                                await interaction.response.send_message(success_msg, ephemeral=True)
                            else:
                                await interaction.response.send_message(
                                    f"❌ Failed to create license: {response_data.get('message', 'Unknown error')}", 
                                    ephemeral=True
                                )
                        except:
                            # If JSON parsing fails, assume success if status is 200
                            success_msg = f"⭕ License created successfully!"
                            if username:
                                success_msg += f" for user: {username}"
                            if not username or not password:
                                success_msg += "\n\n📝 Note: Username/password were left empty. Customer can set these during registration."
                            await interaction.response.send_message(success_msg, ephemeral=True)
                    else:
                        await interaction.response.send_message(
                            f"❌ API request failed with status {resp.status}. Please try again later.",
                            ephemeral=True
                        )
                        
        except aiohttp.ClientError as e:
            await interaction.response.send_message(
                f"❌ Network error: Unable to connect to the license server. Please try again later.",
                ephemeral=True
            )
        except asyncio.TimeoutError:
            await interaction.response.send_message(
                "❌ Request timed out. Please try again later.",
                ephemeral=True
            )
        except Exception as e:
            await interaction.response.send_message(
                f"❌ An unexpected error occurred. Please try again later.",
                ephemeral=True
            )


class DeleteModal(discord.ui.Modal):
    def __init__(self):
        super().__init__(title="Delete License")
       
        self.add_item(discord.ui.InputText(
            label="License Key",
            placeholder="Enter license key to delete",
            required=True
        ))
    
    async def callback(self, interaction: discord.Interaction):
        license_key = self.children[0].value.strip()
       
        if not license_key:
            await interaction.response.send_message(
                "🥲 Please enter a license key to delete.",
                ephemeral=True
            )
            return
        
        # Prepare API request
        api_url = f'{API_BASE_URL}/delete_license.php'
        payload = {
            'license_key': license_key
        }
        
        try:
            timeout = ClientTimeout(total=30)
            async with aiohttp.ClientSession(timeout=timeout) as session:
                async with session.post(api_url, json=payload) as resp:
                    response_text = await resp.text()
                    print(f"Delete API Response: {response_text}")  # Debug logging
                   
                    if resp.status == 200:
                        try:
                            response_data = await resp.json()
                            if response_data.get('success'):
                                await interaction.response.send_message(
                                    f"✅ License deleted successfully!\n{response_data['message']}",
                                    ephemeral=True
                                )
                            else:
                                await interaction.response.send_message(
                                    f"❌ Failed to delete license: {response_data.get('message', 'License key not found')}",
                                    ephemeral=True
                                )
                        except:
                            # If JSON parsing fails, assume success if status is 200
                            await interaction.response.send_message(
                                f"✅ License deleted successfully for license key: {license_key}",
                                ephemeral=True
                            )
                    else:
                        await interaction.response.send_message(
                            f"❌ API request failed with status {resp.status}. Please try again later.",
                            ephemeral=True
                        )
                       
        except aiohttp.ClientError as e:
            await interaction.response.send_message(
                f"❌ Network error: Unable to connect to the license server. Please try again later.",
                ephemeral=True
            )
        except asyncio.TimeoutError:
            await interaction.response.send_message(
                "❌ Request timed out. Please try again later.",
                ephemeral=True
            )
        except Exception as e:
            await interaction.response.send_message(
                f"❌ An unexpected error occurred. Please try again later.",
                ephemeral=True
            )


class BlacklistModal(discord.ui.Modal):
    def __init__(self):
        super().__init__(title="Blacklist Discord UID 🙊")
        self.add_item(discord.ui.InputText(
            label="Discord UID",
            placeholder="e.g., 123456789012345678",
            required=True
        ))
        self.add_item(discord.ui.InputText(
            label="Reason",
            placeholder="Reason for blacklist (required)",
            required=True,
            max_length=200
        ))

    async def callback(self, interaction: discord.Interaction):
        discord_uid = self.children[0].value.strip()
        reason = self.children[1].value.strip()

        # Basic validation for Discord snowflakes (usually 17-19 digits, allow a bit wider)
        if not re.fullmatch(r"\d{15,21}", discord_uid):
            await interaction.response.send_message(
                "❌ Please enter a valid Discord UID (15-21 digits).",
                ephemeral=True
            )
            return

        if len(reason) < 3:
            await interaction.response.send_message(
                "❌ Please provide a reason (at least 3 characters).",
                ephemeral=True
            )
            return

        api_url = f"{API_BASE_URL}/blacklist.php"
        payload = {"discord_id": discord_uid, "reason": reason, "added_by": str(interaction.user.id)}

        try:
            timeout = ClientTimeout(total=30)
            headers = {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36",
                "Accept": "application/json, text/plain, */*"
            }
            async with aiohttp.ClientSession(timeout=timeout, headers=headers) as session:
                async with session.post(api_url, json=payload) as resp:
                    response_text = await resp.text()

                    if resp.status == 200:
                        try:
                            data = await resp.json()
                            if data.get("success"):
                                await interaction.response.send_message(
                                    data.get("message", "✅ UID has been blacklisted."),
                                    ephemeral=True
                                )
                            else:
                                await interaction.response.send_message(
                                    data.get("message", "❌ Failed to blacklist UID."),
                                    ephemeral=True
                                )
                        except Exception:
                            # If server returned non-JSON but OK, still confirm
                            await interaction.response.send_message(
                                "✅ UID has been blacklisted.",
                                ephemeral=True
                            )
                    else:
                        await interaction.response.send_message(
                            f"❌ Server error (Status {resp.status}). Please try again later.",
                            ephemeral=True
                        )
        except aiohttp.ClientError:
            await interaction.response.send_message(
                "❌ Network error. Unable to reach the server.",
                ephemeral=True
            )
        except asyncio.TimeoutError:
            await interaction.response.send_message(
                "❌ Request timed out. Please try again.",
                ephemeral=True
            )
        except Exception:
            await interaction.response.send_message(
                "❌ An unexpected error occurred. Please try again.",
                ephemeral=True
            )


class SearchUserModal(discord.ui.Modal):
    def __init__(self):
        super().__init__(title="Search License")
       
        self.add_item(discord.ui.InputText(
            label="License Key",
            placeholder="Enter license key to search",
            required=True
        ))
    
    async def callback(self, interaction: discord.Interaction):
        license_key = self.children[0].value.strip()
       
        if not license_key:
            await interaction.response.send_message(
                "❌ Please enter a license key to search.",
                ephemeral=True
            )
            return
        
        await interaction.response.defer(ephemeral=True)
        
        # Prepare API request
        api_url = f'{API_BASE_URL}/search_user.php'
        payload = {'license_key': license_key}
        
        try:
            timeout = ClientTimeout(total=30)
            async with aiohttp.ClientSession(timeout=timeout) as session:
                async with session.post(api_url, json=payload) as resp:
                    if resp.status == 200:
                        try:
                            response_data = await resp.json()
                            
                            if response_data.get('success') and response_data.get('user'):
                                user_data = response_data['user']
                               
                                embed = discord.Embed(
                                    title=f"🔍 License: {user_data.get('license_key', 'N/A')}",
                                    color=discord.Color.light_grey()
                                )
                               
                                embed.add_field(name="👤 Username", value=f"`{user_data.get('username', 'N/A')}`", inline=False)
                                embed.add_field(name="🔐 Password", value=f"`{user_data.get('password', 'N/A')}`", inline=False)
                                embed.add_field(name="🔑 License Key", value=f"`{user_data.get('license_key', 'N/A')}`", inline=False)
                                embed.add_field(name="📅 Valid Until", value=user_data.get('valid_until', 'N/A'), inline=True)
                                embed.add_field(name="🖥️ HWID", value=user_data.get('hwid', 'Not Set'), inline=True)
                                embed.add_field(name="📅 Created", value=user_data.get('created_at', 'N/A'), inline=True)
                                embed.add_field(name="🕐 Last Logon", value=user_data.get('last_logon', 'N/A'), inline=True)
                                embed.add_field(name="🆔 Discord UID", value=user_data.get('discord_uid', 'N/A'), inline=True)
                                embed.add_field(name="🆔 Discord UID Alt", value=user_data.get('discord_uid_alt', 'N/A'), inline=True)
                               
                                await interaction.followup.send(embed=embed, ephemeral=True)
                            else:
                                await interaction.followup.send(f"❌ License key '{license_key}' not found.", ephemeral=True)
                        except Exception as e:
                            await interaction.followup.send("❌ Failed to parse search results.", ephemeral=True)
                    else:
                        await interaction.followup.send(f"❌ Search failed with status {resp.status}.", ephemeral=True)
        except Exception as e:
            await interaction.followup.send(f"❌ Search error: {str(e)}", ephemeral=True)


# Setup intents
intents = discord.Intents.default()

# Create bot instance
bot = discord.Bot(intents=intents)

@bot.event
async def on_ready():
    print(f"✅ Logged in as {bot.user}")
    print(f"🆔 Bot ID: {bot.user.id}")
    print("🤖 Bot is ready to use!")
    
    # List all registered commands
    print(f"📋 Registered commands: {[cmd.name for cmd in bot.pending_application_commands]}")
    
    # Try to sync commands manually
    try:
        await bot.sync_commands()
        print("✅ Commands synced successfully!")
    except Exception as e:
        print(f"❌ Failed to sync commands: {e}")

@bot.event
async def on_application_command_error(ctx, error):
    print(f"❌ Command error: {error}")

# Register slash command (py-cord syntax)
@bot.slash_command(name="generate", description="Open form to generate license", guild_ids=[TEST_GUILD_ID] if TEST_GUILD_ID else None)
async def generate(ctx: discord.ApplicationContext):
    await ctx.response.send_modal(GenerateModal())

# Delete command
@bot.slash_command(name="delete", description="Delete a license by username", guild_ids=[TEST_GUILD_ID] if TEST_GUILD_ID else None)
async def delete(ctx: discord.ApplicationContext):
    await ctx.response.send_modal(DeleteModal())

# Blacklist command
@bot.slash_command(name="blacklist", description="Blacklist a Discord UID", guild_ids=[TEST_GUILD_ID] if TEST_GUILD_ID else None)
async def blacklist(ctx: discord.ApplicationContext):
    await ctx.response.send_modal(BlacklistModal())

@bot.slash_command(name="showblacklist", description="Display all blacklisted Discord UIDs", guild_ids=[TEST_GUILD_ID] if TEST_GUILD_ID else None)
async def showblacklist(ctx: discord.ApplicationContext):
    await ctx.defer(ephemeral=True)
    api_url = f"{API_BASE_URL}/get_blacklist.php"
    try:
        timeout = ClientTimeout(total=30)
        async with aiohttp.ClientSession(timeout=timeout) as session:
            async with session.get(api_url) as resp:
                response_text = await resp.text()
                if resp.status == 200:
                    try:
                        data = await resp.json()
                        rows = data.get('blacklist', []) if isinstance(data, dict) else []
                        if not rows:
                            await ctx.followup.send("📋 No blacklisted UIDs found.", ephemeral=True)
                            return
                        view = BlacklistPaginationView(rows, per_page=6)
                        await ctx.followup.send(embed=view.get_embed(), view=view, ephemeral=True)
                    except Exception:
                        await ctx.followup.send("❌ Failed to parse blacklist response.", ephemeral=True)
                else:
                    await ctx.followup.send(f"❌ API request failed with status {resp.status}.", ephemeral=True)
    except Exception as e:
        await ctx.followup.send(f"❌ Network error: {e}", ephemeral=True)

# NEW PAGINATED SHOWLICENSE COMMAND - REPLACE YOUR OLD ONE WITH THIS
@bot.slash_command(name="showlicense", description="Display all licenses in the database with pagination", guild_ids=[TEST_GUILD_ID] if TEST_GUILD_ID else None)
async def showlicense(ctx: discord.ApplicationContext):
    await ctx.defer(ephemeral=True)
    
    # Prepare API request
    api_url = f'{API_BASE_URL}/get_all_licenses.php'
    
    try:
        timeout = ClientTimeout(total=30)
        async with aiohttp.ClientSession(timeout=timeout) as session:
            async with session.get(api_url) as resp:
                response_text = await resp.text()
                print(f"ShowLicense API Response Status: {resp.status}")
                print(f"ShowLicense API Response: {response_text}")
                
                if resp.status == 200:
                    # Check if response is empty or whitespace
                    if not response_text.strip():
                        await ctx.followup.send(
                            "📋 No licenses found in the database (empty response).",
                            ephemeral=True
                        )
                        return
                    
                    try:
                        # Try to parse JSON
                        response_data = await resp.json()
                        
                        # Check if it's a successful response with licenses
                        if response_data.get('success') and response_data.get('licenses'):
                            licenses = response_data['licenses']
                            
                            # DEBUG: Print what fields are available
                            if licenses:
                                print(f"Available fields in first license: {list(licenses[0].keys())}")
                                print(f"First license data: {licenses[0]}")
                            
                            if len(licenses) == 0:
                                await ctx.followup.send(
                                    "📋 No licenses found in the database.",
                                    ephemeral=True
                                )
                                return
                            
                            # Create pagination view
                            view = LicensePaginationView(licenses, licenses_per_page=5)
                            embed = view.get_embed()
                            
                            await ctx.followup.send(embed=embed, view=view, ephemeral=True)
                        
                        elif response_data.get('success') and not response_data.get('licenses'):
                            await ctx.followup.send(
                                "📋 No licenses found in the database.",
                                ephemeral=True
                            )
                        
                        else:
                            # API returned success=false
                            error_msg = response_data.get('message', 'Unknown error from API')
                            await ctx.followup.send(
                                f"❌ API Error: {error_msg}",
                                ephemeral=True
                            )
                    
                    except ValueError as json_error:
                        # JSON parsing failed
                        print(f"JSON parsing error: {json_error}")
                        await ctx.followup.send(
                            f"❌ Server returned invalid response format.\n**Error:** {str(json_error)}\n**Raw response (first 500 chars):**\n```\n{response_text[:500]}\n```",
                            ephemeral=True
                        )
                
                else:
                    await ctx.followup.send(
                        f"❌ API request failed with status {resp.status}.\n**Response:**\n```\n{response_text[:500]}\n```",
                        ephemeral=True
                    )
                    
    except aiohttp.ClientError as e:
        await ctx.followup.send(
            f"❌ Network error: Unable to connect to the license server.\n**Error:** {str(e)}",
            ephemeral=True
        )
    except asyncio.TimeoutError:
        await ctx.followup.send(
            "❌ Request timed out. The server may be overloaded. Please try again later.",
            ephemeral=True
        )
    except Exception as e:
        await ctx.followup.send(
            f"❌ An unexpected error occurred.\n**Error:** {str(e)}",
            ephemeral=True
        )


# SHOW EXPIRED COMMAND
@bot.slash_command(name="showexpired", description="Display all expired licenses in the database with pagination", guild_ids=[TEST_GUILD_ID] if TEST_GUILD_ID else None)
async def showexpired(ctx: discord.ApplicationContext):
    await ctx.defer(ephemeral=True)
    
    # Prepare API request
    api_url = f'{API_BASE_URL}/get_expired_licenses.php'
    
    try:
        timeout = ClientTimeout(total=30)
        async with aiohttp.ClientSession(timeout=timeout) as session:
            async with session.get(api_url) as resp:
                response_text = await resp.text()
                print(f"ShowExpired API Response Status: {resp.status}")
                print(f"ShowExpired API Response: {response_text}")
                
                if resp.status == 200:
                    # Check if response is empty or whitespace
                    if not response_text.strip():
                        await ctx.followup.send(
                            "📓 No expired licenses found in the database (empty response).",
                            ephemeral=True
                        )
                        return
                    
                    try:
                        # Try to parse JSON
                        response_data = await resp.json()
                        
                        # Check if it's a successful response with licenses
                        if response_data.get('success') and response_data.get('licenses'):
                            expired_licenses = response_data['licenses']
                            
                            if len(expired_licenses) == 0:
                                await ctx.followup.send(
                                    "📓 No expired licenses found in the database.",
                                    ephemeral=True
                                )
                                return
                            
                            # Create pagination view with expired theme
                            view = LicensePaginationView(
                                expired_licenses, 
                                licenses_per_page=5, 
                                title="⭕ Expired Licenses",
                                expired_mode=True
                            )
                            embed = view.get_embed()
                            
                            await ctx.followup.send(embed=embed, view=view, ephemeral=True)
                        
                        elif response_data.get('success') and not response_data.get('licenses'):
                            await ctx.followup.send(
                                "📓 No expired licenses found in the database.",
                                ephemeral=True
                            )
                        
                        else:
                            # API returned success=false
                            error_msg = response_data.get('message', 'Unknown error from API')
                            await ctx.followup.send(
                                f"❌ API Error: {error_msg}",
                                ephemeral=True
                            )
                    
                    except ValueError as json_error:
                        # JSON parsing failed
                        print(f"JSON parsing error: {json_error}")
                        await ctx.followup.send(
                            f"❌ Server returned invalid response format.\n**Error:** {str(json_error)}\n**Raw response (first 500 chars):**\n```\n{response_text[:500]}\n```",
                            ephemeral=True
                        )
                
                else:
                    await ctx.followup.send(
                        f"❌ API request failed with status {resp.status}.\n**Response:**\n```\n{response_text[:500]}\n```",
                        ephemeral=True
                    )
                    
    except aiohttp.ClientError as e:
        await ctx.followup.send(
            f"❌ Network error: Unable to connect to the license server.\n**Error:** {str(e)}",
            ephemeral=True
        )
    except asyncio.TimeoutError:
        await ctx.followup.send(
            "❌ Request timed out. The server may be overloaded. Please try again later.",
            ephemeral=True
        )

# Add a test command to verify commands are working
@bot.slash_command(name="test", description="Test command to verify bot is working", guild_ids=[TEST_GUILD_ID] if TEST_GUILD_ID else None)
async def test(ctx: discord.ApplicationContext):
    await ctx.respond("✅ Bot is working! Commands are synchronized.", ephemeral=True)

# Force sync command (for debugging)
@bot.slash_command(name="sync", description="Force sync all commands", guild_ids=[TEST_GUILD_ID] if TEST_GUILD_ID else None)
async def sync_commands(ctx: discord.ApplicationContext):
    await ctx.defer(ephemeral=True)
    try:
        synced = await bot.sync_commands()
        await ctx.followup.send(f"✅ Successfully synced {len(synced)} commands!", ephemeral=True)
    except Exception as e:
        await ctx.followup.send(f"❌ Failed to sync commands: {e}", ephemeral=True)

@bot.slash_command(name="help", description="Display all enabled commands", guild_ids=[TEST_GUILD_ID] if TEST_GUILD_ID else None)
async def help_command(ctx: discord.ApplicationContext):
    await ctx.defer(ephemeral=True)
    try:
        commands_source = getattr(bot, "application_commands", None)
        if not commands_source:
            commands_source = getattr(bot, "pending_application_commands", [])

        developer_set = {"test", "sync"}
        seen_names = set()
        developer_cmds = []
        admin_cmds = []

        for command in commands_source:
            name = getattr(command, "name", None)
            description = getattr(command, "description", "") or "No description"
            if not name or name in seen_names:
                continue
            seen_names.add(name)
            if name in developer_set:
                developer_cmds.append((name, description))
            else:
                admin_cmds.append((name, description))

        developer_cmds.sort(key=lambda item: item[0].lower())
        admin_cmds.sort(key=lambda item: item[0].lower())

        def format_block(items):
            if not items:
                return "_None_"
            return "\n".join([f"`/{n}` — {d}" for n, d in items])

        embed = discord.Embed(
            title="❔Seraph Authorisation Command Help",
            description="List of enabled slash commands usable by you🤍",
            color=discord.Color.light_grey(),
            timestamp=datetime.now()
        )

        embed.add_field(name="🛠️ Developer", value=format_block(developer_cmds), inline=False)
        embed.add_field(name="🧑‍💼 Admin / Staff", value=format_block(admin_cmds), inline=False)

        # Fallback if somehow nothing is registered
        if not embed.fields:
            embed.description = "No commands are currently registered."

        await ctx.followup.send(embed=embed, ephemeral=True)
    except Exception as e:
        await ctx.followup.send(f"❌ Failed to generate help: {e}", ephemeral=True)

@bot.slash_command(name="updateinfo", description="Update license info", guild_ids=[TEST_GUILD_ID] if TEST_GUILD_ID else None)
async def updateinfo(ctx: discord.ApplicationContext):
    await ctx.response.send_modal(UpdateInfoModal())

@bot.slash_command(name="search", description="Search for a user by License", guild_ids=[TEST_GUILD_ID] if TEST_GUILD_ID else None)
async def search(ctx: discord.ApplicationContext):
    await ctx.response.send_modal(SearchUserModal())

# NEW STATS COMMAND
@bot.slash_command(name="stats", description="Display database statistics", guild_ids=[TEST_GUILD_ID] if TEST_GUILD_ID else None)
async def stats(ctx: discord.ApplicationContext):
    await ctx.defer(ephemeral=True)
    
    # Prepare API request
    api_url = f'{API_BASE_URL}/get_stats.php'
    
    try:
        timeout = ClientTimeout(total=30)
        async with aiohttp.ClientSession(timeout=timeout) as session:
            async with session.get(api_url) as resp:
                response_text = await resp.text()
                print(f"Stats API Response Status: {resp.status}")
                print(f"Stats API Response: {response_text}")
                
                if resp.status == 200:
                    try:
                        # Try to parse JSON
                        response_data = await resp.json()
                        
                        # Check if it's a successful response
                        if response_data.get('success'):
                            stats_data = response_data.get('stats', {})
                            
                            embed = discord.Embed(
                                title="📊 Database Statistics",
                                description="Current license database overview",
                                color=discord.Color.light_grey(),
                                timestamp=datetime.now()
                            )
                            
                            # Total users
                            total_users = stats_data.get('total_users', 0)
                            embed.add_field(
                                name="👥 Total Users", 
                                value=f"**{total_users:,}**", 
                                inline=True
                            )
                            
                            # Active licenses (non-expired)
                            active_licenses = stats_data.get('active_licenses', 0)
                            embed.add_field(
                                name="✅ Active Licenses", 
                                value=f"**{active_licenses:,}**", 
                                inline=True
                            )
                            
                            # Expired licenses
                            expired_licenses = stats_data.get('expired_licenses', 0)
                            embed.add_field(
                                name="❌ Expired Licenses", 
                                value=f"**{expired_licenses:,}**", 
                                inline=True
                            )
                            
                            # Users with HWID set
                            hwid_set = stats_data.get('hwid_set', 0)
                            embed.add_field(
                                name="🖥️ HWID Set", 
                                value=f"**{hwid_set:,}**", 
                                inline=True
                            )
                            
                            # Users without HWID
                            hwid_not_set = stats_data.get('hwid_not_set', 0)
                            embed.add_field(
                                name="🆓 HWID Not Set", 
                                value=f"**{hwid_not_set:,}**", 
                                inline=True
                            )
                            
                            # Recent registrations (last 7 days)
                            recent_registrations = stats_data.get('recent_registrations', 0)
                            embed.add_field(
                                name="📅 Last 7 Days", 
                                value=f"**{recent_registrations:,}** new", 
                                inline=True
                            )
                            
                            # Calculate percentages if we have data
                            if total_users > 0:
                                active_percent = (active_licenses / total_users) * 100
                                hwid_percent = (hwid_set / total_users) * 100
                                
                                embed.add_field(
                                    name="📈 Active Rate", 
                                    value=f"**{active_percent:.1f}%**", 
                                    inline=True
                                )
                                embed.add_field(
                                    name="🔒 HWID Rate", 
                                    value=f"**{hwid_percent:.1f}%**", 
                                    inline=True
                                )
                                embed.add_field(
                                    name="📊 Health Status", 
                                    value="🟢 **Healthy**" if active_percent > 70 else "🟡 **Warning**" if active_percent > 50 else "🔴 **Critical**", 
                                    inline=True
                                )
                            
                            embed.set_footer(text="Statistics updated")
                            
                            await ctx.followup.send(embed=embed, ephemeral=True)
                        
                        else:
                            # API returned success=false
                            error_msg = response_data.get('message', 'Unknown error from API')
                            await ctx.followup.send(
                                f"❌ API Error: {error_msg}",
                                ephemeral=True
                            )
                    
                    except ValueError as json_error:
                        # JSON parsing failed
                        print(f"JSON parsing error: {json_error}")
                        await ctx.followup.send(
                            f"❌ Server returned invalid response format.\n**Error:** {str(json_error)}\n**Raw response (first 500 chars):**\n```\n{response_text[:500]}\n```",
                            ephemeral=True
                        )
                
                else:
                    await ctx.followup.send(
                        f"❌ API request failed with status {resp.status}.\n**Response:**\n```\n{response_text[:500]}\n```",
                        ephemeral=True
                    )
                    
    except aiohttp.ClientError as e:
        await ctx.followup.send(
            f"❌ Network error: Unable to connect to the license server.\n**Error:** {str(e)}",
            ephemeral=True
        )
    except asyncio.TimeoutError:
        await ctx.followup.send(
            "❌ Request timed out. The server may be overloaded. Please try again later.",
            ephemeral=True
        )
    except Exception as e:
        await ctx.followup.send(
            f"❌ An unexpected error occurred.\n**Error:** {str(e)}",
            ephemeral=True
        )


# Missing HWID viewer
@bot.slash_command(name="missinghwid", description="Lists Users missing HWID Information", guild_ids=[TEST_GUILD_ID] if TEST_GUILD_ID else None)
async def missinghwid(ctx: discord.ApplicationContext):
    await ctx.defer(ephemeral=True)

    # Call endpoint without a limit parameter; server default will apply
    api_url = f"{API_BASE_URL}/missinghwid_count.php"
    try:
        timeout = ClientTimeout(total=30)
        async with aiohttp.ClientSession(timeout=timeout) as session:
            async with session.get(api_url) as resp:
                response_text = await resp.text()
                print(f"MissingHWID API Status: {resp.status}")
                print(f"MissingHWID API Response: {response_text}")

                if resp.status == 200:
                    try:
                        data = await resp.json()
                        rows = data.get('rows', []) if isinstance(data, dict) else []
                        if not rows:
                            await ctx.followup.send("📋 No users without HWID found.", ephemeral=True)
                            return

                        total_count = data.get('missing_hwid', len(rows)) if isinstance(data, dict) else len(rows)
                        view = MissingHWIDPaginationView(rows, per_page=6, total_count=total_count)
                        embed = view.get_embed()
                        await ctx.followup.send(embed=embed, view=view, ephemeral=True)

                    except Exception as e:
                        await ctx.followup.send(f"❌ Failed to parse response: {e}", ephemeral=True)
                else:
                    await ctx.followup.send(f"❌ API request failed with status {resp.status}.", ephemeral=True)

    except Exception as e:
        await ctx.followup.send(f"❌ Network error: {e}", ephemeral=True)


# License type view command - fetches specific counts from specificlicense.php
@bot.slash_command(name="licensetypeview", description="Show All current types of Licenses in Seraph", guild_ids=[TEST_GUILD_ID] if TEST_GUILD_ID else None)
async def licensetypeview(ctx: discord.ApplicationContext):
    """Fetch the PHP endpoint that returns counts per license prefix and display as a nicely formatted embed.
    This command fetches all types from the server (no keywords required).
    """
    await ctx.defer(ephemeral=True)

    # Build API URL (no keywords -> returns all counts)
    api_url = f"{API_BASE_URL}/specificlicense.php"

    try:
        timeout = ClientTimeout(total=30)
        async with aiohttp.ClientSession(timeout=timeout) as session:
            async with session.get(api_url) as resp:
                response_text = await resp.text()
                print(f"LicenseTypeView API Status: {resp.status}")
                print(f"LicenseTypeView API Response: {response_text}")

                if resp.status == 200:
                    # empty response check
                    if not response_text.strip():
                        await ctx.followup.send("📊 No data returned from server.", ephemeral=True)
                        return

                    try:
                        data = await resp.json()

                        # data is expected to be a simple dict of name->count
                        if isinstance(data, dict) and data:
                            # Build embed
                            embed = discord.Embed(
                                title="🔐🐪 License Types UwW :3",
                                description="License type collects from a prefix",
                                color=discord.Color.light_grey(),
                                timestamp=datetime.now()
                            )

                            # Sort keys but keep OTHER last if present
                            keys = [k for k in data.keys() if k != 'OTHER']
                            keys.sort()
                            if 'OTHER' in data:
                                keys.append('OTHER')

                            # Add one non-inline field per license type for a stacked look
                            for key in keys:
                                try:
                                    val = int(data.get(key, 0))
                                except Exception:
                                    try:
                                        val = int(str(data.get(key, '0')).strip())
                                    except Exception:
                                        val = 0

                                # Skip zero counts to keep the embed concise
                                if val == 0:
                                    continue

                                
                                embed.add_field(name=f"🟢`{key}` | {val:,}", value="\u200b", inline=False)

                            
                            if not embed.fields:
                                embed.description = "No license types with counts > 0 were returned."

                            await ctx.followup.send(embed=embed, ephemeral=True)
                        else:
                            await ctx.followup.send("❌ Well Seems there no one in the database with that license prefix gulp", ephemeral=True)

                    except Exception as je:
                        print(f"JSON parse error: {je}")
                        raw_snippet = response_text[:500]
                        await ctx.followup.send(
                            "❌ Failed to parse server response as JSON.\n**Raw:**\n```\n" + raw_snippet + "\n```",
                            ephemeral=True
                        )

                else:
                    snippet = response_text[:500]
                    await ctx.followup.send(
                        "❌ API request failed with status {}.\n**Response:**\n```\n{}\n```".format(resp.status, snippet),
                        ephemeral=True
                    )

    except aiohttp.ClientError as e:
        await ctx.followup.send(f"❌ Network error: {str(e)}", ephemeral=True)
    except asyncio.TimeoutError:
        await ctx.followup.send("❌ Request timed out.", ephemeral=True)
    except Exception as e:
        await ctx.followup.send(f"❌ An unexpected error occurred: {str(e)}", ephemeral=True)


# Main execution
if __name__ == "__main__":
    if not TOKEN:
        print("❌ Error: Bot token is not set!")
        exit(1)
    
    try:
        bot.run(TOKEN)
    except discord.LoginFailure:
        print("❌ Invalid bot token. Please check your token.")
    except Exception as e:
        print(f"❌ Failed to start bot: {e}")