"""
bot/handlers/support.py
-----------------------
سیستم پشتیبانی کاربر به صورت تیکتی.
"""

from __future__ import annotations

from aiogram import F, Router
from aiogram.fsm.context import FSMContext
from aiogram.types import (
    CallbackQuery,
    InlineKeyboardButton,
    InlineKeyboardMarkup,
    Message,
)
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

import config

from bot.states.states import SupportStates
from database import crud
from database.models import (
    SenderRole,
    SupportTicket,
    SupportTicketStatus,
)


router = Router(name="support")


# ============================================================
# KEYBOARDS
# ============================================================

def support_keyboard() -> InlineKeyboardMarkup:
    return InlineKeyboardMarkup(
        inline_keyboard=[
            [
                InlineKeyboardButton(
                    text="🆕 ثبت درخواست پشتیبانی",
                    callback_data="support_new",
                )
            ],
            [
                InlineKeyboardButton(
                    text="📋 تیکت‌های من",
                    callback_data="support_my_tickets",
                )
            ],
            [
                InlineKeyboardButton(
                    text="🔙 بازگشت",
                    callback_data="support_back",
                )
            ],
        ]
    )


def cancel_support_keyboard() -> InlineKeyboardMarkup:
    return InlineKeyboardMarkup(
        inline_keyboard=[
            [
                InlineKeyboardButton(
                    text="❌ لغو",
                    callback_data="support_cancel",
                )
            ]
        ]
    )


def ticket_keyboard(
    ticket_id: int,
    is_open: bool,
) -> InlineKeyboardMarkup:

    buttons = []

    if is_open:
        buttons.append(
            [
                InlineKeyboardButton(
                    text="💬 ارسال پیام",
                    callback_data=f"support_reply:{ticket_id}",
                )
            ]
        )

    buttons.append(
        [
            InlineKeyboardButton(
                text="🔙 تیکت‌های من",
                callback_data="support_my_tickets",
            )
        ]
    )

    return InlineKeyboardMarkup(
        inline_keyboard=buttons
    )


# ============================================================
# SUPPORT MENU
# ============================================================

@router.callback_query(F.data == "support")
async def show_support_menu(
    callback: CallbackQuery,
    state: FSMContext,
):
    await state.clear()

    await callback.message.edit_text(
        "🎫 <b>پشتیبانی</b>\n\n"
        "اگر مشکلی داری یا سوالی برات پیش اومده، "
        "از طریق تیکت با پشتیبانی در ارتباط باش.\n\n"
        "پیامت رو ثبت کن تا ادمین بررسی کنه و پاسخ رو "
        "داخل همین ربات برات ارسال کنه.",
        reply_markup=support_keyboard(),
    )

    await callback.answer()


# ============================================================
# NEW TICKET
# ============================================================

@router.callback_query(F.data == "support_new")
async def new_support_ticket(
    callback: CallbackQuery,
    state: FSMContext,
    session: AsyncSession,
):
    await state.clear()

    user = await crud.get_user_by_telegram_id(
        session,
        callback.from_user.id,
    )

    if not user:
        await callback.answer(
            "ابتدا ربات را /start کنید.",
            show_alert=True,
        )
        return

    if user.is_blocked:
        await callback.answer(
            "حساب شما مسدود شده است.",
            show_alert=True,
        )
        return

    result = await session.execute(
        select(SupportTicket)
        .where(
            SupportTicket.user_id == user.id,
            SupportTicket.status
            == SupportTicketStatus.OPEN.value,
        )
        .order_by(
            SupportTicket.id.desc()
        )
    )

    existing_ticket = result.scalars().first()

    if existing_ticket:
        await callback.message.edit_text(
            "⚠️ <b>یک تیکت باز دارید.</b>\n\n"
            f"شماره تیکت: <code>#{existing_ticket.id}</code>\n\n"
            "برای جلوگیری از ایجاد تیکت‌های تکراری، "
            "از همین تیکت استفاده کن.",
            reply_markup=ticket_keyboard(
                existing_ticket.id,
                True,
            ),
        )

        await callback.answer()
        return

    await state.set_state(
        SupportStates.WAITING_FOR_MESSAGE
    )

    await callback.message.edit_text(
        "📝 <b>ثبت درخواست پشتیبانی</b>\n\n"
        "لطفاً مشکل یا سوال خودت رو در یک پیام کامل بنویس.\n\n"
        "در صورت نیاز می‌تونی عکس هم ارسال کنی.",
        reply_markup=cancel_support_keyboard(),
    )

    await callback.answer()


