"""Public /start, deep links, help and membership-check callbacks."""

from __future__ import annotations

import logging

from aiogram import F, Router
from aiogram.exceptions import TelegramBadRequest
from aiogram.filters import Command, CommandStart
from aiogram.types import CallbackQuery, Message

from app.context import AppContext
from app.errors import BlockedUserError, DeliveryError, RateLimitedError, TokenError
from app.keyboards.inline import main_menu, membership_gate
from app.services.membership_service import MembershipResult

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


def _gate_text(result: MembershipResult, membership_message: str) -> str:
    lines = [membership_message.strip(), ""]
    if result.has_errors:
        lines.append("⚠️ بررسی عضویت در بعضی کانال‌ها ممکن نشد؛ این وضعیت به معنی عضویت نیست.")
        lines.append("")
    lines.append("کانال‌های باقی‌مانده:")
    for item in result.unconfirmed:
        if item.error:
            lines.append(f"• {item.channel.title} — بررسی ناموفق")
        else:
            lines.append(f"• {item.channel.title}")
    return "\n".join(lines)


async def _send_membership_prompt(
    message: Message | None,
    ctx: AppContext,
    *,
    token: str,
    result: MembershipResult,
    edit: bool = False,
) -> None:
    if message is None:
        return
    message_text = await ctx.app_settings.get("membership_message")
    check_label = await ctx.app_settings.get("membership_check_button")
    text = _gate_text(result, message_text)
    keyboard = membership_gate(
        [item.channel for item in result.unconfirmed],
        token=token,
        check_label=check_label,
    )
    if edit:
        try:
            await message.edit_text(text, reply_markup=keyboard)
        except TelegramBadRequest as exc:
            detail = str(exc).lower()
            if "message is not modified" in detail:
                return
            if "message can't be edited" in detail or "message to edit not found" in detail:
                await message.answer(text, reply_markup=keyboard)
                return
            raise
    else:
        await message.answer(text, reply_markup=keyboard)


@router.message(CommandStart(), F.chat.type == "private")
async def start(message: Message, ctx: AppContext) -> None:
    args = (message.text or "").split(maxsplit=1)
    payload = args[1].strip() if len(args) > 1 else ""
    user = message.from_user
    if user is None:
        return
    await ctx.repos.users.get_or_create(
        user.id, username=user.username, display_name=user.full_name
    )
    if not payload:
        if await ctx.admins.is_admin(user.id):
            await message.answer(
                "🎛 پنل مدیریت رسانه\nیکی از گزینه‌ها را انتخاب کنید:",
                reply_markup=main_menu(is_primary=await ctx.admins.is_primary(user.id)),
            )
        else:
            await message.answer(
                "سلام 👋\n"
                "این ربات برای دسترسی به ویدیوهای منتشرشده از طریق لینک اختصاصی است.\n"
                "برای دریافت ویدیو، لینک ارسال‌شده را باز کنید."
            )
        return
    if len(payload) > 64:
        await message.answer("❌ لینک نامعتبر است.")
        return
    try:
        outcome = await ctx.delivery.request(
            payload,
            telegram_id=user.id,
            username=user.username,
            display_name=user.full_name,
        )
    except TokenError as exc:
        await message.answer(f"❌ {exc}")
        return
    except (RateLimitedError, DeliveryError, BlockedUserError) as exc:
        await message.answer(f"⏳ {exc}")
        return
    if outcome.kind == "membership" and outcome.membership is not None:
        await _send_membership_prompt(message, ctx, token=payload, result=outcome.membership)
        return
    if outcome.delivery is not None:
        policy = await ctx.app_settings.delete_policy(outcome.post)
        if policy.enabled and policy.user_seconds > 0:
            await message.answer(
                f"✅ ویدیو ارسال شد. این پیام پس از {policy.user_seconds} ثانیه حذف می‌شود.\n"
                "توجه: حذف پیام از جلوگیری از ذخیره یا بازنشر محتوا توسط کاربر تضمین نمی‌کند."
            )
        else:
            await message.answer("✅ ویدیو برای شما ارسال شد.")


@router.callback_query(F.data.startswith("gate:check:"))
async def check_membership(callback: CallbackQuery, ctx: AppContext) -> None:
    user = callback.from_user
    if user is None or callback.data is None:
        return
    token = callback.data.removeprefix("gate:check:")
    if not token or len(token) > 64:
        await callback.answer("لینک نامعتبر است.", show_alert=True)
        return
    try:
        outcome = await ctx.delivery.request(
            token,
            telegram_id=user.id,
            username=user.username,
            display_name=user.full_name,
        )
    except (RateLimitedError, DeliveryError, BlockedUserError) as exc:
        await callback.answer(f"⏳ {exc}"[:190], show_alert=True)
        return
    except TokenError as exc:
        await callback.answer(f"❌ {exc}"[:190], show_alert=True)
        return
    if outcome.kind == "membership" and outcome.membership is not None:
        await _send_membership_prompt(
            callback.message, ctx, token=token, result=outcome.membership, edit=True
        )
        await callback.answer("هنوز عضو همه کانال‌ها نیستید.", show_alert=True)
        return
    if callback.message is not None:
        try:
            await callback.message.edit_text(
                "✅ عضویت تأیید شد و ویدیو در گفت‌وگوی خصوصی ارسال شد."
            )
        except Exception:
            await callback.message.answer("✅ عضویت تأیید شد و ویدیو ارسال شد.")
    await callback.answer("✅ عضویت تأیید شد.")


@router.message(Command("help"), F.chat.type == "private")
async def help_command(message: Message) -> None:
    await message.answer(
        "راهنما:\n"
        "• لینک اختصاصی ویدیو را باز کنید تا وضعیت عضویت بررسی شود.\n"
        "• برای دریافت ویدیو، عضو همه کانال‌های نمایش‌داده‌شده شوید و «بررسی عضویت» را بزنید.\n"
        "• اگر لینک منقضی یا غیرفعال شده باشد، پیام مناسب نمایش داده می‌شود.\n"
        "• دسترسی به پنل مدیریت فقط برای شناسه‌های ثبت‌شده در ADMIN_IDS است."
    )


@router.message(Command("id"))
async def show_id(message: Message) -> None:
    if message.from_user is None:
        return
    text = f"🆔 شناسه شما: `{message.from_user.id}`"
    if message.chat.type != "private":
        text += f"\n🆔 شناسه این چت: `{message.chat.id}`"
    await message.answer(text, parse_mode="Markdown")
