import logging
import shlex
from aiogram import Router, F
from aiogram.filters import Command
from aiogram.types import Message, BufferedInputFile, CallbackQuery
from aiogram.fsm.context import FSMContext
from sqlalchemy.ext.asyncio import AsyncSession

from src.database.session import SessionLocal
from src.database.db_methods.users import delete_user_by_tg, get_all_user_tg_ids
from src.database.db_methods.export import export_users_to_excel
from src.database.enums import MassageTechnique
from src.bot.middleware.admin import AdminMiddleware
from src.bot.keyboards.admin import kb_admin_commands
from src.bot.states.survey import BroadcastFSM

logger = logging.getLogger(__name__)
router = Router(name="dev_tools_router")

# Admin router with middleware
admin_router = Router(name="admin_router")
admin_router.message.middleware(AdminMiddleware())
admin_router.callback_query.middleware(AdminMiddleware())


@router.message(Command("clear_user"))
async def clear_user_cmd(message: Message, state: FSMContext):
    await state.clear()
    tg_id = str(message.from_user.id)

    async with SessionLocal() as session:  # type: AsyncSession
        deleted = await delete_user_by_tg(session, tg_id)
        await session.commit()

    await message.answer(
        "🧹 Всё удалено, можно проходить /start заново." if deleted
        else "ℹ️ Пользователь не найден. Просто запусти /start."
    )


@admin_router.message(Command("export_users"))
async def export_users_cmd(message: Message):
    try:
        # Parse command arguments with proper quote handling
        if message.text:
            try:
                # Use shlex to properly parse quoted arguments
                parts = shlex.split(message.text)
                args = parts[1:] if len(parts) > 1 else []
            except ValueError:
                # Fallback to simple split if shlex fails
                args = message.text.split()[1:]
        else:
            args = []
        
        city = None
        technique = None
        
        if len(args) >= 1 and args[0] and args[0] not in ('""', "''", ''):
            city = args[0]
        
        if len(args) >= 2 and args[1] and args[1] not in ('""', "''", ''):
            try:
                technique = MassageTechnique(args[1])
            except ValueError:
                await message.answer(
                    f"❌ Неверная техника массажа: {args[1]}\n"
                    f"Доступные: {', '.join([t.value for t in MassageTechnique])}"
                )
                return
        
        # Show processing message
        filter_info = []
        if city:
            filter_info.append(f"город: {city}")
        if technique:
            filter_info.append(f"техника: {technique.value}")
        
        filter_text = f" (фильтр: {', '.join(filter_info)})" if filter_info else ""
        await message.answer(f"📊 Формирую Excel файл{filter_text}...")
        
        # Export to Excel
        async with SessionLocal() as session:
            excel_file = await export_users_to_excel(
                session,
                city=city if city else None,
                massage_technique=technique,
            )
        
        # Send file
        filename = "users_export.xlsx"
        if city:
            filename = f"users_{city.replace(' ', '_')}.xlsx"
        if technique:
            filename = filename.replace('.xlsx', f'_{technique.value.replace(" ", "_")}.xlsx')
        
        file = BufferedInputFile(
            excel_file.read(),
            filename=filename
        )
        
        await message.answer_document(
            file,
            caption=f"📊 Экспорт пользователей{filter_text}"
        )
        
        logger.info(f"User {message.from_user.id} exported users (city={city}, technique={technique})")
        
    except Exception as e:
        logger.exception(f"Error exporting users: {e}")
        await message.answer(f"❌ Ошибка при экспорте: {str(e)}")


@admin_router.message(Command("admin_help"))
async def admin_help_cmd(message: Message):
    """Show admin commands help menu."""
    await message.answer(
        "🔧 <b>Админские команды</b>\n\n"
        "Выбери команду для просмотра справки:",
        reply_markup=kb_admin_commands()
    )


