"""
Опросы и голосования
Только для администраторов
"""
import logging
import json
from datetime import datetime
from aiogram import Router, F
from aiogram.types import Message, CallbackQuery
from aiogram.filters import Command, StateFilter
from aiogram.fsm.state import State, StatesGroup
from aiogram.fsm.context import FSMContext
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from database.db import AsyncSessionLocal
from database.models import User, Poll
from utils.decorators import admin_only
from keyboards.inline import get_poll_keyboard, get_poll_results_keyboard, get_poll_close_keyboard
import config

logger = logging.getLogger(__name__)

router = Router()


# =============================================================================
# FSM для создания опроса
# =============================================================================

class PollCreateState(StatesGroup):
    waiting_for_question = State()
    waiting_for_options = State()


# =============================================================================
# СОЗДАНИЕ ОПРОСА
# =============================================================================

@router.message(Command('poll_create'))
@admin_only
async def cmd_poll_create(message: Message, state: FSMContext):
    """
    Создание опроса
    Использование: /poll_create "Вопрос" "Вариант 1" "Вариант 2" ...
    Или в режиме диалога
    """
    # Проверяем что это личка или чат
    if message.chat.type == 'private':
        await message.answer(
            '⚠️ <b>Опросы создаются только в чате!</b>\n\n'
            'Напишите команду в общем чате:\n'
            '<code>/poll_create "Вопрос" "Вариант 1" "Вариант 2"</code>',
            parse_mode='HTML'
        )
        return

    # Парсим аргументы
    args = message.text.split(maxsplit=1)
    if len(args) < 2:
        # Режим диалога
        await message.answer(
            '📊 <b>Создание опроса</b>\n\n'
            'Отправьте вопрос опроса (или используйте команду с аргументами):\n'
            '<code>/poll_create "За какой цвет покрасить подъезд?" "Бежевый" "Зелёный" "Серый"</code>',
            parse_mode='HTML'
        )
        await state.set_state(PollCreateState.waiting_for_question)
        return

    # Парсим вопрос и варианты
    text = args[1]
    await create_poll_from_text(message, text, state)


async def create_poll_from_text(message: Message, text: str, state: FSMContext):
    """Создать опрос из текста"""
    # Простая парсинг: разделяем по кавычкам или пробелам
    import shlex
    try:
        parts = shlex.split(text)
    except ValueError:
        parts = text.split('"')
        parts = [p.strip() for p in parts if p.strip()]

    if len(parts) < 3:
        await message.answer(
            '❌ <b>Ошибка!</b>\n\n'
            'Нужно минимум 3 части:\n'
            '1. Вопрос\n'
            '2. Вариант 1\n'
            '3. Вариант 2\n\n'
            'Пример:\n'
            '<code>/poll_create "За какой цвет?" "Бежевый" "Зелёный"</code>',
            parse_mode='HTML'
        )
        return

    question = parts[0]
    options = parts[1:]

    if len(options) > 10:
        options = options[:10]
        await message.answer('⚠️ Максимум 10 вариантов, лишние обрезаны')

    # Создаём опрос в БД
    async with AsyncSessionLocal() as session:
        poll = Poll(
            message_id=0,  # Заполним после отправки
            chat_id=message.chat.id,
            question=question,
            options=json.dumps(options, ensure_ascii=False),
            votes=json.dumps({str(i): [] for i in range(len(options))}, ensure_ascii=False),
            created_by=message.from_user.id,
        )
        session.add(poll)
        await session.commit()
        await session.refresh(poll)

    # Отправляем опрос с кнопками
    keyboard = get_poll_keyboard(poll.poll_id, options)
    
    poll_text = (
        f'📊 <b>ОПРОС</b>\n\n'
        f'{question}\n\n'
        f'Голосуйте кнопками ниже! 👇'
    )

    sent_message = await message.answer(poll_text, reply_markup=keyboard, parse_mode='HTML')

    # Обновляем message_id
    async with AsyncSessionLocal() as session:
        poll.message_id = sent_message.message_id
        await session.commit()

    await message.answer(
        f'✅ Опрос создан!\n\n'
        f'Вопрос: {question}\n'
        f'Вариантов: {len(options)}\n\n'
        f'Для закрытия: <code>/poll_end {poll.poll_id}</code>',
        parse_mode='HTML'
    )
    await state.clear()


