"""
Расписание отключений — вода, свет, отопление
Только для администраторов
"""
import logging
from datetime import datetime, timedelta
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 Schedule, User
from utils.decorators import admin_only
from keyboards.inline import get_schedule_menu, get_schedule_item_menu
import config

logger = logging.getLogger(__name__)

router = Router()


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

class ScheduleState(StatesGroup):
    waiting_for_type = State()
    waiting_for_title = State()
    waiting_for_start = State()
    waiting_for_end = State()
    waiting_for_description = State()


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

@router.message(Command('schedule_add'))
@admin_only
async def cmd_schedule_add(message: Message, state: FSMContext):
    """
    Добавить событие в расписание
    Использование: /schedule_add
    """
    await message.answer(
        '📅 <b>Добавление события в расписание</b>\n\n'
        'Выберите тип отключения:\n\n'
        '1️⃣ 💧 Вода\n'
        '2️⃣ ⚡ Электричество\n'
        '3️⃣ 🔥 Отопление\n'
        '4️⃣ 🔶 Газ\n'
        '5️⃣ 🛗 Лифт\n'
        '6️⃣ 📋 Общее\n\n'
        'Или отправьте номер типа (1-6):',
        reply_markup=get_schedule_menu(),
        parse_mode='HTML'
    )
    await state.set_state(ScheduleState.waiting_for_type)


@router.callback_query(F.data.startswith('schedule_type_'))
async def callback_schedule_type(callback: CallbackQuery, state: FSMContext):
    """Выбор типа отключения"""
    type_map = {
        'schedule_type_water': ('water', '💧 Вода'),
        'schedule_type_electricity': ('electricity', '⚡ Электричество'),
        'schedule_type_heating': ('heating', '🔥 Отопление'),
        'schedule_type_gas': ('gas', '🔶 Газ'),
        'schedule_type_elevator': ('elevator', '🛗 Лифт'),
        'schedule_type_general': ('general', '📋 Общее'),
    }
    
    type_key, type_name = type_map.get(callback.data, ('general', '📋 Общее'))
    await state.update_data(schedule_type=type_key, type_name=type_name)
    
    await callback.message.answer(
        f'✅ Тип: {type_name}\n\n'
        'Теперь отправьте название события:\n'
        '<i>Например: "Плановое отключение воды"</i>',
        parse_mode='HTML'
    )
    await state.set_state(ScheduleState.waiting_for_title)
    await callback.answer()


@router.message(ScheduleState.waiting_for_type)
async def process_schedule_type(message: Message, state: FSMContext):
    """Выбор типа отключения текстом"""
    type_map = {
        '1': ('water', '💧 Вода'),
        '2': ('electricity', '⚡ Электричество'),
        '3': ('heating', '🔥 Отопление'),
        '4': ('gas', '🔶 Газ'),
        '5': ('elevator', '🛗 Лифт'),
        '6': ('general', '📋 Общее'),
    }
    
    text = message.text.strip()
    if text in type_map:
        type_key, type_name = type_map[text]
        await state.update_data(schedule_type=type_key, type_name=type_name)
        
        await message.answer(
            f'✅ Тип: {type_name}\n\n'
            'Теперь отправьте название события:\n'
            '<i>Например: "Плановое отключение воды"</i>',
            parse_mode='HTML'
        )
        await state.set_state(ScheduleState.waiting_for_title)
    else:
        await message.answer('❌ Неверный тип. Выберите из меню или отправьте номер 1-6:')


@router.message(ScheduleState.waiting_for_title)
async def process_schedule_title(message: Message, state: FSMContext):
    """Получили название события"""
    title = message.text
    await state.update_data(title=title)
    
    await message.answer(
        f'✅ Название: {title}\n\n'
        'Теперь отправьте дату и время НАЧАЛА в формате:\n'
        '<code>ДД.ММ.ГГГГ ЧЧ:ММ</code>\n\n'
        '<i>Например: 27.02.2026 10:00</i>',
        parse_mode='HTML'
    )


