"""Custom commands — let admins define their own chat commands.

A custom command is stored as a row in the `custom_commands` table with:
  • name (e.g. "rules")
  • response text
  • file_id / file_type (optional, for media replies)

When a non-built-in command is sent, the bot looks it up and replies.
"""
from __future__ import annotations

import logging
import shlex
from typing import Optional

from telegram import Update
from telegram.constants import ParseMode
from telegram.error import BadRequest
from telegram.ext import ContextTypes

from bot import db
from bot.decorators import admin_only
from bot.persian_router import register_mixed

logger = logging.getLogger(__name__)


@admin_only
async def setcmd_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Define a custom command. Reply to a message to capture its content."""
    chat = update.effective_chat
    msg = update.message
    text = msg.text or ""
    parts = text.split(maxsplit=1)
    if len(parts) < 2:
        await msg.reply_text(
            "❌ استفاده: <code>setcmd name</code> (روی پیام ریپلای کنید)\n"
            "یا <code>setcmd name | متن پاسخ</code>",
            parse_mode=ParseMode.HTML,
        )
        return
    rest = parts[1]
    # Format: name | response   OR   name (with reply)
    if "|" in rest:
        name, body = rest.split("|", 1)
        name = name.strip().lstrip("/").lower()
        body = body.strip()
        if not name or not body:
            await msg.reply_text("❌ نام و پاسخ باید پر باشند.")
            return
        await db.add_custom_command(chat.id, name, body, None, None)
        await msg.reply_text(f"✅ دستور سفارشی <code>/{name}</code> ثبت شد.", parse_mode=ParseMode.HTML)
        return

    name = rest.strip().lstrip("/").lower()
    if not name:
        await msg.reply_text("❌ نام نامعتبر.")
        return

    if not msg.reply_to_message:
        await msg.reply_text(
            "❌ روی پیام مورد نظر ریپلای کنید یا از فرمت <code>name | متن</code> استفاده کنید.",
            parse_mode=ParseMode.HTML,
        )
        return

    rp = msg.reply_to_message
    file_id: Optional[str] = None
    file_type: Optional[str] = None
    body = rp.text or rp.caption or ""
    if rp.photo:
        file_id = rp.photo[-1].file_id
        file_type = "photo"
    elif rp.video:
        file_id = rp.video.file_id
        file_type = "video"
    elif rp.voice:
        file_id = rp.voice.file_id
        file_type = "voice"
    elif rp.document:
        file_id = rp.document.file_id
        file_type = "document"
    elif rp.sticker:
        file_id = rp.sticker.file_id
        file_type = "sticker"
    elif rp.animation:
        file_id = rp.animation.file_id
        file_type = "animation"

    await db.add_custom_command(chat.id, name, body, file_id, file_type)
    await msg.reply_text(f"✅ دستور سفارشی <code>/{name}</code> ثبت شد.", parse_mode=ParseMode.HTML)


@admin_only
async def rmcmd_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Remove a custom command."""
    chat = update.effective_chat
    text = (update.message.text or "").split(maxsplit=1)
    if len(text) < 2:
        await update.message.reply_text("❌ استفاده: <code>rmcmd name</code>", parse_mode=ParseMode.HTML)
        return
    name = text[1].strip().lstrip("/").lower()
    await db.delete_custom_command(chat.id, name)
    await update.message.reply_text(f"🗑 دستور <code>/{name}</code> حذف شد.", parse_mode=ParseMode.HTML)


@admin_only
async def cmds_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """List all custom commands in this chat."""
    chat = update.effective_chat
    cmds = await db.get_all_custom_commands(chat.id)
    if not cmds:
        await update.message.reply_text("ℹ️ دستور سفارشی‌ای تعریف نشده است.")
        return
    lines = [f"• <code>/{c['trigger']}</code>" for c in cmds]
    await update.message.reply_text(
        f"📜 <b>دستورات سفارشی ({len(cmds)}):</b>\n" + "\n".join(lines),
        parse_mode=ParseMode.HTML,
    )


async def try_dispatch_custom(update: Update, context: ContextTypes.DEFAULT_TYPE) -> bool:
    """If the message is a registered custom command, reply and return True."""
    msg = update.message
    if not msg or not msg.text:
        return False
    text = msg.text.strip()
    if not text.startswith("/"):
        return False
    parts = text.split()
    if len(parts) < 1:
        return False
    name = parts[0].lstrip("/").split("@")[0].lower()
    chat = update.effective_chat
    if not chat:
        return False
    cmd = await db.get_custom_command(chat.id, name)
    if not cmd:
        return False
    try:
        if cmd.get("file_id") and cmd.get("file_type"):
            ftype = cmd["file_type"]
            if ftype == "photo":
                await msg.reply_photo(cmd["file_id"], caption=cmd.get("response") or None, parse_mode=ParseMode.HTML)
            elif ftype == "video":
                await msg.reply_video(cmd["file_id"], caption=cmd.get("response") or None, parse_mode=ParseMode.HTML)
            elif ftype == "voice":
                await msg.reply_voice(cmd["file_id"], caption=cmd.get("response") or None, parse_mode=ParseMode.HTML)
            elif ftype == "document":
                await msg.reply_document(cmd["file_id"], caption=cmd.get("response") or None, parse_mode=ParseMode.HTML)
            elif ftype == "sticker":
                await msg.reply_sticker(cmd["file_id"])
            elif ftype == "animation":
                await msg.reply_animation(cmd["file_id"], caption=cmd.get("response") or None, parse_mode=ParseMode.HTML)
        else:
            await msg.reply_text(cmd.get("response") or "—", parse_mode=ParseMode.HTML)
        return True
    except BadRequest as e:
        logger.warning("Custom command reply failed: %s", e)
        return False


# ───────── Registration ─────────
def register(app) -> None:
    register_mixed(
        app,
        {
            "setcmd": setcmd_cmd,
            "rmcmd": rmcmd_cmd,
            "cmds": cmds_cmd,
            "listcommands": cmds_cmd,
        },
        {
            "ساخت دستور": setcmd_cmd,
            "حذف دستور": rmcmd_cmd,
            "دستورات": cmds_cmd,
        },
    )


def register_listener(app) -> None:
    """Hook the custom command dispatcher at group -1 (before everything else)."""
    from telegram.ext import MessageHandler, filters
    app.add_handler(
        MessageHandler(filters.COMMAND, try_dispatch_custom),
        group=-1,
    )