@router.message(PollCreateState.waiting_for_question)
async def process_question(message: Message, state: FSMContext):
    """Получили вопрос опроса"""
    question = message.text
    await state.update_data(question=question)
    await state.set_state(PollCreateState.waiting_for_options)

    await message.answer(
        '📝 Теперь отправьте варианты ответов через запятую:\n\n'
        '<code>Вариант 1, Вариант 2, Вариант 3</code>\n\n'
        'Или отмените: /cancel',
        parse_mode='HTML'
    )


@router.message(PollCreateState.waiting_for_options)
async def process_options(message: Message, state: FSMContext):
    """Получили варианты опроса"""
    options_text = message.text
    options = [o.strip() for o in options_text.split(',')]

    if len(options) < 2:
        await message.answer(
            '❌ Нужно минимум 2 варианта!\n'
            'Отправьте ещё раз через запятую:'
        )
        return

    data = await state.get_data()
    question = data.get('question')

    await state.clear()
    await create_poll_from_text(message, f'"{question}" ' + ' '.join([f'"{o}"' for o in options]), state)


# =============================================================================
# ГОЛОСОВАНИЕ
# =============================================================================

@router.callback_query(F.data.startswith('poll_vote_'))
async def callback_poll_vote(callback: CallbackQuery):
    """Голосование за вариант"""
    # poll_vote_{poll_id}_{option_index}
    parts = callback.data.split('_')
    poll_id = int(parts[2])
    option_index = int(parts[3])
    user_id = callback.from_user.id

    async with AsyncSessionLocal() as session:
        # Получаем опрос
        stmt = select(Poll).where(Poll.poll_id == poll_id)
        result = await session.execute(stmt)
        poll = result.scalar_one_or_none()

        if not poll:
            await callback.answer('❌ Опрос не найден', show_alert=True)
            return

        if not poll.is_active:
            await callback.answer('⛔ Опрос уже закрыт', show_alert=True)
            return

        # Проверяем что пользователь верифицирован
        user_stmt = select(User).where(User.user_id == user_id)
        result = await session.execute(user_stmt)
        user = result.scalar_one_or_none()

        # Голосовать могут все (даже неверифицированные)
        # Но можно добавить проверку если нужно

        # Получаем текущие голоса
        votes_data = json.loads(poll.votes) if poll.votes else {}

        # Убираем старый голос этого пользователя если есть
        for key in votes_data:
            if str(user_id) in votes_data[key]:
                votes_data[key].remove(str(user_id))

        # Добавляем новый голос
        key = str(option_index)
        if key not in votes_data:
            votes_data[key] = []
        votes_data[key].append(str(user_id))

        # Сохраняем
        poll.votes = json.dumps(votes_data, ensure_ascii=False)
        await session.commit()

        # Получаем результаты
        results = poll.get_results()
        total = poll.total_votes

        # Формируем текст результатов
        results_text = '📊 <b>Результаты голосования</b>\n\n'
        for option, count, percent in results:
            bar = '█' * int(percent / 10)  # Визуальная шкала
            results_text += f'{bar} {option}: {count} ({percent}%)\n'

        results_text += f'\n👥 Всего голосов: {total}'

    await callback.answer(f'✅ Ваш голос учтён!', show_alert=False)
    
    # Отправляем результаты в чат (видимо только проголосовавшему)
    await callback.message.answer(
        results_text,
        parse_mode='HTML'
    )


# =============================================================================
# ПРОСМОТР РЕЗУЛЬТАТОВ
# =============================================================================

