import discord
from discord import app_commands
from discord.ext import commands
import asyncio
import random
from datetime import datetime, timedelta
import logging
from database import db
from utils.security import parse_money_string, format_money_string

logger = logging.getLogger("gamble_bot.cogs.events")

def is_crown_owner(interaction: discord.Interaction) -> bool:
    """Returns True ONLY if the user is the Server Owner (Crown Holder)."""
    return bool(interaction.guild and interaction.user.id == interaction.guild.owner_id)

def owner_only():
    """Decorator enforcing that only the crown owner can trigger the command."""
    async def predicate(interaction: discord.Interaction) -> bool:
        if is_crown_owner(interaction):
            return True
        await interaction.response.send_message("❌ **Yetkisiz Erişim:** Bu etkinliği sadece sunucu sahibi başlatabilir!", ephemeral=True)
        return False
    return app_commands.check(predicate)


class GiveawayView(discord.ui.View):
    """Interactive join button for server giveaways."""
    def __init__(self, reward_str: str, winner_count: int, end_time: datetime, title: str):
        super().__init__(timeout=None)
        self.reward_str = reward_str
        self.winner_count = winner_count
        self.end_time = end_time
        self.title = title
        self.participants = set()
        self.ended = False

    @discord.ui.button(label="Katıl (0)", style=discord.ButtonStyle.success, emoji="🎉", custom_id="giveaway_join_btn")
    async def join_giveaway(self, interaction: discord.Interaction, button: discord.ui.Button):
        if self.ended:
            await interaction.response.send_message("❌ Bu etkinlik sona erdi!", ephemeral=True)
            return

        user_id = interaction.user.id
        if user_id in self.participants:
            self.participants.remove(user_id)
            button.label = f"Katıl ({len(self.participants)})"
            await interaction.response.edit_message(view=self)
            await interaction.followup.send("👋 Etkinlik katılımınız iptal edildi.", ephemeral=True)
        else:
            self.participants.add(user_id)
            button.label = f"Katıl ({len(self.participants)})"
            await interaction.response.edit_message(view=self)
            await interaction.followup.send("🎉 **Etkinliğe başarıyla katıldınız!** Bol şanslar dileriz.", ephemeral=True)


class FlashRainView(discord.ui.View):
    """Fast-reaction button for Flash Money Rain events."""
    def __init__(self, amount_per_person: float, max_claimers: int):
        super().__init__(timeout=120.0)
        self.amount_per_person = amount_per_person
        self.max_claimers = max_claimers
        self.claimed_users = set()

    @discord.ui.button(label="💸 Parayı Kap (0)", style=discord.ButtonStyle.primary, emoji="⚡", custom_id="flash_rain_btn")
    async def claim_rain(self, interaction: discord.Interaction, button: discord.ui.Button):
        if len(self.claimed_users) >= self.max_claimers:
            button.disabled = True
            button.label = f"Tükendi ({len(self.claimed_users)}/{self.max_claimers})"
            button.style = discord.ButtonStyle.secondary
            await interaction.response.edit_message(view=self)
            await interaction.followup.send("❌ Maalesef tüm ödüller kapıldı!", ephemeral=True)
            return

        user_id = interaction.user.id
        if user_id in self.claimed_users:
            await interaction.response.send_message("❌ Bu para yağmurundan zaten ödülünüzü aldınız!", ephemeral=True)
            return

        self.claimed_users.add(user_id)
        
        # Credit balance instantly
        await db.register_user(user_id)
        new_balance = await db.update_balance(
            user_id,
            self.amount_per_person,
            "event_reward",
            f"Para Yağmuru Etkinlik Ödülü: {self.amount_per_person}"
        )

        button.label = f"Kapıldı ({len(self.claimed_users)}/{self.max_claimers})"
        if len(self.claimed_users) >= self.max_claimers:
            button.disabled = True
            button.style = discord.ButtonStyle.secondary

        await interaction.response.edit_message(view=self)
        await interaction.followup.send(
            f"⚡ **TEBRİKLER!** Hızlı davranıp **+{format_money_string(self.amount_per_person)}** kaptınız!\n"
            f"Güncel Bakiyeniz: 💰 **{format_money_string(new_balance)}**",
            ephemeral=True
        )


