"""
bot/handlers/admin/config.py
----------------------------
مدیریت ارسال کانفیگ و لینک Subscription توسط ادمین
"""

from __future__ import annotations

import html
import logging

from aiogram import F, Router
from aiogram.fsm.context import FSMContext
from aiogram.types import (
    CallbackQuery,
    InlineKeyboardButton,
    InlineKeyboardMarkup,
    Message,
)

import config

from database import crud
from database.database import get_session
from database.models import OrderStatus

from bot.states.states import (
    AdminConfigStates,
    AdminTestConfigStates,
)

router = Router(name="admin_config")

logger = logging.getLogger(__name__)


# ============================================================
# ADMIN CHECK
# ============================================================

def is_admin_user(
    user_id: int,
) -> bool:

    return config.is_admin(
        user_id
    )


# ============================================================
# START CONFIG DELIVERY
# ============================================================

async def start_config_delivery(
    message: Message,
    state: FSMContext,
    order_id: int,
    admin_id: int,
) -> bool:

    if not is_admin_user(admin_id):

        return False

    async with get_session() as session:

        order = await crud.get_order(
            session,
            order_id,
        )

        if not order:

            return False

        if order.status != OrderStatus.PAID.value:

            return False

    await state.update_data(
        config_order_id=order_id
    )

    await state.set_state(
        AdminConfigStates.WAITING_FOR_CONFIG
    )

    try:

        await message.answer(
            "🔐 <b>ارسال کانفیگ</b>\n\n"
            f"🧾 سفارش: <code>#{order_id}</code>\n\n"
            "کانفیگ این سرویس را ارسال کن."
        )

    except Exception:

        logger.exception(
            "Could not send config request | order_id=%s",
            order_id,
        )

        await state.clear()

        return False

    return True


# ============================================================
# RECEIVE CONFIG
# ============================================================

@router.message(
    AdminConfigStates.WAITING_FOR_CONFIG,
    F.text,
)
async def receive_config(
    message: Message,
    state: FSMContext,
):

    if not is_admin_user(
        message.from_user.id
    ):

        return

    data = await state.get_data()

    order_id = data.get(
        "config_order_id"
    )

    if not order_id:

        await state.clear()

        await message.answer(
            "❌ سفارش مربوط به این مرحله پیدا نشد."
        )

        return

    config_text = (
        message.text.strip()
    )

    if not config_text:

        await message.answer(
            "⚠️ کانفیگ نمی‌تواند خالی باشد."
        )

        return

    async with get_session() as session:

        order = await crud.get_order(
            session,
            order_id,
        )

        if not order:

            await state.clear()

            await message.answer(
                "❌ سفارش پیدا نشد."
            )

            return

        if order.status != OrderStatus.PAID.value:

            await state.clear()

            await message.answer(
                "⚠️ وضعیت این سفارش برای دریافت کانفیگ مناسب نیست."
            )

            return

        await crud.set_order_config(
            session=session,
            order_id=order_id,
            config_text=config_text,
        )

    await state.update_data(
        config_text=config_text
    )

    await state.set_state(
        AdminConfigStates.WAITING_FOR_SUBSCRIPTION
    )

    await message.answer(
        "🔗 <b>ارسال لینک Subscription</b>\n\n"
        f"🧾 سفارش: <code>#{order_id}</code>\n\n"
        "حالا لینک Subscription این سرویس را ارسال کن.\n\n"
        "مثال:\n"
        "<code>https://example.com/sub/xxxxx</code>"
    )


# ============================================================
# RECEIVE SUBSCRIPTION
# ============================================================

