﻿"""
ggbro Music Bot
Posts song info and YouTube links to chat. Users can use ggbro's
built-in floating player to listen.

Requirements:
    pip install python-socketio[client] requests yt-dlp

Commands:
    /play <query>     - Search YouTube and add to queue
    /stop             - Clear the queue
    /skip             - Skip current song
    /queue            - Show the queue
    /nowplaying       - Show current song
"""

import logging
import os
import re
import subprocess
import json
from ggbro import Bot, SlashCommand

logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(name)s] %(message)s')

# â”€â”€ Configuration â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
BOT_TOKEN = 'YOUR_BOT_TOKEN'
PUBLIC_API_URL = os.getenv('GGBRO_PUBLIC_URL', 'https://ggbro.app')
GATEWAY_URL = os.getenv('GGBRO_GATEWAY_URL', PUBLIC_API_URL)

bot = Bot(token=BOT_TOKEN, api_url=PUBLIC_API_URL, gateway_url=GATEWAY_URL)

# Per-server queues: server_id -> list of {title, url, duration, requested_by}
queues: dict[str, list[dict]] = {}
# Per-server now-playing index
now_playing: dict[str, int] = {}

# â”€â”€ Helpers â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€

def search_youtube(query: str) -> dict | None:
    """Search YouTube using yt-dlp and return the first result."""
    try:
        # If it's already a URL, use it directly
        if re.match(r'https?://', query):
            search_query = query
        else:
            search_query = f'ytsearch1:{query}'

        result = subprocess.run(
            ['yt-dlp', '--no-download', '--print-json', '--flat-playlist',
             '--no-warnings', '-q', search_query],
            capture_output=True, text=True, timeout=15
        )

        if result.returncode != 0 or not result.stdout.strip():
            return None

        info = json.loads(result.stdout.strip().split('\n')[0])
        video_id = info.get('id', '')
        title = info.get('title', 'Unknown')
        duration = info.get('duration')
        url = info.get('webpage_url') or info.get('url') or f'https://www.youtube.com/watch?v={video_id}'

        duration_str = ''
        if duration:
            mins, secs = divmod(int(duration), 60)
            duration_str = f'{mins}:{secs:02d}'

        return {
            'title': title,
            'url': url,
            'duration': duration_str,
        }
    except Exception as e:
        logging.error('YouTube search failed: %s', e)
        return None


def format_duration(d: str) -> str:
    return f' ({d})' if d else ''


# â”€â”€ Register commands â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€

bot.register_commands([
    SlashCommand(name='play', description='Play a song from YouTube', options=[
        {'name': 'query', 'description': 'YouTube URL or search query', 'required': True}
    ]),
    SlashCommand(name='stop', description='Stop playback and clear the queue'),
    SlashCommand(name='skip', description='Skip to the next song'),
    SlashCommand(name='queue', description='Show the current song queue'),
    SlashCommand(name='nowplaying', description='Show the currently playing song'),
])

# â”€â”€ Command handlers â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€

@bot.command('play')
def play(ctx):
    # Prefer typed options â€” positional args is the fallback for simple commands
    query = str(ctx.get_option('query', ctx.args) or '').strip()
    if not query:
        ctx.reply('âŒ Please provide a YouTube URL or search query!\nUsage: `/play <song name or URL>`')
        return

    ctx.reply(f'ðŸ” Searching for **{query}**...')

    song = search_youtube(query)
    if not song:
        ctx.reply('âŒ No results found. Try a different search query.')
        return

    song['requested_by'] = ctx.user.get('username', 'Someone')
    server_id = ctx.server_id

    if server_id not in queues:
        queues[server_id] = []
        now_playing[server_id] = 0

    queues[server_id].append(song)
    position = len(queues[server_id])

    dur = format_duration(song['duration'])
    if position == 1:
        ctx.reply(
            f'ðŸŽµ **Now Playing:**\n'
            f'**{song["title"]}**{dur}\n'
            f'{song["url"]}\n'
            f'Requested by {song["requested_by"]}'
        )
    else:
        ctx.reply(
            f'âœ… Added to queue (#{position}):\n'
            f'**{song["title"]}**{dur}\n'
            f'Requested by {song["requested_by"]}'
        )


@bot.command('stop')
def stop(ctx):
    server_id = ctx.server_id
    if server_id in queues:
        count = len(queues[server_id])
        queues[server_id] = []
        now_playing[server_id] = 0
        ctx.reply(f'â¹ï¸ Stopped playback and cleared {count} song(s) from the queue.')
    else:
        ctx.reply('ðŸ“­ Nothing is playing.')


@bot.command('skip')
def skip(ctx):
    server_id = ctx.server_id
    q = queues.get(server_id, [])
    idx = now_playing.get(server_id, 0)

    if not q or idx >= len(q):
        ctx.reply('ðŸ“­ Nothing to skip.')
        return

    skipped = q[idx]
    now_playing[server_id] = idx + 1

    if idx + 1 < len(q):
        next_song = q[idx + 1]
        dur = format_duration(next_song['duration'])
        ctx.reply(
            f'â­ï¸ Skipped **{skipped["title"]}**\n'
            f'ðŸŽµ **Now Playing:** **{next_song["title"]}**{dur}\n'
            f'{next_song["url"]}'
        )
    else:
        ctx.reply(f'â­ï¸ Skipped **{skipped["title"]}**\nðŸ“­ Queue is now empty.')
        queues[server_id] = []
        now_playing[server_id] = 0


@bot.command('queue')
def show_queue(ctx):
    server_id = ctx.server_id
    q = queues.get(server_id, [])
    idx = now_playing.get(server_id, 0)

    if not q or idx >= len(q):
        ctx.reply('ðŸ“­ The queue is empty! Use `/play` to add songs.')
        return

    lines = []
    for i, song in enumerate(q[idx:idx + 10], start=1):
        dur = format_duration(song['duration'])
        prefix = 'ðŸŽµ' if i == 1 else f'{i}.'
        lines.append(f'{prefix} **{song["title"]}**{dur} â€” {song["requested_by"]}')

    remaining = len(q) - idx - 10
    if remaining > 0:
        lines.append(f'... and {remaining} more')

    ctx.reply('ðŸŽ¶ **Queue:**\n' + '\n'.join(lines))


@bot.command('nowplaying')
def now_playing_cmd(ctx):
    server_id = ctx.server_id
    q = queues.get(server_id, [])
    idx = now_playing.get(server_id, 0)

    if not q or idx >= len(q):
        ctx.reply('ðŸ“­ Nothing is playing right now.')
        return

    song = q[idx]
    dur = format_duration(song['duration'])
    pos = f'{idx + 1}/{len(q)}'
    ctx.reply(
        f'ðŸŽµ **Now Playing ({pos}):**\n'
        f'**{song["title"]}**{dur}\n'
        f'{song["url"]}\n'
        f'Requested by {song["requested_by"]}'
    )


# â”€â”€ Events â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€

@bot.event('ready')
def on_ready():
    print('âœ… Music Bot is online!')


# â”€â”€ Start â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€

if __name__ == '__main__':
    bot.run()