@admin_router.callback_query(F.data == "admin:export_all")
async def admin_export_all_callback(cb: CallbackQuery):
    """Export all users when button is clicked."""
    await cb.answer("📊 Начинаю экспорт...")
    
    try:
        await cb.message.answer("📊 Формирую Excel файл...")
        
        # Export to Excel (all users, no filters)
        async with SessionLocal() as session:
            excel_file = await export_users_to_excel(
                session,
                city=None,
                massage_technique=None,
            )
        
        # Send file
        filename = "users_export.xlsx"
        file = BufferedInputFile(
            excel_file.read(),
            filename=filename
        )
        
        await cb.message.answer_document(
            file,
            caption="📊 Экспорт всех пользователей"
        )
        
        logger.info(f"User {cb.from_user.id} exported all users via button")
        
    except Exception as e:
        logger.exception(f"Error exporting users via button: {e}")
        await cb.message.answer(f"❌ Ошибка при экспорте: {str(e)}")


@admin_router.callback_query(F.data.startswith("admin_help:"))
async def admin_help_callback(cb: CallbackQuery):
    """Show help for specific admin command."""
    await cb.answer()
    
    command = cb.data.split(":", 1)[1] if ":" in cb.data else ""
    
    if command == "export_users":
        help_text = (
            "<b>📊 Справка по команде /export_users</b>\n\n"
            "<b>Описание:</b>\n"
            "Экспортирует список пользователей в Excel файл с фильтрацией по городу и технике массажа.\n\n"
            "<b>Использование:</b>\n"
            "<code>/export_users</code> - экспорт всех пользователей\n"
            "<code>/export_users Москва</code> - экспорт пользователей из Москвы\n"
            "<code>/export_users Москва classic</code> - экспорт пользователей из Москвы с классической техникой\n"
            "<code>/export_users \"\" \"sport massage\"</code> - экспорт всех пользователей со спортивным массажем\n\n"
            "<b>Доступные техники массажа:</b>\n"
        )
        
        techniques = "\n".join([f"• <code>{t.value}</code>" for t in MassageTechnique])
        help_text += techniques
        
        help_text += (
            "\n\n<b>Формат файла:</b>\n"
            "Excel файл содержит следующие колонки:\n"
            "• ID, Telegram ID, Имя, Пол, Город\n"
            "• Техника массажа, Место практики, Опыт с клиентами\n"
            "• Навыки в соцсетях, Удобство общения\n"
            "• Telegram Username, Telegram Link"
        )
    elif command == "send_to_users":
        help_text = (
            "<b>📢 Справка по команде /send_to_users</b>\n\n"
            "<b>Описание:</b>\n"
            "Отправляет сообщение всем пользователям бота, которые уже запускали бота.\n\n"
            "<b>Использование:</b>\n"
            "1. Отправь команду <code>/send_to_users</code>\n"
            "2. Отправь сообщение для рассылки (текст, аудио, голосовое или видеокружок)\n"
            "3. Сообщение будет отправлено всем пользователям\n\n"
            "<b>Поддерживаемые типы сообщений:</b>\n"
            "• Текст\n"
            "• Аудио (voice / audio)\n"
            "• Видеокружок (video note)\n\n"
            "<b>Важно:</b>\n"
            "• Рассылка может занять некоторое время\n"
            "• Ошибки при отправке отдельным пользователям не прерывают рассылку"
        )
    else:
        help_text = f"❌ Справка для команды '{command}' не найдена."
    
    await cb.message.answer(help_text, reply_markup=kb_admin_commands())


@admin_router.message(Command("send_to_users"))
async def send_to_users_cmd(message: Message, state: FSMContext):
    """Start broadcast flow - ask for message to send."""
    await state.set_state(BroadcastFSM.await_message)
    await message.answer(
        "📢 <b>Создание рассылки</b>\n\n"
        "Отправь сообщение для рассылки всем пользователям:\n"
        "• Текст\n"
        "• Аудио (voice / audio)\n"
        "• Видеокружок (video note)\n\n"
        "Для отмены отправь /cancel"
    )


@admin_router.callback_query(F.data == "admin:broadcast")
async def admin_broadcast_callback(cb: CallbackQuery, state: FSMContext):
    """Start broadcast flow from button."""
    await cb.answer()
    await state.set_state(BroadcastFSM.await_message)
    await cb.message.answer(
        "📢 <b>Создание рассылки</b>\n\n"
        "Отправь сообщение для рассылки всем пользователям:\n"
        "• Текст\n"
        "• Аудио (voice / audio)\n"
        "• Видеокружок (video note)\n\n"
        "Для отмены отправь /cancel"
    )