# ============================================================
# NOTIFY ADMINS
# ============================================================

async def notify_admins_new_ticket(
    message: Message,
    ticket: SupportTicket,
    user,
):
    username = (
        f"@{user.username}"
        if user.username
        else "بدون یوزرنیم"
    )

    full_name = (
        f"{user.first_name or ''} "
        f"{user.last_name or ''}"
    ).strip()

    if not full_name:
        full_name = "بدون نام"

    notification_text = (
        "🔔 <b>تیکت جدید پشتیبانی</b>\n\n"
        f"🎫 <b>تیکت:</b> <code>#{ticket.id}</code>\n"
        f"👤 <b>کاربر:</b> {full_name}\n"
        f"🔗 <b>یوزرنیم:</b> {username}\n"
        f"🆔 <b>Telegram ID:</b> <code>{user.telegram_id}</code>\n\n"
        "📩 یک درخواست پشتیبانی جدید ثبت شده است."
    )

    keyboard = InlineKeyboardMarkup(
        inline_keyboard=[
            [
                InlineKeyboardButton(
                    text="🎫 مشاهده تیکت",
                    callback_data=f"admin_support_ticket:{ticket.id}",
                )
            ]
        ]
    )

    for admin_id in config.ADMIN_IDS:
        try:
            await message.bot.send_message(
                chat_id=admin_id,
                text=notification_text,
                reply_markup=keyboard,
            )
        except Exception:
            # اگر یکی از ادمین‌ها ربات را بلاک کرده باشد،
            # ارسال برای بقیه ادمین‌ها ادامه پیدا می‌کند.
            continue


# ============================================================
# RECEIVE SUPPORT TEXT
# ============================================================

@router.message(
    SupportStates.WAITING_FOR_MESSAGE,
    F.text,
)
async def receive_support_text(
    message: Message,
    state: FSMContext,
    session: AsyncSession,
):
    user = await crud.get_user_by_telegram_id(
        session,
        message.from_user.id,
    )

    if not user:
        await state.clear()

        await message.answer(
            "❌ اطلاعات کاربری پیدا نشد.\n"
            "لطفاً /start را بزنید."
        )
        return

    if user.is_blocked:
        await state.clear()

        await message.answer(
            "🚫 حساب شما مسدود شده است."
        )
        return

    ticket = await crud.get_or_create_open_ticket(
        session,
        user.id,
    )

    support_message = await crud.add_support_message(
        session,
        ticket.id,
        SenderRole.USER.value,
        text=message.text,
    )

    if not support_message:
        await state.clear()

        await message.answer(
            "❌ ثبت پیام انجام نشد.\n"
            "لطفاً دوباره تلاش کنید."
        )
        return

    await notify_admins_new_ticket(
        message,
        ticket,
        user,
    )

    await state.clear()

    await message.answer(
        "✅ <b>درخواستت ثبت شد.</b>\n\n"
        f"🎫 شماره تیکت: <code>#{ticket.id}</code>\n\n"
        "پیامت برای پشتیبانی ارسال شد.\n"
        "بعد از بررسی، پاسخ ادمین داخل همین ربات برات ارسال میشه.",
        reply_markup=support_keyboard(),
    )


# ============================================================
# RECEIVE SUPPORT PHOTO
# ============================================================

