"""`/add` flow and URL submission states."""

from __future__ import annotations

import logging

from aiogram import F, Router
from aiogram.filters import Command, CommandObject
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, extract_url, safe_edit
from app.keyboards.callbacks import AddCB
from app.keyboards.menus import add_prompt_keyboard, job_actions_keyboard, main_menu
from app.utils.formatting import esc, format_job_summary

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


class AddJobStates(StatesGroup):
    waiting_url = State()


PROMPT = (
    "<b>➕ افزودن عملیات جدید</b>\n\n"
    "آدرس کامل صفحه یا فایل ویدئو را بفرستید؛ باید با <code>http://</code> یا "
    "<code>https://</code> شروع شود و دامنه‌اش در فهرست مجاز باشد.\n\n"
    "مثال:\n<code>https://example.com/videos/123</code>\n\n"
    "برای انصراف از دکمه «لغو» یا دستور /start استفاده کنید."
)


async def _destination_ready(ctx: AppContext) -> bool:
    stored = await ctx.repo.get_setting("destination_chat_id")
    return bool(stored) or ctx.settings.default_chat_id is not None


async def _destination_problem(message: Message, ctx: AppContext) -> bool:
    """Return True (and explain) when the configured destination is unusable."""

    if not await _destination_ready(ctx):
        await message.answer(
            "⚙️ ابتدا مقصد انتشار را تنظیم کنید.\n"
            "از /settings یا دکمه «تنظیم مقصد» استفاده کنید. عملیات بدون مقصد معتبر "
            "شروع نمی‌شود تا دانلود بی‌فایده انجام نشود.",
            parse_mode="HTML",
        )
        return True
    try:
        await ctx.uploader.resolve_destination()
    except AppError as exc:
        await message.answer(
            "⚙️ مقصد انتشار معتبر نیست:\n"
            f"{esc(error_text(exc))}\n\n"
            "ربات را در یک کانال یا گروه عضو/ادمین کنید و از /settings مقصد را "
            "دوباره تنظیم کنید. چت خصوصی پذیرفته نمی‌شود.",
            parse_mode="HTML",
        )
        return True
    except Exception:
        logger.exception("destination validation failed")
        await message.answer(
            "⚙️ بررسی دسترسی به مقصد انتشار ممکن نشد. اتصال تلگرام را بررسی کنید و "
            "دوباره تلاش کنید.",
            parse_mode="HTML",
        )
        return True
    return False


async def _submit_url(
    message: Message,
    state: FSMContext,
    ctx: AppContext,
    raw_text: str,
) -> bool:
    if message.from_user is None:
        return False
    if await _destination_problem(message, ctx):
        return False

    placeholder = await message.answer("⏳ در حال بررسی آدرس و ساخت عملیات…")
    try:
        job = await ctx.jobs.create_job(
            extract_url(raw_text),
            owner_id=message.from_user.id,
            owner_chat_id=message.chat.id,
        )
    except AppError as exc:
        try:
            await placeholder.edit_text(
                f"❌ {esc(error_text(exc))}",
                parse_mode="HTML",
            )
        except Exception:
            await message.answer(f"❌ {esc(error_text(exc))}", parse_mode="HTML")
        return False
    except Exception:
        logger.exception("could not create job")
        await placeholder.edit_text(
            "❌ خطای غیرمنتظره هنگام ثبت عملیات رخ داد. گزارش ربات را بررسی کنید."
        )
        return False

    await placeholder.edit_text(
        f"{format_job_summary(job, detail=False)}\n\n"
        "پردازش در صف قرار گرفت. از دکمه‌های زیر می‌توانید وضعیت را ببینید.",
        parse_mode="HTML",
        disable_web_page_preview=True,
        reply_markup=job_actions_keyboard(job),
    )
    await state.clear()
    return True


@router.message(Command("add"))
async def add_command(
    message: Message,
    command: CommandObject,
    state: FSMContext,
    ctx: AppContext,
) -> None:
    await state.clear()
    argument = (command.args or "").strip()
    if argument:
        await _submit_url(message, state, ctx, argument)
        return
    await state.set_state(AddJobStates.waiting_url)
    await message.answer(
        PROMPT,
        parse_mode="HTML",
        disable_web_page_preview=True,
        reply_markup=add_prompt_keyboard(),
    )


@router.callback_query(AddCB.filter(F.action == "prompt"))
async def add_prompt_callback(
    callback: CallbackQuery, callback_data: AddCB, state: FSMContext, ctx: AppContext
) -> None:
    await state.set_state(AddJobStates.waiting_url)
    await callback.answer()
    await safe_edit(callback, PROMPT, add_prompt_keyboard())


@router.callback_query(AddCB.filter(F.action == "cancel"))
async def add_cancel_callback(
    callback: CallbackQuery, callback_data: AddCB, state: FSMContext, ctx: AppContext
) -> None:
    await state.clear()
    await callback.answer("افزودن لغو شد.")
    await safe_edit(
        callback,
        "<b>🎬 منوی اصلی</b>\n\nعملیات جدیدی ثبت نشد.",
        main_menu(is_admin=callback.from_user.id in ctx.settings.admin_ids),
    )


@router.message(AddJobStates.waiting_url, F.text, ~F.text.startswith("/"))
async def add_url_message(
    message: Message,
    state: FSMContext,
    ctx: AppContext,
) -> None:
    await _submit_url(message, state, ctx, message.text or "")