@router.callback_query(F.data.startswith('poll_results_'))
async def callback_poll_results(callback: CallbackQuery):
    """Показать результаты опроса"""
    parts = callback.data.split('_')
    poll_id = int(parts[2])

    async with AsyncSessionLocal() as session:
        stmt = select(Poll).where(Poll.poll_id == poll_id)
        result = await session.execute(stmt)
        poll = result.scalar_one_or_none()

        if not poll:
            await callback.answer('❌ Опрос не найден', show_alert=True)
            return

        results = poll.get_results()
        total = poll.total_votes
        status = '🔒 Закрыт' if not poll.is_active else '🟢 Активен'

        text = (
            f'📊 <b>Результаты опроса</b>\n\n'
            f'<b>Вопрос:</b> {poll.question}\n'
            f'<b>Статус:</b> {status}\n\n'
        )

        for option, count, percent in results:
            bar = '█' * int(percent / 10)
            text += f'{bar} {option}: {count} ({percent}%)\n'

        text += f'\n👥 Всего голосов: {total}'

    await callback.message.answer(text, parse_mode='HTML')
    await callback.answer()


# =============================================================================
# ЗАКРЫТИЕ ОПРОСА
# =============================================================================

@router.message(Command('poll_end'))
@admin_only
async def cmd_poll_end(message: Message):
    """
    Закрыть опрос
    Использование: /poll_end <poll_id>
    """
    args = message.text.split()
    if len(args) < 2:
        await message.answer(
            '❌ <b>Использование:</b>\n'
            '<code>/poll_end <номер_опроса></code>\n\n'
            'Номер опроса можно узнать из команды создания.',
            parse_mode='HTML'
        )
        return

    try:
        poll_id = int(args[1])
    except ValueError:
        await message.answer('❌ Неверный номер опроса')
        return

    async with AsyncSessionLocal() as session:
        stmt = select(Poll).where(Poll.poll_id == poll_id)
        result = await session.execute(stmt)
        poll = result.scalar_one_or_none()

        if not poll:
            await message.answer('❌ Опрос не найден')
            return

        if not poll.is_active:
            await message.answer('⛔ Опрос уже закрыт')
            return

        # Закрываем опрос
        poll.is_active = False
        poll.closed_at = datetime.utcnow()
        await session.commit()

        # Показываем финальные результаты
        results = poll.get_results()
        total = poll.total_votes

        text = (
            f'🔒 <b>ОПРОС ЗАКРЫТ</b>\n\n'
            f'<b>Вопрос:</b> {poll.question}\n\n'
        )

        for option, count, percent in results:
            bar = '█' * int(percent / 10)
            text += f'{bar} {option}: {count} ({percent}%)\n'

        text += f'\n👥 Всего голосов: {total}'

    await message.answer(text, parse_mode='HTML')


# =============================================================================
# СПИСОК ОПРОСОВ
# =============================================================================

@router.message(Command('polls'))
async def cmd_polls(message: Message):
    """Список активных опросов"""
    async with AsyncSessionLocal() as session:
        stmt = select(Poll).where(
            Poll.chat_id == message.chat.id,
            Poll.is_active == True
        ).order_by(Poll.created_at.desc())
        result = await session.execute(stmt)
        polls = list(result.scalars().all())

        if not polls:
            await message.answer('📊 Нет активных опросов')
            return

        text = '📊 <b>Активные опросы</b>\n\n'
        for poll in polls:
            total = poll.total_votes
            status = '🔒 Закрыт' if not poll.is_active else '🟢 Активен'
            text += f'{poll.poll_id}. {poll.question[:50]}... ({total} голосов) {status}\n'

        text += '\n💡 Для голосования нажмите на кнопку в сообщении с опросом'

    await message.answer(text, parse_mode='HTML')


# =============================================================================
# ОТМЕНА
# =============================================================================

@router.message(Command('cancel'))
async def cmd_cancel(message: Message, state: FSMContext):
    """Отмена текущего действия"""
    current_state = await state.get_state()
    if current_state:
        await state.clear()
        await message.answer('❌ Отменено')
    else:
        await message.answer('ℹ️ Нет активного действия для отмены')