@router.message(
    SupportStates.WAITING_FOR_MESSAGE,
    F.photo,
)
async def receive_support_photo(
    message: Message,
    state: FSMContext,
    session: AsyncSession,
):
    user = await crud.get_user_by_telegram_id(
        session,
        message.from_user.id,
    )

    if not user:
        await state.clear()

        await message.answer(
            "❌ اطلاعات کاربری پیدا نشد.\n"
            "لطفاً /start را بزنید."
        )
        return

    if user.is_blocked:
        await state.clear()

        await message.answer(
            "🚫 حساب شما مسدود شده است."
        )
        return

    ticket = await crud.get_or_create_open_ticket(
        session,
        user.id,
    )

    support_message = await crud.add_support_message(
        session,
        ticket.id,
        SenderRole.USER.value,
        text=message.caption,
        photo_file_id=message.photo[-1].file_id,
    )

    if not support_message:
        await state.clear()

        await message.answer(
            "❌ ثبت پیام انجام نشد.\n"
            "لطفاً دوباره تلاش کنید."
        )
        return

    await notify_admins_new_ticket(
        message,
        ticket,
        user,
    )

    await state.clear()

    await message.answer(
        "✅ <b>درخواستت ثبت شد.</b>\n\n"
        f"🎫 شماره تیکت: <code>#{ticket.id}</code>\n\n"
        "پیام و تصویر برای پشتیبانی ارسال شد.",
        reply_markup=support_keyboard(),
    )


# ============================================================
# CANCEL
# ============================================================

@router.callback_query(F.data == "support_cancel")
async def cancel_support(
    callback: CallbackQuery,
    state: FSMContext,
):
    await state.clear()

    await callback.message.edit_text(
        "🎫 <b>پشتیبانی</b>\n\n"
        "عملیات لغو شد.",
        reply_markup=support_keyboard(),
    )

    await callback.answer()


# ============================================================
# MY TICKETS
# ============================================================

@router.callback_query(F.data == "support_my_tickets")
async def my_support_tickets(
    callback: CallbackQuery,
    state: FSMContext,
    session: AsyncSession,
):
    await state.clear()

    user = await crud.get_user_by_telegram_id(
        session,
        callback.from_user.id,
    )

    if not user:
        await callback.answer(
            "کاربر پیدا نشد.",
            show_alert=True,
        )
        return

    result = await session.execute(
        select(SupportTicket)
        .where(
            SupportTicket.user_id == user.id
        )
        .order_by(
            SupportTicket.id.desc()
        )
    )

    tickets = list(
        result.scalars().all()
    )

    if not tickets:
        await callback.message.edit_text(
            "📋 <b>تیکت‌های من</b>\n\n"
            "هنوز هیچ تیکتی ثبت نکرده‌ای.",
            reply_markup=support_keyboard(),
        )

        await callback.answer()
        return

    buttons = []

    for ticket in tickets[:20]:

        if ticket.status == SupportTicketStatus.OPEN.value:
            status = "🟢 باز"
        else:
            status = "⚪ بسته"

        buttons.append(
            [
                InlineKeyboardButton(
                    text=f"#{ticket.id} — {status}",
                    callback_data=f"support_ticket:{ticket.id}",
                )
            ]
        )

    buttons.append(
        [
            InlineKeyboardButton(
                text="🔙 بازگشت",
                callback_data="support",
            )
        ]
    )

    await callback.message.edit_text(
        "📋 <b>تیکت‌های من</b>\n\n"
        "تیکت موردنظر را انتخاب کن:",
        reply_markup=InlineKeyboardMarkup(
            inline_keyboard=buttons
        ),
    )

    await callback.answer()


# ============================================================
# SHOW TICKET
# ============================================================

