"""
Обработчик быстрого ответа на заявку.

Перехватывает свободные сообщения авторизованных пользователей вне активного
флоу и предлагает отправить их как комментарий к последней активной заявке.
Последняя активная заявка определяется по:
  - уведомлению, которое было отправлено пользователю (notifier)
  - карточке заявки, которую пользователь открывал (cb_iticket_detail)
TTL контекста — 60 минут (настраивается в reply_context.py).
"""
from __future__ import annotations

from maxapi.context import BaseContext
from maxapi.dispatcher import Router
from maxapi.filters import F
from maxapi.types.updates.message_callback import MessageCallback
from maxapi.types.updates.message_created import MessageCreated

from bot.filters import PayloadStartsWith
from bot.flow_config import PAYLOADS, TRANSITIONS
from bot.handlers.create_ticket import _extract_attachments
from bot.keyboards import main_menu_kb, reply_confirm_kb
from bot.nav_helper import nav_set
from bot.send_helper import bot_send
from bot.states import AuthStates, CommentStates, TicketStates
from bot.texts import QuickReplyTexts
from database.connection import get_db
from database.queries.intradesk import get_intradesk_contact_id_for_phone
from database.queries.organizations import get_organization
from database.queries.reply_context import clear_reply_context, get_reply_context
from external.intradesk_api import (
    add_task_comment,
    invalidate_client_cache,
    invalidate_task_comment,
    upload_attachments,
)

router = Router(router_id="quick_reply")

_ACTIVE_STATES = [
    AuthStates.waiting_contact,
    TicketStates.waiting_description,
    TicketStates.collecting_attachments,
    TicketStates.confirming,
    TicketStates.pending_confirm,
    CommentStates.waiting_text,
]


@router.message_created()
async def on_idle_message(
    event: MessageCreated, context: BaseContext, bot_user: dict
) -> None:
    """Перехватить свободное сообщение вне активного флоу."""
    state = await context.get_state()
    if state in _ACTIVE_STATES:
        return

    chat_id, user_id = event.get_ids()
    if chat_id is None or user_id is None:
        return

    body = event.message.body
    text = (body.text or "").strip() if body else ""
    file_atts = _extract_attachments(event)

    if not text and not file_atts:
        return  # стикер, локация и т.п. — игнорируем

    ctx = await get_reply_context(user_id)
    if not ctx:
        return  # нет активного контекста заявки — молча игнорируем

    task_id: int = ctx["task_id"]
    task_number: int | None = ctx["task_number"]

    await context.set_state(TRANSITIONS["reply:pending"])
    await context.set_data({
        "pending_reply_text": text,
        "pending_reply_atts": file_atts,
        "pending_reply_task_id": task_id,
        "pending_reply_task_number": task_number,
    })

    display = text[:300] + ("…" if len(text) > 300 else "") if text else ""
    if file_atts:
        atts_note = f"\n📎 +{len(file_atts)} файл(ов)"
        display = (display + atts_note) if display else atts_note.strip()

    await bot_send(
        event.bot,
        chat_id=chat_id,
        user_id=user_id,
        text=QuickReplyTexts.CONFIRM.format(
            number=task_number or task_id,
            text=display,
        ),
        attachments=[reply_confirm_kb(task_id)],
    )


@router.message_callback(PayloadStartsWith(PAYLOADS.PFX_CONFIRM_REPLY))
async def cb_confirm_reply(
    event: MessageCallback, context: BaseContext, bot_user: dict
) -> None:
    state = await context.get_state()
    if state != TRANSITIONS["reply:pending"]:
        await event.answer(notification="")
        return

    await event.answer(notification="")

    data = await context.get_data()
    task_id: int | None = data.get("pending_reply_task_id")
    task_number: int | None = data.get("pending_reply_task_number")
    text: str = data.get("pending_reply_text") or ""
    file_atts: list[dict] = data.get("pending_reply_atts") or []

    await context.clear()
    await clear_reply_context(bot_user["max_user_id"])

    chat_id = event.message.recipient.chat_id if event.message else None
    if not chat_id or not task_id:
        return

    # Данные организации для contact_person_id и инвалидации кэша
    intradesk_id: int | None = None
    contact_person_id: int | None = None
    if bot_user.get("org_id"):
        org = await get_organization(bot_user["org_id"])
        intradesk_id = org.get("intradesk_id") if org else None
        if intradesk_id and bot_user.get("phone"):
            db = get_db()
            contact_person_id = await get_intradesk_contact_id_for_phone(
                db, intradesk_id, bot_user["phone"]
            )

    if file_atts:
        file_atts = await upload_attachments(file_atts, task_id=task_id, target="Comment")

    ok = await add_task_comment(
        task_number=task_number,
        text=text or "📎 Файл прикреплён",
        contact_person_id=contact_person_id,
        attachments=file_atts or None,
    )

    if ok:
        invalidate_task_comment(task_id)
        if intradesk_id:
            invalidate_client_cache(intradesk_id)

    result = (
        QuickReplyTexts.SENT.format(number=task_number or task_id)
        if ok else QuickReplyTexts.ERROR
    )
    mid = await bot_send(
        event.bot,
        chat_id=chat_id,
        user_id=bot_user["max_user_id"],
        text=result,
        attachments=[main_menu_kb()],
    )
    await nav_set(context, mid)


@router.message_callback(F.callback.payload == PAYLOADS.CANCEL_REPLY)
async def cb_cancel_reply(
    event: MessageCallback, context: BaseContext, bot_user: dict
) -> None:
    await event.answer(notification="")
    await context.clear()

    chat_id = event.message.recipient.chat_id if event.message else None
    if not chat_id:
        return

    from bot.handlers.menu import build_main_menu_text

    mid = await bot_send(
        event.bot,
        chat_id=chat_id,
        user_id=bot_user["max_user_id"],
        text=await build_main_menu_text(bot_user),
        attachments=[main_menu_kb()],
    )
    await nav_set(context, mid)
