"""Autolock — scheduled group lock/unlock at given times.

Inspired by DIGI ANTI's setautolock / remautolock / autolock stats commands.
"""
from __future__ import annotations

import datetime as _dt
import logging
import re
from typing import Optional

from telegram import Update
from telegram.constants import ParseMode
from telegram.error import BadRequest, Forbidden
from telegram.ext import ContextTypes, JobQueue

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

logger = logging.getLogger(__name__)


# ───────── Helpers ─────────
_TIME_RE = re.compile(r"^([01]?\d|2[0-3]):([0-5]\d)$")


def _parse_time(text: str) -> Optional[_dt.time]:
    """Parse 'HH:MM' into a datetime.time object. Returns None on failure."""
    m = _TIME_RE.match(text.strip())
    if not m:
        return None
    return _dt.time(int(m.group(1)), int(m.group(2)))


def _is_locked_now(start: str, end: str, now: _dt.time) -> bool:
    """Whether the group should be locked at `now` given the start/end times.

    Handles both overnight and same-day ranges.
    """
    s = _parse_time(start)
    e = _parse_time(end)
    if s is None or e is None:
        return False
    if s == e:
        return False
    if s < e:
        return s <= now < e
    # Overnight (e.g. 22:00 → 06:00)
    return now >= s or now < e


# ───────── Commands ─────────
@admin_only
async def setautolock_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Set autolock start and end times. Usage: setautolock HH:MM HH:MM"""
    chat = update.effective_chat
    args = (update.message.text or "").split()
    if len(args) < 3:
        await update.message.reply_text(
            "❌ استفاده: <code>setautolock 22:00 06:00</code>\n"
            "ساعت اول: زمان قفل شدن | ساعت دوم: زمان باز شدن",
            parse_mode=ParseMode.HTML,
        )
        return

    start = args[1]
    end = args[2]
    if _parse_time(start) is None or _parse_time(end) is None:
        await update.message.reply_text(
            "❌ فرمت زمان اشتباه است! از قالب <code>HH:MM</code> استفاده کنید.",
            parse_mode=ParseMode.HTML,
        )
        return

    await db.set_setting(chat.id, "autolock_start", start)
    await db.set_setting(chat.id, "autolock_end", end)
    await update.message.reply_text(
        f"⏰ قفل خودکار تنظیم شد:\n"
        f"🔒 ساعت <code>{start}</code> قفل می‌شود\n"
        f"🔓 ساعت <code>{end}</code> باز می‌شود",
        parse_mode=ParseMode.HTML,
    )


@admin_only
async def remautolock_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Remove the autolock schedule for this chat."""
    chat = update.effective_chat
    for k in ("autolock_start", "autolock_end", "autolock_active"):
        await db.set_setting(chat.id, k, None)
    await update.message.reply_text("🗑 قفل خودکار حذف شد.")


@admin_only
async def autolockstats_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Show autolock status for the current chat."""
    chat = update.effective_chat
    start = await db.get_setting(chat.id, "autolock_start")
    end = await db.get_setting(chat.id, "autolock_end")
    active = await db.get_setting(chat.id, "autolock_active")

    if not start or not end:
        await update.message.reply_text(
            "ℹ️ در حال حاضر قفل خودکار تنظیم نشده است.\n"
            "برای تنظیم: <code>setautolock 22:00 06:00</code>",
            parse_mode=ParseMode.HTML,
        )
        return

    now = _dt.datetime.now().time().replace(second=0, microsecond=0)
    currently = "🔒 قفل" if _is_locked_now(start, end, now) else "🔓 باز"

    await update.message.reply_text(
        f"⏰ <b>وضعیت قفل خودکار</b>\n\n"
        f"• ساعت قفل: <code>{start}</code>\n"
        f"• ساعت باز شدن: <code>{end}</code>\n"
        f"• وضعیت فعلی: {currently}\n"
        f"• ساعت فعلی: <code>{now.strftime('%H:%M')}</code>",
        parse_mode=ParseMode.HTML,
    )


@admin_only
async def autolockon_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Manually engage autolock now."""
    chat = update.effective_chat
    await db.set_setting(chat.id, "autolock_active", "1")
    await _set_chat_lock(context, chat.id, True)
    await update.message.reply_text("🔒 گروه قفل شد (دستی).")