@router.message(
    AdminConfigStates.WAITING_FOR_SUBSCRIPTION,
    F.text,
)
async def receive_subscription(
    message: Message,
    state: FSMContext,
):

    if not is_admin_user(
        message.from_user.id
    ):

        return

    subscription_text = (
        message.text.strip()
    )

    if not subscription_text:

        await message.answer(
            "⚠️ لینک Subscription نمی‌تواند خالی باشد."
        )

        return

    data = await state.get_data()

    order_id = data.get(
        "config_order_id"
    )

    if not order_id:

        await state.clear()

        await message.answer(
            "❌ سفارش مربوط به این مرحله پیدا نشد."
        )

        return

    async with get_session() as session:

        # ====================================================
        # ORDER
        # ====================================================

        order = await crud.get_order(
            session,
            order_id,
        )

        if not order:

            await state.clear()

            await message.answer(
                "❌ سفارش پیدا نشد."
            )

            return

        # ====================================================
        # STATUS
        # ====================================================

        if order.status != OrderStatus.WAITING_SUBSCRIPTION.value:

            await state.clear()

            await message.answer(
                "⚠️ این سفارش در مرحله دریافت Subscription نیست."
            )

            return

        # ====================================================
        # SAVE SUBSCRIPTION TO ORDER
        # ====================================================

        await crud.set_order_subscription(
            session=session,
            order_id=order_id,
            subscription_text=subscription_text,
        )

        # ====================================================
        # ORDER DATA
        # ====================================================

        user_id = order.user_id
        plan_id = order.plan_id

        duration_days = (
            order.plan.duration_days
            if order.plan
            else 30
        )

        config_text = (
            order.config_text
            or ""
        )

        service_name = (
            order.service_name
            or f"سرویس #{order.id}"
        )

        order_type = (
            order.order_type
            or "new"
        )

        # ====================================================
        # NEW PURCHASE
        # ====================================================

        if order_type == "new":

            subscription = (
                await crud.create_subscription(
                    session=session,
                    user_id=user_id,
                    plan_id=plan_id,
                    duration_days=duration_days,
                    config_text=config_text,
                    service_name=service_name,
                    subscription_text=subscription_text,
                )
            )

            # ------------------------------------------------
            # اتصال Order به Subscription
            # ------------------------------------------------

            await crud.set_order_subscription_id(
                session=session,
                order_id=order_id,
                subscription_id=subscription.id,
            )

            # ------------------------------------------------
            # اطلاعات برای پیام
            # ------------------------------------------------

            subscription_id = (
                subscription.id
            )

        # ====================================================
        # RENEWAL
        # ====================================================

        else:

            if not order.subscription_id:

                await state.clear()

                await message.answer(
                    "❌ این سفارش تمدید است اما سرویس قبلی مشخص نیست."
                )

                return

            subscription = (
                await crud.extend_subscription(
                    session=session,
                    subscription_id=order.subscription_id,
                    duration_days=duration_days,
                    new_config_text=config_text,
                    new_subscription_text=subscription_text,
                )
            )

            if not subscription:

                await state.clear()

                await message.answer(
                    "❌ سرویس قبلی برای تمدید پیدا نشد."
                )

                return

            subscription_id = (
                subscription.id
            )

        # ====================================================
        # FINISH ORDER
        # ====================================================

        order.status = (
            OrderStatus.COMPLETED.value
        )

        await session.commit()

        # ====================================================
        # PLAN INFO
        # ====================================================

        plan_name = (
            order.plan.name
            if order.plan
            else "نامشخص"
        )

        volume = (
            order.plan.volume_gb
            if order.plan
            else 0
        )

        user_telegram_id = (
            order.user.telegram_id
            if order.user
            else None
        )

    # ========================================================
    # CLEAR ADMIN STATE
    # ========================================================

    await state.clear()

    # ========================================================
    # ADMIN SUCCESS MESSAGE
    # ========================================================

    await message.answer(
        "✅ <b>سرویس با موفقیت ثبت شد.</b>\n\n"

        f"🧾 سفارش: "
        f"<code>#{order_id}</code>\n"

        f"📦 پلن: "
        f"{html.escape(str(plan_name))}\n"

        f"🏷 نام سرویس: "
        f"{html.escape(str(service_name))}\n"

        f"🆔 شناسه سرویس: "
        f"<code>{subscription_id}</code>\n\n"

        "🔐 کانفیگ ذخیره شد.\n"
        "🔗 لینک Subscription ذخیره شد."
    )

    # ========================================================
    # USER MESSAGE
    # ========================================================

    if user_telegram_id:

        try:

            await message.bot.send_message(
                chat_id=user_telegram_id,
                text=(
                    "🎉 <b>سرویس شما آماده شد!</b>\n\n"

                    f"🏷 <b>نام سرویس:</b> "
                    f"{html.escape(str(service_name))}\n\n"

                    f"📦 <b>پلن:</b> "
                    f"{html.escape(str(plan_name))}\n"

                    f"💾 <b>حجم:</b> "
                    f"{volume} گیگ\n\n"

                    f"🔐 <b>کانفیگ:</b>\n"
                    f"<pre>{html.escape(str(config_text))}</pre>\n\n"

                    f"🔗 <b>لینک Subscription:</b>\n"
                    f"<code>{html.escape(str(subscription_text))}</code>\n\n"

                    "📦 برای مشاهده دوباره اطلاعات سرویس، "
                    "از بخش «سرویس‌های من» وارد سرویس شو."
                ),
            )

        except Exception:

            logger.exception(
                "Could not notify user | order_id=%s",
                order_id,
            )

    logger.info(
        "Subscription completed | "
        "order_id=%s | "
        "subscription_id=%s | "
        "user=%s",
        order_id,
        subscription_id,
        user_telegram_id,
    )
