"""Per-post deep-link token management."""

from __future__ import annotations

from aiogram import F, Router
from aiogram.fsm.context import FSMContext
from aiogram.types import CallbackQuery, Message

from app.context import AppContext
from app.database.base import utcnow
from app.handlers.common import show
from app.keyboards.inline import back_cancel, back_menu, confirm, links_menu, token_menu
from app.states import TokenState
from app.utils.validation import format_local, parse_int, parse_local_datetime

router = Router(name="links")


async def _links_home(callback: CallbackQuery, ctx: AppContext) -> None:
    posts = await ctx.repos.posts.list(limit=10)
    text = (
        "🔗 مدیریت لینک‌ها\n\n"
        "هر پست لینک اختصاصی و توکن مستقل دارد. توکن با CSPRNG تولید می‌شود و "
        "در لاگ‌ها ثبت نمی‌شود. با تولید لینک جدید، لینک قبلی غیرفعال می‌شود."
    )
    if not posts:
        text += "\n\nهنوز پستی وجود ندارد."
    await show(callback, text, links_menu(posts))


@router.callback_query(F.data == "menu:links")
async def links_home(callback: CallbackQuery, ctx: AppContext) -> None:
    await _links_home(callback, ctx)
    await callback.answer()


async def _render_link(
    callback: CallbackQuery,
    ctx: AppContext,
    post_id: int,
    *,
    answer: bool = True,
) -> bool:
    post = await ctx.repos.posts.get(post_id)
    if post is None:
        if answer:
            await callback.answer("پست پیدا نشد.", show_alert=True)
        return False
    token = await ctx.repos.tokens.latest_for_post(post_id)
    tz = ctx.settings.tzinfo
    if token is None:
        text = (
            f"🔗 پست #{post_id}\nلینک فعالی وجود ندارد.\n"
            "با «تولید لینک جدید» یک توکن تازه ساخته می‌شود."
        )
        active = False
    else:
        expires = format_local(token.expires_at, tz, empty="بدون انقضا")
        max_uses = "نامحدود" if token.max_uses is None else str(token.max_uses)
        text = (
            f"🔗 پست #{post_id}\n"
            f"عنوان: {post.title or 'بدون عنوان'}\n"
            f"لینک:\n{post.video_link or '—'}\n\n"
            f"وضعیت توکن: {'فعال' if token.is_active else 'غیرفعال'}\n"
            f"استفاده‌شده: {token.use_count} از {max_uses}\n"
            f"انقضا: {expires}\n"
            f"آخرین استفاده: {format_local(token.last_used_at, tz)}\n"
            f"تعداد کل توکن‌های این پست: {len(await ctx.repos.tokens.list_for_post(post_id))}"
        )
        active = token.is_active
    await show(callback, text, token_menu(post_id, active))
    if answer:
        await callback.answer()
    return True


@router.callback_query(F.data.startswith("post:link:"))
async def link_view_from_post(callback: CallbackQuery, ctx: AppContext) -> None:
    post_id = int(callback.data.rsplit(":", 1)[1])
    if await _render_link(callback, ctx, post_id, answer=False):
        await callback.answer()


@router.callback_query(F.data.startswith("link:view:"))
async def link_view(callback: CallbackQuery, ctx: AppContext) -> None:
    post_id = int(callback.data.rsplit(":", 1)[1])
    if await _render_link(callback, ctx, post_id, answer=False):
        await callback.answer()


@router.callback_query(F.data.startswith("link:regen:"))
async def link_regen_ask(callback: CallbackQuery, ctx: AppContext) -> None:
    post_id = int(callback.data.rsplit(":", 1)[1])
    await show(
        callback,
        "لینک جدید ساخته شود؟ لینک قبلی فوراً غیرفعال می‌شود و کاربران قبلی "
        "با لینک قدیمی نمی‌توانند ویدیو دریافت کنند.",
        confirm("regen", post_id, back=f"link:view:{post_id}"),
    )
    await callback.answer()


@router.callback_query(F.data.startswith("confirm:regen:"))
async def link_regen_confirm(callback: CallbackQuery, ctx: AppContext) -> None:
    post_id = int(callback.data.rsplit(":", 1)[1])
    try:
        link = await ctx.tokens.regenerate(post_id, actor_id=callback.from_user.id)
    except Exception as exc:
        await callback.answer(str(exc)[:190], show_alert=True)
        return
    await callback.answer("لینک جدید ساخته شد.")
    await show(
        callback,
        f"🔗 لینک جدید پست #{post_id}:\n{link}",
        back_menu(f"link:view:{post_id}"),
    )