@router.message(ScheduleState.waiting_for_start)
async def process_schedule_start(message: Message, state: FSMContext):
    """Получили время начала"""
    text = message.text.strip()
    
    try:
        start_time = datetime.strptime(text, '%d.%m.%Y %H:%M')
    except ValueError:
        await message.answer(
            '❌ Неверный формат даты.\n'
            'Используйте: <code>ДД.ММ.ГГГГ ЧЧ:ММ</code>\n\n'
            '<i>Например: 27.02.2026 10:00</i>',
            parse_mode='HTML'
        )
        return
    
    if start_time < datetime.utcnow():
        await message.answer('❌ Время начала должно быть в будущем!')
        return
    
    await state.update_data(start_time=start_time)
    
    await message.answer(
        f'✅ Начало: {start_time.strftime("%d.%m.%Y %H:%M")}\n\n'
        'Теперь отправьте дату и время ОКОНЧАНИЯ:\n'
        '<code>ДД.ММ.ГГГГ ЧЧ:ММ</code>',
        parse_mode='HTML'
    )
    await state.set_state(ScheduleState.waiting_for_end)


@router.message(ScheduleState.waiting_for_end)
async def process_schedule_end(message: Message, state: FSMContext):
    """Получили время окончания"""
    text = message.text.strip()
    
    try:
        end_time = datetime.strptime(text, '%d.%m.%Y %H:%M')
    except ValueError:
        await message.answer(
            '❌ Неверный формат даты.\n'
            'Используйте: <code>ДД.ММ.ГГГГ ЧЧ:ММ</code>',
            parse_mode='HTML'
        )
        return
    
    data = await state.get_data()
    start_time = data.get('start_time')
    
    if end_time <= start_time:
        await message.answer('❌ Время окончания должно быть позже времени начала!')
        return
    
    await state.update_data(end_time=end_time)
    
    await message.answer(
        f'✅ Окончание: {end_time.strftime("%d.%m.%Y %H:%M")}\n\n'
        'Отправьте описание (необязательно) или нажмите "Пропустить":',
        reply_markup=get_schedule_item_menu(skip=True),
        parse_mode='HTML'
    )
    await state.set_state(ScheduleState.waiting_for_description)


@router.message(ScheduleState.waiting_for_description)
async def process_schedule_description(message: Message, state: FSMContext):
    """Получили описание или пропустили"""
    if message.text and message.text.lower() != 'пропустить':
        description = message.text
    else:
        description = None
    
    await state.update_data(description=description)
    
    # Сохраняем событие в БД
    data = await state.get_data()
    
    async with AsyncSessionLocal() as session:
        schedule = Schedule(
            schedule_type=data['schedule_type'],
            title=data['title'],
            description=description,
            start_time=data['start_time'],
            end_time=data['end_time'],
            created_by=message.from_user.id,
        )
        session.add(schedule)
        await session.commit()
        await session.refresh(schedule)
    
    # Формируем сообщение о создании
    type_name = data.get('type_name', '📋 Общее')
    duration = (data['end_time'] - data['start_time']).total_seconds() / 3600
    
    await message.answer(
        f'✅ <b>Событие добавлено в расписание!</b>\n\n'
        f'{type_name} — {data["title"]}\n\n'
        f'📅 Начало: {data["start_time"].strftime("%d.%m.%Y %H:%M")}\n'
        f'📅 Окончание: {data["end_time"].strftime("%d.%m.%Y %H:%M")}\n'
        f'⏱️ Длительность: {duration:.1f} ч.\n'
        f'🔖 ID: {schedule.schedule_id}\n\n'
        f'Для просмотра: /график',
        parse_mode='HTML'
    )
    await state.clear()


# =============================================================================
# ПРОСМОТР РАСПИСАНИЯ
# =============================================================================