# ============================================================
# TEST CONFIG POOL
# ============================================================

from html import escape

from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup

from bot.states.states import AdminTestConfigStates


TEST_CONFIG_FINISH_CALLBACK = (
    "admin_test_config_finish"
)

TEST_CONFIG_STOCK_CALLBACK = (
    "admin_test_config_stock"
)

TEST_CONFIG_LIST_CALLBACK = (
    "admin_test_config_list"
)

TEST_CONFIG_DELETE_PREFIX = (
    "admin_test_config_delete_"
)

TEST_CONFIG_DELETE_CONFIRM_PREFIX = (
    "admin_test_config_delete_confirm_"
)

TEST_CONFIG_DELETE_CANCEL_PREFIX = (
    "admin_test_config_delete_cancel_"
)


def test_config_finish_keyboard() -> InlineKeyboardMarkup:

    return InlineKeyboardMarkup(
        inline_keyboard=[
            [
                InlineKeyboardButton(
                    text="✅ همینقدر خوبه",
                    callback_data=TEST_CONFIG_FINISH_CALLBACK,
                )
            ]
        ]
    )


# ============================================================
# START TEST CONFIG MANAGEMENT
# ============================================================

@router.message(
    F.text == "/testconfigs"
)
async def start_test_config_management(
    message: Message,
    state: FSMContext,
):

    if not is_admin_user(
        message.from_user.id
    ):
        return

    await state.clear()

    async with get_session() as session:

        available_count = (
            await crud.get_available_test_config_count(
                session
            )
        )

    await state.update_data(
        test_config_count=0
    )

    await state.set_state(
        AdminTestConfigStates.WAITING_FOR_TEST_CONFIG
    )

    await message.answer(
        "🧪 <b>مدیریت اکانت تست</b>\n\n"
        f"📦 موجودی فعلی: <b>{available_count}</b> کانفیگ\n\n"
        "حالا کانفیگ‌های تست را یکی‌یکی ارسال کن.\n\n"
        "مثلاً با ارسال اولین کانفیگ:\n"
        "🧪 کانفیگ تست اول\n\n"
        "بعد از هر کانفیگ، کانفیگ بعدی را بفرست.\n"
        "هر وقت تمام شد، روی دکمه «همینقدر خوبه» بزن."
    )


# ============================================================
# RECEIVE TEST CONFIG
# ============================================================