@router.callback_query(
    F.data.startswith("support_ticket:")
)
async def show_ticket(
    callback: CallbackQuery,
    state: FSMContext,
    session: AsyncSession,
):
    await state.clear()

    try:
        ticket_id = int(
            callback.data.split(":", 1)[1]
        )
    except (ValueError, IndexError):
        await callback.answer(
            "تیکت نامعتبر است.",
            show_alert=True,
        )
        return

    result = await session.execute(
        select(SupportTicket)
        .where(
            SupportTicket.id == ticket_id
        )
    )

    ticket = result.scalar_one_or_none()

    if not ticket:
        await callback.answer(
            "تیکت پیدا نشد.",
            show_alert=True,
        )
        return

    user = await crud.get_user_by_telegram_id(
        session,
        callback.from_user.id,
    )

    if not user or ticket.user_id != user.id:
        await callback.answer(
            "این تیکت متعلق به شما نیست.",
            show_alert=True,
        )
        return

    result = await session.execute(
        select(
            SupportTicket
        )
        .where(
            SupportTicket.id == ticket_id
        )
        .options()
    )

    ticket = result.scalar_one_or_none()

    result = await session.execute(
        select(
            SupportTicket
        )
        .where(
            SupportTicket.id == ticket_id
        )
    )

    ticket = result.scalar_one_or_none()

    # گرفتن پیام‌ها به صورت جداگانه برای جلوگیری از مشکل lazy loading
    result = await session.execute(
        select(
            crud.SupportMessage
        )
    ) if False else None

    # از تابع CRUD برای گرفتن کامل تیکت استفاده می‌کنیم.
    ticket = await crud.get_ticket(
        session,
        ticket_id,
    )

    if not ticket:
        await callback.answer(
            "تیکت پیدا نشد.",
            show_alert=True,
        )
        return

    if ticket.user_id != user.id:
        await callback.answer(
            "این تیکت متعلق به شما نیست.",
            show_alert=True,
        )
        return

    if ticket.status == SupportTicketStatus.OPEN.value:
        status_text = "🟢 باز"
    else:
        status_text = "⚪ بسته"

    text = (
        "🎫 <b>تیکت پشتیبانی</b>\n\n"
        f"شماره: <code>#{ticket.id}</code>\n"
        f"وضعیت: {status_text}\n\n"
        "━━━━━━━━━━━━━━\n"
        "💬 <b>پیام‌ها</b>\n"
    )

    if not ticket.messages:
        text += "\nهنوز پیامی ثبت نشده."
    else:
        for item in ticket.messages[-10:]:

            if item.sender_role == SenderRole.USER.value:
                sender = "👤 شما"
            else:
                sender = "🛠 پشتیبانی"

            if item.text:
                text += (
                    f"\n<b>{sender}:</b>\n"
                    f"{item.text}\n"
                )

            if item.photo_file_id:
                text += "📷 تصویر ارسال شده\n"

            text += "────────────\n"

    await callback.message.edit_text(
        text,
        reply_markup=ticket_keyboard(
            ticket.id,
            ticket.status
            == SupportTicketStatus.OPEN.value,
        ),
    )

    await callback.answer()


# ============================================================
# REPLY TO EXISTING TICKET
# ============================================================

@router.callback_query(
    F.data.startswith("support_reply:")
)
async def reply_to_ticket(
    callback: CallbackQuery,
    state: FSMContext,
    session: AsyncSession,
):
    try:
        ticket_id = int(
            callback.data.split(":", 1)[1]
        )
    except (ValueError, IndexError):
        await callback.answer(
            "تیکت نامعتبر است.",
            show_alert=True,
        )
        return

    ticket = await crud.get_ticket(
        session,
        ticket_id,
    )

    if not ticket:
        await callback.answer(
            "تیکت پیدا نشد.",
            show_alert=True,
        )
        return

    user = await crud.get_user_by_telegram_id(
        session,
        callback.from_user.id,
    )

    if not user or ticket.user_id != user.id:
        await callback.answer(
            "این تیکت متعلق به شما نیست.",
            show_alert=True,
        )
        return

    if ticket.status != SupportTicketStatus.OPEN.value:
        await callback.answer(
            "این تیکت بسته شده است.",
            show_alert=True,
        )
        return

    await state.update_data(
        support_ticket_id=ticket.id
    )

    await state.set_state(
        SupportStates.WAITING_FOR_MESSAGE
    )

    await callback.message.edit_text(
        f"💬 <b>پاسخ به تیکت #{ticket.id}</b>\n\n"
        "پیام جدیدت رو ارسال کن.",
        reply_markup=cancel_support_keyboard(),
    )

    await callback.answer()


# ============================================================
# BACK
# ============================================================

@router.callback_query(F.data == "support_back")
async def support_back(
    callback: CallbackQuery,
    state: FSMContext,
):
    await state.clear()

    await callback.message.delete()

    await callback.answer()