"""Destination configuration and runtime settings UI."""

from __future__ import annotations

import logging

from aiogram import F, Router
from aiogram.filters import Command
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from aiogram.types import CallbackQuery, Message

from app.context import AppContext
from app.errors import AppError
from app.handlers.common import error_text, safe_edit
from app.keyboards.callbacks import SettingsCB
from app.keyboards.menus import destination_prompt_keyboard, settings_keyboard
from app.services.uploader import normalize_chat_target
from app.utils.formatting import esc, format_destination

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


class SettingsStates(StatesGroup):
    waiting_destination = State()


DESTINATION_PROMPT = (
    "<b>✏️ تنظیم مقصد انتشار</b>\n\n"
    "شناسه عددی مقصد (مانند <code>-1001234567890</code>) یا نام کاربری کانال "
    "(مانند <code>@my_channel</code>) را بفرستید.\n\n"
    "شرایط:\n"
    "• ربات باید عضو کانال یا گروه باشد.\n"
    "• در کانال، ربات باید مدیر با اجازه «ارسال پیام» باشد.\n"
    "• چت خصوصی به‌عنوان مقصد انتشار پذیرفته نمی‌شود.\n\n"
    "پس از ذخیره می‌توانید با دکمه «آزمون ارسال» دسترسی را بررسی کنید."
)


def _short_domains(domains: list[str], limit: int = 12) -> str:
    shown = domains[:limit]
    text = "، ".join(f"<code>{esc(item)}</code>" for item in shown)
    if len(domains) > limit:
        text += f" و {len(domains) - limit} دامنه دیگر"
    return text or "—"


async def settings_text(ctx: AppContext) -> str:
    raw_destination = await ctx.repo.get_setting("destination_chat_id")
    settings = ctx.settings
    lines = [
        "<b>⚙️ تنظیمات ربات</b>",
        "",
        f"مقصد انتشار: {format_destination(raw_destination, settings.default_chat_id)}",
        f"دامنه‌های مجاز: {_short_domains(settings.allowed_domains)}",
        "ذخیره‌سازی رسانه: <b>غیرفعال (ارسال مستقیم)</b>",
        "",
        "<b>محدودیت‌ها</b>",
        f"حداکثر صفحات هر عملیات: <b>{settings.max_pages_per_job}</b>",
        f"حداکثر ویدئوهای هر عملیات: <b>{settings.max_videos_per_job}</b>",
        f"دانلود هم‌زمان: <b>{settings.max_concurrent_downloads}</b>",
        f"حداکثر حجم فایل: <b>{settings.max_file_size_mb} MB</b>",
        f"حداکثر آپلود تلگرام: <b>{settings.telegram_max_upload_mb} MB</b>",
        f"زمان هر عملیات: <b>{settings.max_job_seconds} ثانیه</b>",
        f"robots.txt: <b>{'رعایت می‌شود' if settings.respect_robots_txt else 'غیرفعال'}</b>",
        f"Playwright fallback: <b>{'فعال' if settings.browser_fallback_enabled else 'غیرفعال'}</b>",
        f"FFmpeg: <b>{'در دسترس' if ctx.processor.available else 'در دسترس نیست'}</b>",
        "",
        "مقصد در دیتابیس ذخیره می‌شود. سایر محدودیت‌ها از فایل <code>.env</code> "
        "خوانده می‌شوند و نیاز به راه‌اندازی مجدد دارند.",
    ]
    return "\n".join(lines)


@router.message(Command("settings"))
async def settings_command(
    message: Message, state: FSMContext, ctx: AppContext
) -> None:
    await state.clear()
    await message.answer(
        await settings_text(ctx),
        parse_mode="HTML",
        disable_web_page_preview=True,
        reply_markup=settings_keyboard(),
    )


@router.callback_query(SettingsCB.filter(F.action.in_({"menu", "refresh"})))
async def settings_menu_callback(
    callback: CallbackQuery,
    callback_data: SettingsCB,
    state: FSMContext,
    ctx: AppContext,
) -> None:
    await state.clear()
    await callback.answer()
    await safe_edit(callback, await settings_text(ctx), settings_keyboard())


@router.callback_query(SettingsCB.filter(F.action == "destination"))
async def destination_callback(
    callback: CallbackQuery,
    callback_data: SettingsCB,
    state: FSMContext,
    ctx: AppContext,
) -> None:
    await state.set_state(SettingsStates.waiting_destination)
    await callback.answer()
    await safe_edit(callback, DESTINATION_PROMPT, destination_prompt_keyboard())


@router.callback_query(SettingsCB.filter(F.action == "test"))
async def test_destination_callback(
    callback: CallbackQuery,
    callback_data: SettingsCB,
    ctx: AppContext,
) -> None:
    await callback.answer("در حال بررسی مقصد…")
    try:
        destination = await ctx.uploader.resolve_destination()
        await ctx.uploader.send_test_message(destination.chat_id)
    except AppError as exc:
        await callback.bot.send_message(
            callback.from_user.id,
            f"❌ آزمون مقصد ناموفق بود:\n{esc(error_text(exc))}",
            parse_mode="HTML",
        )
        return
    except Exception:
        logger.exception("destination test failed")
        await callback.bot.send_message(
            callback.from_user.id,
            "❌ خطای غیرمنتظره هنگام آزمون مقصد رخ داد. گزارش ربات را بررسی کنید.",
        )
        return
    await safe_edit(
        callback,
        await settings_text(ctx) + "\n\n✅ پیام آزمایشی با موفقیت به مقصد ارسال شد.",
        settings_keyboard(),
    )


@router.callback_query(SettingsCB.filter(F.action == "clear"))
async def clear_destination_callback(
    callback: CallbackQuery,
    callback_data: SettingsCB,
    state: FSMContext,
    ctx: AppContext,
) -> None:
    await state.clear()
    await ctx.repo.delete_setting("destination_chat_id")
    await callback.answer("مقصد ذخیره‌شده حذف شد.")
    await safe_edit(callback, await settings_text(ctx), settings_keyboard())


@router.message(
    SettingsStates.waiting_destination, F.text, ~F.text.startswith("/")
)
async def destination_message(
    message: Message, state: FSMContext, ctx: AppContext
) -> None:
    raw = (message.text or "").strip()
    placeholder = await message.answer("⏳ در حال بررسی دسترسی ربات به مقصد…")
    try:
        target = normalize_chat_target(raw)
        destination = await ctx.uploader.validate_target(target)
    except AppError as exc:
        await placeholder.edit_text(
            f"❌ {esc(error_text(exc))}\n\nدوباره تلاش کنید یا /settings را بزنید.",
            parse_mode="HTML",
        )
        return
    except Exception:
        logger.exception("destination validation failed")
        await placeholder.edit_text(
            "❌ خطای غیرمنتظره در بررسی مقصد رخ داد. گزارش ربات را بررسی کنید."
        )
        return

    await ctx.repo.set_setting("destination_chat_id", str(target))
    await state.clear()
    await placeholder.edit_text(
        "✅ مقصد انتشار ذخیره شد.\n"
        f"عنوان: <b>{esc(destination.title)}</b>\n"
        f"شناسه: <code>{destination.chat_id}</code>\n\n"
        + await settings_text(ctx),
        parse_mode="HTML",
        disable_web_page_preview=True,
        reply_markup=settings_keyboard(),
    )