@router.message(
    AdminTestConfigStates.WAITING_FOR_TEST_CONFIG,
    F.text,
)
async def receive_test_config(
    message: Message,
    state: FSMContext,
):

    if not is_admin_user(
        message.from_user.id
    ):
        return

    config_text = message.text.strip()

    if not config_text:
        await message.answer(
            "⚠️ کانفیگ نمی‌تواند خالی باشد."
        )
        return

    data = await state.get_data()

    current_count = int(
        data.get(
            "test_config_count",
            0,
        )
    )

    async with get_session() as session:

        await crud.add_test_config(
            session=session,
            config_text=config_text,
        )

        available_count = (
            await crud.get_available_test_config_count(
                session
            )
        )

    current_count += 1

    await state.update_data(
        test_config_count=current_count
    )

    await message.answer(
        "✅ <b>کانفیگ تست ذخیره شد.</b>\n\n"
        f"🧪 این کانفیگ: <b>{current_count}</b>\n"
        f"📦 موجودی کل تست: <b>{available_count}</b>\n\n"
        "کانفیگ بعدی را ارسال کن یا اگر تمام شد، "
        "روی «همینقدر خوبه» بزن.",
        reply_markup=test_config_finish_keyboard(),
    )


# ============================================================
# FINISH TEST CONFIG MANAGEMENT
# ============================================================

@router.callback_query(
    F.data == TEST_CONFIG_FINISH_CALLBACK
)
async def finish_test_config_management(
    callback: CallbackQuery,
    state: FSMContext,
):

    if not is_admin_user(
        callback.from_user.id
    ):
        await callback.answer(
            "⛔ دسترسی ندارید.",
            show_alert=True,
        )
        return

    data = await state.get_data()

    added_count = int(
        data.get(
            "test_config_count",
            0,
        )
    )

    async with get_session() as session:

        available_count = (
            await crud.get_available_test_config_count(
                session
            )
        )

    await state.clear()

    await callback.message.edit_text(
        "✅ <b>مدیریت اکانت تست به پایان رسید.</b>\n\n"
        f"➕ کانفیگ اضافه‌شده در این مرحله: <b>{added_count}</b>\n"
        f"📦 موجودی قابل استفاده: <b>{available_count}</b>"
    )

    await callback.answer()


# ============================================================
# TEST STOCK
# ============================================================

def test_stock_keyboard() -> InlineKeyboardMarkup:

    return InlineKeyboardMarkup(
        inline_keyboard=[
            [
                InlineKeyboardButton(
                    text="🧪 مشاهده کانفیگ‌های آزاد",
                    callback_data=TEST_CONFIG_LIST_CALLBACK,
                )
            ]
        ]
    )


@router.message(
    F.text == "/teststock"
)
async def test_stock(
    message: Message,
):

    if not is_admin_user(
        message.from_user.id
    ):
        return

    async with get_session() as session:

        available_count = (
            await crud.get_available_test_config_count(
                session
            )
        )

        all_configs = (
            await crud.list_test_configs(
                session
            )
        )

    used_count = (
        len(all_configs)
        - available_count
    )

    await message.answer(
        "📦 <b>موجودی اکانت تست</b>\n\n"
        f"🟢 قابل استفاده: <b>{available_count}</b>\n"
        f"🔴 مصرف‌شده: <b>{used_count}</b>\n"
        f"📊 کل ثبت‌شده: <b>{len(all_configs)}</b>\n\n"
        "برای مدیریت کانفیگ‌های آزاد از دکمه زیر استفاده کن.",
        reply_markup=test_stock_keyboard(),
    )


# ============================================================
# SHOW AVAILABLE TEST CONFIGS
# ============================================================

