import asyncio
import os
import logging
from aiogram import Bot, Dispatcher, types, BaseMiddleware
from aiogram.filters import Command
from aiogram.types import FSInputFile, InlineKeyboardMarkup, InlineKeyboardButton
from aiogram.client.default import DefaultBotProperties
from aiogram.client.session.aiohttp import AiohttpSession # <-- TAMBAH INI
from dotenv import load_dotenv
from apscheduler.schedulers.asyncio import AsyncIOScheduler

# Import modul lokal yang sudah kita buat
from yt_engine import process_youtube_request
from db_manager import db
from s3_manager import upload_audio, download_audio, delete_audio

# Setup Logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

load_dotenv()
BOT_TOKEN = os.getenv("BOT_TOKEN")
# Pastikan ini mengambil angka ID Telegram kamu
AUTHORIZED_USER_ID = int(os.getenv("AUTHORIZED_USER_ID", 0)) 

# --- INISIALISASI BOT ---
# Timeout diatur 300 detik (5 menit) agar Telegram tidak memutus koneksi saat mengirim file MP3 yang besar
session = AiohttpSession(timeout=300) 

bot = Bot(
    token=BOT_TOKEN, 
    session=session, 
    default=DefaultBotProperties(parse_mode=None)
)
dp = Dispatcher()
# --- MIDDLEWARE / SECURITY CHECK ---
class SecurityMiddleware(BaseMiddleware):
    async def __call__(self, handler, event: types.Message, data: dict):
        # Memblokir semua orang kecuali Kamu (Single-User Mode)
        if event.from_user.id != AUTHORIZED_USER_ID:
            logger.warning(f"Akses ditolak untuk User ID: {event.from_user.id}")
            return # Abaikan pesan
        return await handler(event, data)

# Daftarkan Satpam ke sistem
dp.message.middleware(SecurityMiddleware())

# --- COMMAND HANDLERS ---
@dp.message(Command("start"))
async def cmd_start(message: types.Message):
    await message.answer(
        "🎧 **Kantor-Bypass Music Bot Ready!**\n\n"
        "Kirim judul lagu atau link YouTube dengan format:\n"
        "`/play <judul/link>`\n\n"
        "Contoh: `/play Dewa 19 Kangen`"
    )

@dp.message(Command("play"))
async def cmd_play(message: types.Message):
    query = message.text.replace("/play", "").strip()
    if not query:
        return await message.answer("⚠️ Masukkan judul lagu. Contoh: `/play Nadin Amizah`")

    # Kirim status loading
    status_msg = await message.answer("🔍 *Mencari dan memproses...*")
    
    # Gunakan asyncio.create_task agar tidak nge-block queue bot (bisa antre banyak lagu)
    asyncio.create_task(process_music_request(query, message.chat.id, status_msg.message_id))

# --- CORE LOGIC: PROCESS MUSIC ---
async def process_music_request(query: str, chat_id: int, status_msg_id: int):
    local_file = None # Mencegah error 'UnboundLocalError' jika gagal di awal
    try:
        # 1. Download dari YouTube
        yt_result = await process_youtube_request(query)
        
        if yt_result["status"] == "error":
            return await bot.edit_message_text(f"❌ Gagal: {yt_result['message']}", chat_id, status_msg_id)
            
        video_id = yt_result["video_id"]
        title = yt_result["title"]
        local_file = yt_result["file_path"]
        s3_object_name = f"{video_id}.mp3"

        # 2. Cek Cache di Database
        cached_data = await db.get_cache(video_id)
        
        if cached_data:
            await bot.edit_message_text("⚡ *Mengambil dari Cache S3...*", chat_id, status_msg_id)
            # Download dari S3 ke local temporary
            local_file = f"downloads/cache_{video_id}.mp3"
            await download_audio(s3_object_name, local_file)
        else:
            await bot.edit_message_text("☁️ *Mengunggah ke S3 Storage...*", chat_id, status_msg_id)
            # Upload file baru ke S3
            if local_file and os.path.exists(local_file):
                await upload_audio(local_file, s3_object_name)
                await db.save_cache(video_id, title, s3_object_name)

        # 3. Kirim Audio ke Telegram
        await bot.edit_message_text("📤 *Mengirim audio ke Telegram... (Mungkin butuh waktu)*", chat_id, status_msg_id)
        
        if local_file and os.path.exists(local_file):
            audio = FSInputFile(local_file)
            
            # Opsi: Tombol pencarian selanjutnya
            kb = [[InlineKeyboardButton(text="🎵 Putar Lagu Acak Lainnya", switch_inline_query_current_chat="")]]
            reply_markup = InlineKeyboardMarkup(inline_keyboard=kb)

            # Ekstra Pengaman Timeout di Request Level
            await bot.send_audio(
                chat_id=chat_id,
                audio=audio,
                title=title,
                performer="Music Bot",
                reply_markup=reply_markup,
                request_timeout=300
            )
            
            # Hapus pesan status yang muter-muter
            await bot.delete_message(chat_id, status_msg_id)
        else:
             await bot.edit_message_text("❌ File audio tidak ditemukan di server lokal.", chat_id, status_msg_id)

    except Exception as e:
        logger.error(f"Error processing music: {e}")
        try:
            await bot.edit_message_text(f"❌ Terjadi kesalahan internal: {e}", chat_id, status_msg_id)
        except:
            pass # Abaikan jika pesan sudah terhapus
        
    finally:
        # 4. Hapus file temporary di VPS (Hemat Disk!)
        if local_file and os.path.exists(local_file):
            os.remove(local_file)

# --- BACKGROUND JOB: AUTO CLEANUP (7 HARI) ---
async def cleanup_expired_cache():
    logger.info("🧹 Menjalankan tugas pembersihan cache otomatis...")
    expired_items = await db.get_expired_cache(days=7)
    
    for item in expired_items:
        # Hapus dari S3
        await delete_audio(item['s3_object_key'])
        # Hapus dari Database
        await db.delete_cache(item['youtube_id'])
        logger.info(f"🗑️ Dihapus: {item['title']} (Usia > 7 Hari)")

# --- MAIN LOOP ---
async def main():
    # Konek ke database
    await db.connect()
    
    # Jalankan Scheduler untuk bersih-bersih tiap jam 3 pagi
    scheduler = AsyncIOScheduler()
    scheduler.add_job(cleanup_expired_cache, 'cron', hour=3, minute=0)
    scheduler.start()

    logger.info("🚀 Bot Music Started!")
    
    # Hapus webhook lama (jika ada) dan mulai polling
    await bot.delete_webhook(drop_pending_updates=True)
    await dp.start_polling(bot)

if __name__ == "__main__":
    asyncio.run(main())