@admin_only
async def autolockoff_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Manually disengage autolock."""
    chat = update.effective_chat
    await db.set_setting(chat.id, "autolock_active", "0")
    await _set_chat_lock(context, chat.id, False)
    await update.message.reply_text("🔓 گروه باز شد (دستی).")


# ───────── Background job ─────────
async def _set_chat_lock(context: ContextTypes.DEFAULT_TYPE, chat_id: int, locked: bool) -> None:
    """Toggle default permissions for non-admins to lock/unlock the group."""
    try:
        if locked:
            perms = context.bot.defaults.permissions if context.bot.defaults else None
            await context.bot.set_chat_permissions(
                chat_id,
                can_send_messages=False,
                can_send_audios=False,
                can_send_documents=False,
                can_send_photos=False,
                can_send_videos=False,
                can_send_video_notes=False,
                can_send_voice_notes=False,
                can_send_polls=False,
                can_send_other_messages=False,
                can_add_web_page_previews=False,
                can_change_info=False,
                can_invite_users=False,
                can_pin_messages=False,
                can_manage_topics=False,
            )
        else:
            await context.bot.set_chat_permissions(
                chat_id,
                can_send_messages=True,
                can_send_audios=True,
                can_send_documents=True,
                can_send_photos=True,
                can_send_videos=True,
                can_send_video_notes=True,
                can_send_voice_notes=True,
                can_send_polls=True,
                can_send_other_messages=True,
                can_add_web_page_previews=True,
            )
    except (BadRequest, Forbidden) as e:
        logger.warning("Failed to set chat permissions for %s: %s", chat_id, e)


async def autolock_job(context: ContextTypes.DEFAULT_TYPE) -> None:
    """Run every minute. For every chat with an autolock schedule, lock/unlock as needed."""
    now = _dt.datetime.now().time().replace(second=0, microsecond=0)
    now_str = now.strftime("%H:%M")

    try:
        conn = await db.get_conn()
        cursor = await conn.execute(
            "SELECT chat_id, key, value FROM chat_settings "
            "WHERE key IN ('autolock_start', 'autolock_end')"
        )
        rows = await cursor.fetchall()

        chats: dict[int, dict[str, str]] = {}
        for chat_id, key, value in rows:
            chats.setdefault(chat_id, {})[key] = value

        for chat_id, kv in chats.items():
            start = kv.get("autolock_start")
            end = kv.get("autolock_end")
            if not start or not end:
                continue
            should_be_locked = _is_locked_now(start, end, now)
            current = (await db.get_setting(chat_id, "autolock_active")) == "1"
            if should_be_locked != current:
                await db.set_setting(chat_id, "autolock_active", "1" if should_be_locked else "0")
                await _set_chat_lock(context, chat_id, should_be_locked)
                if should_be_locked and now_str == start:
                    try:
                        await context.bot.send_message(chat_id, "🔒 گروه به صورت خودکار قفل شد.")
                    except (BadRequest, Forbidden):
                        pass
                elif not should_be_locked and now_str == end:
                    try:
                        await context.bot.send_message(chat_id, "🔓 گروه به صورت خودکار باز شد.")
                    except (BadRequest, Forbidden):
                        pass
    except Exception as e:
        logger.exception("autolock_job error: %s", e)


# ───────── Registration ─────────
def register(app) -> None:
    register_mixed(
        app,
        {
            "setautolock": setautolock_cmd,
            "remautolock": remautolock_cmd,
            "autolockstats": autolockstats_cmd,
            "autolockon": autolockon_cmd,
            "autolockoff": autolockoff_cmd,
        },
        {
            "تنظیم قفل خودکار": setautolock_cmd,
            "قفل خودکار": setautolock_cmd,
            "حذف قفل خودکار": remautolock_cmd,
            "پاک کردن قفل خودکار": remautolock_cmd,
            "وضعیت قفل خودکار": autolockstats_cmd,
            "وضعیت قفل اتوماتیک": autolockstats_cmd,
            "قفل خودکار فعال": autolockon_cmd,
            "روشن کردن قفل خودکار": autolockon_cmd,
            "قفل خودکار غیرفعال": autolockoff_cmd,
            "خاموش کردن قفل خودکار": autolockoff_cmd,
        },
    )


def register_jobs(app) -> None:
    """Schedule the autolock background job (call from post_init or after build)."""
    jq: JobQueue = app.job_queue
    if jq is None:
        logger.warning("JobQueue is not available — autolock background task will not run.")
        return
    jq.run_repeating(autolock_job, interval=60, first=10, name="bobi:autolock")