def available_test_configs_keyboard(
    configs,
) -> InlineKeyboardMarkup:

    buttons = []

    for test_config in configs:

        buttons.append(
            [
                InlineKeyboardButton(
                    text=f"🗑 حذف کانفیگ #{test_config.id}",
                    callback_data=(
                        f"{TEST_CONFIG_DELETE_PREFIX}"
                        f"{test_config.id}"
                    ),
                )
            ]
        )

    buttons.append(
        [
            InlineKeyboardButton(
                text="🔄 بروزرسانی",
                callback_data=TEST_CONFIG_LIST_CALLBACK,
            ),
            InlineKeyboardButton(
                text="🔙 برگشت",
                callback_data=TEST_CONFIG_STOCK_CALLBACK,
            ),
        ]
    )

    return InlineKeyboardMarkup(
        inline_keyboard=buttons
    )


@router.callback_query(
    F.data == TEST_CONFIG_LIST_CALLBACK
)
async def show_available_test_configs(
    callback: CallbackQuery,
):

    if not is_admin_user(
        callback.from_user.id
    ):
        await callback.answer(
            "⛔ دسترسی ندارید.",
            show_alert=True,
        )
        return

    async with get_session() as session:

        configs = []

        all_configs = (
            await crud.list_test_configs(
                session
            )
        )

        for test_config in all_configs:

            if not test_config.used:
                configs.append(
                    test_config
                )

    if not configs:

        await callback.message.edit_text(
            "🧪 <b>کانفیگ‌های آزاد تست</b>\n\n"
            "❌ در حال حاضر هیچ کانفیگ آزادی وجود ندارد.",
            reply_markup=InlineKeyboardMarkup(
                inline_keyboard=[
                    [
                        InlineKeyboardButton(
                            text="🔙 برگشت",
                            callback_data=TEST_CONFIG_STOCK_CALLBACK,
                        )
                    ]
                ]
            ),
        )

        await callback.answer()
        return

    text = (
        "🧪 <b>کانفیگ‌های آزاد تست</b>\n\n"
        f"📦 تعداد کانفیگ آزاد: <b>{len(configs)}</b>\n\n"
        "برای حذف هر کانفیگ، روی دکمه مربوط به آن بزن."
    )

    await callback.message.edit_text(
        text,
        reply_markup=available_test_configs_keyboard(
            configs
        ),
    )

    await callback.answer()


# ============================================================
# CONFIRM DELETE
# ============================================================
# این هندلر عمداً قبل از هندلر DELETE معمولی قرار گرفته
# تا callback مربوط به confirm با prefix عمومی اشتباه نشود.
# ============================================================

@router.callback_query(
    F.data.startswith(
        TEST_CONFIG_DELETE_CONFIRM_PREFIX
    )
)
async def confirm_test_config_delete(
    callback: CallbackQuery,
):

    if not is_admin_user(
        callback.from_user.id
    ):
        await callback.answer(
            "⛔ دسترسی ندارید.",
            show_alert=True,
        )
        return

    try:
        config_id = int(
            callback.data[
                len(
                    TEST_CONFIG_DELETE_CONFIRM_PREFIX
                ):
            ]
        )

    except (TypeError, ValueError):

        await callback.answer(
            "❌ شناسه کانفیگ نامعتبر است.",
            show_alert=True,
        )
        return

    async with get_session() as session:

        deleted = (
            await crud.delete_available_test_config(
                session=session,
                test_config_id=config_id,
            )
        )

    if not deleted:

        await callback.answer(
            "❌ این کانفیگ وجود ندارد یا قبلاً مصرف شده است.",
            show_alert=True,
        )

        # لیست را دوباره نمایش بده
        await show_available_test_configs(
            callback
        )

        return

    await callback.answer(
        "✅ کانفیگ با موفقیت حذف شد."
    )

    # نمایش مجدد لیست بعد از حذف
    await show_available_test_configs(
        callback
    )


# ============================================================
# ASK DELETE CONFIRMATION
# ============================================================