class EventsCog(commands.Cog, name="Etkinlikler & Çekilişler"):
    def __init__(self, bot):
        self.bot = bot

    @app_commands.command(name="etkinlik_baslat", description="Otomatik ödül yükleyen canlı çekiliş/etkinlik başlatır.")
    @app_commands.describe(
        odul="Dağıtılacak ödül (örn: 100m, 500m, 1b)",
        kazanan_sayisi="Kaç kişi kazanacak? (Varsayılan: 1)",
        sure_dakika="Etkinlik süresi kaç dakika? (örn: 30, 60, 1440)",
        baslik="Etkinliğin başlığı / adı"
    )
    @owner_only()
    async def start_giveaway(
        self,
        interaction: discord.Interaction,
        odul: str,
        sure_dakika: int,
        kazanan_sayisi: int = 1,
        baslik: str = "🎁 BÜYÜK KOLİC GAMBLE ETKİNLİĞİ"
    ):
        """Starts a scheduled giveaway with auto-crediting winnings to winners."""
        reward_val = parse_money_string(odul)
        if reward_val <= 0:
            await interaction.response.send_message("❌ Geçerli bir ödül miktarı girin (Örn: 100m, 500m).", ephemeral=True)
            return

        if sure_dakika <= 0 or kazanan_sayisi <= 0:
            await interaction.response.send_message("❌ Süre ve kazanan sayısı 0'dan büyük olmalıdır.", ephemeral=True)
            return

        guild = interaction.guild
        target_channel = discord.utils.get(guild.text_channels, name="🎁・etkinlikler") or interaction.channel
        end_time = datetime.utcnow() + timedelta(minutes=sure_dakika)
        end_timestamp = int(end_time.timestamp())

        embed = discord.Embed(
            title=f"🎉 {baslik}",
            description=(
                f"KolicGamble resmi sunucu etkinliği başladı!\n\n"
                f"💰 **Ödül:** **{format_money_string(reward_val)}**\n"
                f"🏆 **Kazanan Kişi Sayısı:** `{kazanan_sayisi}` Kişi\n"
                f"⏱️ **Bitiş Zamanı:** <t:{end_timestamp}:R> (<t:{end_timestamp}:F>)\n"
                f"👑 **Düzenleyen:** {interaction.user.mention}\n\n"
                f"👇 *Katılmak için aşağıdaki **[🎉 Katıl]** butonuna tıklayın!*"
            ),
            color=discord.Color.purple(),
            timestamp=end_time
        )
        embed.set_footer(text="Bitiş Tarihi • KolicGamble Etkinlik")

        view = GiveawayView(odul, kazanan_sayisi, end_time, baslik)
        
        await interaction.response.send_message(f"✅ Etkinlik başarıyla {target_channel.mention} kanalında başlatıldı!", ephemeral=True)
        giveaway_msg = await target_channel.send(content="@everyone 🎁 **YENİ ETKİNLİK BAŞLADI!**", embed=embed, view=view)

        # Background timer for giveaway resolution
        async def end_giveaway_task():
            await asyncio.sleep(sure_dakika * 60)
            view.ended = True
            for child in view.children:
                child.disabled = True

            if not view.participants:
                embed.description = f"❌ **Etkinlik Sona Erdi!**\nYeterli katılım olmadığı için kazanan seçilemedi."
                embed.color = discord.Color.red()
                await giveaway_msg.edit(content=None, embed=embed, view=view)
                return

            # Draw winners
            participant_list = list(view.participants)
            num_winners = min(kazanan_sayisi, len(participant_list))
            winner_ids = random.sample(participant_list, num_winners)
            
            winner_mentions = []
            for w_id in winner_ids:
                # Credit balance to each winner
                try:
                    await db.register_user(w_id)
                    await db.update_balance(
                        w_id,
                        reward_val,
                        "giveaway_win",
                        f"Etkinlik Galibiyeti: {baslik} ({format_money_string(reward_val)})"
                    )
                    w_user = guild.get_member(w_id) or await self.bot.fetch_user(w_id)
                    winner_mentions.append(w_user.mention if w_user else f"<@{w_id}>")
                    
                    # Send DM to winner
                    try:
                        if w_user:
                            dm_embed = discord.Embed(
                                title="🎉 TEBRİKLER! Etkinliği Kazandınız!",
                                description=(
                                    f"**{guild.name}** sunucusundaki **{baslik}** çekilişini kazandınız!\n\n"
                                    f"💰 **Kazanılan Ödül:** **{format_money_string(reward_val)}**\n"
                                    f"Ödülünüz doğrudan Discord cüzdan bakiyenize otomatik olarak yüklenmiştir!"
                                ),
                                color=discord.Color.green(),
                                timestamp=datetime.utcnow()
                            )
                            await w_user.send(embed=dm_embed)
                    except Exception:
                        pass
                except Exception as e:
                    logger.error(f"Error crediting giveaway winner {w_id}: {e}")

            winners_text = ", ".join(winner_mentions)
            embed.title = f"🎊 ETKİNLİK SONA ERDİ — {baslik}"
            embed.description = (
                f"🎁 **Ödül:** **{format_money_string(reward_val)}**\n"
                f"👥 **Toplam Katılımcı:** `{len(view.participants)}` Kişi\n\n"
                f"🏆 **KAZANANLAR:**\n"
                f"👉 {winners_text}\n\n"
                f"💵 *Ödüller kazananların Discord cüzdan bakiyelerine otomatik olarak aktarılmıştır!*"
            )
            embed.color = discord.Color.green()
            await giveaway_msg.edit(content=f"🎉 **Tebrikler:** {winners_text}", embed=embed, view=view)

        asyncio.create_task(end_giveaway_task())

    @app_commands.command(name="para_yagmuru", description="Kanala ilk tıklayanların anında nakit kapacağı Para Yağmuru başlatır.")
    @app_commands.describe(
        toplam_odul="Toplam dağıtılacak para (örn: 100m, 500m)",
        kisi_sayisi="Kaç kişi kapabilecek? (örn: 5, 10)"
    )
    @owner_only()
    async def flash_rain(self, interaction: discord.Interaction, toplam_odul: str, kisi_sayisi: int = 5):
        """Spawns an interactive flash button where the first N clickers claim cash."""
        total_val = parse_money_string(toplam_odul)
        if total_val <= 0 or kisi_sayisi <= 0:
            await interaction.response.send_message("❌ Geçerli bir ödül miktarı ve kişi sayısı girin.", ephemeral=True)
            return

        amount_per_person = round(total_val / kisi_sayisi, 2)
        target_channel = discord.utils.get(interaction.guild.text_channels, name="🎁・etkinlikler") or interaction.channel

        embed = discord.Embed(
            title="⚡ ANLIK PARA YAĞMURU BAŞLADI!",
            description=(
                f"🎉 {interaction.user.mention} kanala nakit para fırlattı!\n\n"
                f"💰 **Toplam Ödül:** **{format_money_string(total_val)}**\n"
                f"💵 **Kişi Başı Kazanç:** **{format_money_string(amount_per_person)}**\n"
                f"🏃 **İlk Tıklayan:** `{kisi_sayisi}` Kişi Kapacak!\n\n"
                f"👇 *Aşağıdaki butona ilk tıklayanlar parayı cüzdanına indirir!*"
            ),
            color=discord.Color.gold(),
            timestamp=datetime.utcnow()
        )
        embed.set_footer(text="Hızlı Olan Kazanır • KolicGamble")

        view = FlashRainView(amount_per_person, kisi_sayisi)
        await interaction.response.send_message(f"✅ Para Yağmuru {target_channel.mention} kanalına gönderildi!", ephemeral=True)
        await target_channel.send(content="@here ⚡ **PARAYI İLK KAP KAZAN!**", embed=embed, view=view)


async def setup(bot):
    await bot.add_cog(EventsCog(bot))