async def _broadcast_message(bot, tg_ids: list[str], message_to_forward: Message) -> tuple[int, int]:
    """
    Broadcast message to all users.
    Returns (success_count, fail_count).
    """
    success = 0
    failed = 0
    
    for tg_id in tg_ids:
        try:
            if message_to_forward.text:
                await bot.send_message(chat_id=tg_id, text=message_to_forward.text, parse_mode="HTML")
            elif message_to_forward.voice:
                await bot.send_voice(chat_id=tg_id, voice=message_to_forward.voice.file_id)
            elif message_to_forward.audio:
                await bot.send_audio(chat_id=tg_id, audio=message_to_forward.audio.file_id)
            elif message_to_forward.video_note:
                await bot.send_video_note(chat_id=tg_id, video_note=message_to_forward.video_note.file_id)
            else:
                failed += 1
                continue
            success += 1
        except Exception as e:
            logger.warning(f"Failed to send message to {tg_id}: {e}")
            failed += 1
    
    return success, failed


@admin_router.message(BroadcastFSM.await_message, F.text & ~F.text.startswith("/"))
async def broadcast_text_handler(message: Message, state: FSMContext):
    """Handle text message for broadcast."""
    await state.clear()
    
    # Get all user IDs
    async with SessionLocal() as session:
        tg_ids = await get_all_user_tg_ids(session)
    
    if not tg_ids:
        await message.answer("❌ Нет пользователей для рассылки.")
        return
    
    await message.answer(f"📢 Начинаю рассылку для {len(tg_ids)} пользователей...")
    
    # Broadcast message
    success, failed = await _broadcast_message(message.bot, tg_ids, message)
    
    await message.answer(
        f"✅ <b>Рассылка завершена</b>\n\n"
        f"Успешно: {success}\n"
        f"Ошибок: {failed}\n"
        f"Всего: {len(tg_ids)}"
    )
    
    logger.info(f"Admin {message.from_user.id} broadcasted message to {success} users ({failed} failed)")


@admin_router.message(BroadcastFSM.await_message, F.voice | F.audio)
async def broadcast_audio_handler(message: Message, state: FSMContext):
    """Handle audio/voice message for broadcast."""
    await state.clear()
    
    # Get all user IDs
    async with SessionLocal() as session:
        tg_ids = await get_all_user_tg_ids(session)
    
    if not tg_ids:
        await message.answer("❌ Нет пользователей для рассылки.")
        return
    
    await message.answer(f"📢 Начинаю рассылку для {len(tg_ids)} пользователей...")
    
    # Broadcast message
    success, failed = await _broadcast_message(message.bot, tg_ids, message)
    
    await message.answer(
        f"✅ <b>Рассылка завершена</b>\n\n"
        f"Успешно: {success}\n"
        f"Ошибок: {failed}\n"
        f"Всего: {len(tg_ids)}"
    )
    
    logger.info(f"Admin {message.from_user.id} broadcasted audio to {success} users ({failed} failed)")


@admin_router.message(BroadcastFSM.await_message, F.video_note)
async def broadcast_video_note_handler(message: Message, state: FSMContext):
    """Handle video note for broadcast."""
    await state.clear()
    
    # Get all user IDs
    async with SessionLocal() as session:
        tg_ids = await get_all_user_tg_ids(session)
    
    if not tg_ids:
        await message.answer("❌ Нет пользователей для рассылки.")
        return
    
    await message.answer(f"📢 Начинаю рассылку для {len(tg_ids)} пользователей...")
    
    # Broadcast message
    success, failed = await _broadcast_message(message.bot, tg_ids, message)
    
    await message.answer(
        f"✅ <b>Рассылка завершена</b>\n\n"
        f"Успешно: {success}\n"
        f"Ошибок: {failed}\n"
        f"Всего: {len(tg_ids)}"
    )
    
    logger.info(f"Admin {message.from_user.id} broadcasted video note to {success} users ({failed} failed)")


@admin_router.message(BroadcastFSM.await_message, F.text.startswith("/cancel"))
async def broadcast_cancel_handler(message: Message, state: FSMContext):
    """Cancel broadcast."""
    await state.clear()
    await message.answer("❌ Рассылка отменена.")


# Include admin router
router.include_router(admin_router)