@router.message(Command('график'))
@router.message(Command('schedule'))
async def cmd_schedule(message: Message):
    """Показать расписание отключений"""
    async with AsyncSessionLocal() as session:
        # Получаем активные будущие события
        stmt = (
            select(Schedule)
            .where(Schedule.is_active == True)
            .where(Schedule.end_time > datetime.utcnow())
            .order_by(Schedule.start_time)
            .limit(10)
        )
        result = await session.execute(stmt)
        schedules = list(result.scalars().all())

    if not schedules:
        await message.answer('✅ Нет запланированных отключений')
        return

    text = '📅 <b>Расписание отключений</b>\n\n'
    
    for i, s in enumerate(schedules, 1):
        emoji = s.get_type_emoji()
        type_name = {
            'water': 'Вода',
            'electricity': 'Электричество',
            'heating': 'Отопление',
            'gas': 'Газ',
            'elevator': 'Лифт',
            'general': 'Общее'
        }.get(s.schedule_type, 'Общее')
        
        duration = (s.end_time - s.start_time).total_seconds() / 3600
        
        text += f'{i}. {emoji} <b>{s.title}</b>\n'
        text += f'   └─ Тип: {type_name}\n'
        text += f'   └─ Начало: {s.start_time.strftime("%d.%m.%Y %H:%M")}\n'
        text += f'   └─ Окончание: {s.end_time.strftime("%d.%m.%Y %H:%M")}\n'
        text += f'   └─ Длительность: {duration:.1f} ч.\n'
        
        if s.description:
            text += f'   └─ Описание: {s.description[:100]}\n'
        
        text += '\n'

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


# =============================================================================
# УДАЛЕНИЕ СОБЫТИЯ
# =============================================================================

@router.message(Command('schedule_del'))
@admin_only
async def cmd_schedule_del(message: Message):
    """
    Удалить событие из расписания
    Использование: /schedule_del <ID>
    """
    args = message.text.split()
    if len(args) < 2:
        await message.answer(
            '❌ <b>Использование:</b>\n'
            '<code>/schedule_del &lt;ID&gt;</code>\n\n'
            'ID можно узнать из /график',
            parse_mode='HTML'
        )
        return

    try:
        schedule_id = int(args[1])
    except ValueError:
        await message.answer('❌ Неверный ID')
        return

    async with AsyncSessionLocal() as session:
        schedule = await session.get(Schedule, schedule_id)
        
        if not schedule:
            await message.answer(f'❌ Событие {schedule_id} не найдено')
            return
        
        schedule.is_active = False
        await session.commit()
        
        await message.answer(f'✅ Событие "{schedule.title}" удалено из расписания')


# =============================================================================
# НАПОМИНАНИЯ
# =============================================================================

async def check_and_send_reminders(bot):
    """Проверить и отправить напоминания о предстоящих отключениях"""
    async with AsyncSessionLocal() as session:
        # Находим события которые начнутся через 1 час
        stmt = (
            select(Schedule)
            .where(Schedule.is_active == True)
            .where(Schedule.reminder_sent == False)
            .where(Schedule.start_time > datetime.utcnow())
            .where(Schedule.start_time <= datetime.utcnow() + timedelta(hours=1))
        )
        result = await session.execute(stmt)
        schedules = list(result.scalars().all())
        
        for schedule in schedules:
            # Отправляем напоминание в чат в тему "Важные объявления"
            try:
                emoji = schedule.get_type_emoji()
                duration = (schedule.end_time - schedule.start_time).total_seconds() / 3600

                await bot.send_message(
                    chat_id=config.ADMIN_CHAT_ID,
                    message_thread_id=config.get_topic_id('general'),  # В общую тему
                    text=f'⏰ <b>Напоминание: отключение через 1 час!</b>\n\n'
                    f'{emoji} <b>{schedule.title}</b>\n\n'
                    f'📅 Начало: {schedule.start_time.strftime("%d.%m.%Y %H:%M")}\n'
                    f'📅 Окончание: {schedule.end_time.strftime("%d.%m.%Y %H:%M")}\n'
                    f'⏱️ Длительность: {duration:.1f} ч.\n\n'
                    f'Не забудьте сделать запасы!',
                    parse_mode='HTML'
                )

                # Помечаем что напоминание отправлено
                schedule.reminder_sent = True
                await session.commit()

                logger.info(f'Напоминание об отключении "{schedule.title}" отправлено')

            except Exception as e:
                logger.error(f'Не удалось отправить напоминание: {e}')