@router.callback_query(F.data.startswith("link:toggle:"))
async def link_toggle(callback: CallbackQuery, ctx: AppContext) -> None:
    post_id = int(callback.data.rsplit(":", 1)[1])
    token = await ctx.repos.tokens.latest_for_post(post_id)
    if token is None:
        await callback.answer("لینکی برای این پست وجود ندارد.", show_alert=True)
        return
    await ctx.tokens.set_active(token.id, not token.is_active, callback.from_user.id)
    await callback.answer("وضعیت توکن تغییر کرد.")
    await _render_link(callback, ctx, post_id, answer=False)


@router.callback_query(F.data.startswith("link:expiry:"))
async def link_expiry(callback: CallbackQuery, state: FSMContext) -> None:
    post_id = int(callback.data.rsplit(":", 1)[1])
    await state.set_state(TokenState.waiting_expiry)
    await state.update_data(token_post_id=post_id)
    await show(
        callback,
        "زمان انقضا را به وقت محلی بفرستید (2026-12-31 21:30) یا off برای بدون انقضا.",
        back_cancel(f"link:view:{post_id}"),
    )
    await callback.answer()


@router.message(TokenState.waiting_expiry)
async def link_expiry_receive(message: Message, state: FSMContext, ctx: AppContext) -> None:
    data = await state.get_data()
    post_id = int(data.get("token_post_id", 0))
    token = await ctx.repos.tokens.latest_for_post(post_id)
    if token is None:
        await state.clear()
        await message.answer("لینکی برای این پست وجود ندارد.")
        return
    if not message.text:
        await message.answer("زمان یا off را بفرستید.")
        return
    text = message.text.strip().lower()
    try:
        expires_at = None if text in {"off", "بدون", "حذف"} else parse_local_datetime(text, ctx.settings.tzinfo)
        if expires_at is not None and expires_at <= utcnow():
            raise ValueError("زمان انقضا باید در آینده باشد.")
    except Exception as exc:
        await message.answer(f"⚠️ {exc}")
        return
    await ctx.tokens.set_limits(
        token.id,
        expires_at=expires_at,
        max_uses=token.max_uses,
        actor_id=message.from_user.id,
    )
    await state.clear()
    await message.answer("✅ زمان انقضا ذخیره شد.", reply_markup=back_menu(f"link:view:{post_id}"))


@router.callback_query(F.data.startswith("link:maxuses:"))
async def link_maxuses(callback: CallbackQuery, state: FSMContext) -> None:
    post_id = int(callback.data.rsplit(":", 1)[1])
    await state.set_state(TokenState.waiting_max_uses)
    await state.update_data(token_post_id=post_id)
    await show(
        callback,
        "حداکثر تعداد استفاده را بفرستید (مثلاً 10) یا off برای نامحدود.\n"
        "توجه: هر تحویل موفق ویدیو یک استفاده محسوب می‌شود.",
        back_cancel(f"link:view:{post_id}"),
    )
    await callback.answer()


@router.message(TokenState.waiting_max_uses)
async def link_maxuses_receive(message: Message, state: FSMContext, ctx: AppContext) -> None:
    data = await state.get_data()
    post_id = int(data.get("token_post_id", 0))
    token = await ctx.repos.tokens.latest_for_post(post_id)
    if token is None:
        await state.clear()
        await message.answer("لینکی برای این پست وجود ندارد.")
        return
    if not message.text:
        await message.answer("عدد یا off را بفرستید.")
        return
    text = message.text.strip().lower()
    try:
        max_uses = None if text in {"off", "نامحدود", "حذف"} else parse_int(text, name="حداکثر استفاده", minimum=1)
    except Exception as exc:
        await message.answer(f"⚠️ {exc}")
        return
    await ctx.tokens.set_limits(
        token.id,
        expires_at=token.expires_at,
        max_uses=max_uses,
        actor_id=message.from_user.id,
    )
    await state.clear()
    await message.answer("✅ محدودیت استفاده ذخیره شد.", reply_markup=back_menu(f"link:view:{post_id}"))