@router.callback_query(
    F.data.startswith(
        TEST_CONFIG_DELETE_PREFIX
    )
)
async def ask_test_config_delete(
    callback: CallbackQuery,
):

    if not is_admin_user(
        callback.from_user.id
    ):
        await callback.answer(
            "⛔ دسترسی ندارید.",
            show_alert=True,
        )
        return

    try:
        config_id = int(
            callback.data[
                len(
                    TEST_CONFIG_DELETE_PREFIX
                ):
            ]
        )

    except (TypeError, ValueError):

        await callback.answer(
            "❌ شناسه کانفیگ نامعتبر است.",
            show_alert=True,
        )
        return

    async with get_session() as session:

        configs = (
            await crud.list_test_configs(
                session
            )
        )

        selected_config = next(
            (
                config
                for config in configs
                if config.id == config_id
                and not config.used
            ),
            None,
        )

    if not selected_config:

        await callback.answer(
            "❌ این کانفیگ وجود ندارد یا قبلاً مصرف شده است.",
            show_alert=True,
        )

        await show_available_test_configs(
            callback
        )

        return

    preview = escape(
        str(
            selected_config.config_text
        )
    )

    # برای اینکه متن خیلی طولانی نشود
    if len(preview) > 700:
        preview = (
            preview[:700]
            + "\n..."
        )

    keyboard = InlineKeyboardMarkup(
        inline_keyboard=[
            [
                InlineKeyboardButton(
                    text="🗑 بله، حذف شود",
                    callback_data=(
                        f"{TEST_CONFIG_DELETE_CONFIRM_PREFIX}"
                        f"{config_id}"
                    ),
                ),
                InlineKeyboardButton(
                    text="❌ لغو",
                    callback_data=(
                        f"{TEST_CONFIG_DELETE_CANCEL_PREFIX}"
                        f"{config_id}"
                    ),
                ),
            ],
            [
                InlineKeyboardButton(
                    text="🔙 برگشت به لیست",
                    callback_data=TEST_CONFIG_LIST_CALLBACK,
                )
            ],
        ]
    )

    await callback.message.edit_text(
        "⚠️ <b>حذف کانفیگ تست</b>\n\n"
        f"🆔 <b>شناسه:</b> {config_id}\n\n"
        "آیا مطمئنی که می‌خواهی این کانفیگ حذف شود؟\n\n"
        "🔐 <b>پیش‌نمایش کانفیگ:</b>\n"
        f"<pre>{preview}</pre>\n\n"
        "⚠️ این عملیات قابل برگشت نیست.",
        reply_markup=keyboard,
    )

    await callback.answer()


# ============================================================
# CANCEL DELETE
# ============================================================

@router.callback_query(
    F.data.startswith(
        TEST_CONFIG_DELETE_CANCEL_PREFIX
    )
)
async def cancel_test_config_delete(
    callback: CallbackQuery,
):

    if not is_admin_user(
        callback.from_user.id
    ):
        await callback.answer(
            "⛔ دسترسی ندارید.",
            show_alert=True,
        )
        return

    await show_available_test_configs(
        callback
    )

    await callback.answer(
        "لغو شد."
    )


# ============================================================
# BACK TO STOCK
# ============================================================

@router.callback_query(
    F.data == TEST_CONFIG_STOCK_CALLBACK
)
async def back_to_test_stock(
    callback: CallbackQuery,
):

    if not is_admin_user(
        callback.from_user.id
    ):
        await callback.answer(
            "⛔ دسترسی ندارید.",
            show_alert=True,
        )
        return

    async with get_session() as session:

        available_count = (
            await crud.get_available_test_config_count(
                session
            )
        )

        all_configs = (
            await crud.list_test_configs(
                session
            )
        )

    used_count = (
        len(all_configs)
        - available_count
    )

    await callback.message.edit_text(
        "📦 <b>موجودی اکانت تست</b>\n\n"
        f"🟢 قابل استفاده: <b>{available_count}</b>\n"
        f"🔴 مصرف‌شده: <b>{used_count}</b>\n"
        f"📊 کل ثبت‌شده: <b>{len(all_configs)}</b>",
        reply_markup=test_stock_keyboard(),
    )

    await callback.answer()