# modules/power/power.py
import os
import re
import time
import asyncio
from datetime import datetime, timezone

import discord
from discord.ext import commands
from discord import app_commands

from modules.common.settings import cfg
from mod_perms import require_mod_interaction

# ---------------- helpers ----------------

WEAK_REASONS = {
    "stuck", "idk", "dont know", "don't know", "unknown", "?",
    "lag", "restart", "restarting", "update", "updating", "bug",
    "crash", "crashed"
}

def _now_utc_str() -> str:
    return datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M UTC')

def _reason_ok(s: str) -> tuple[bool, str | None]:
    """
    Enforce a descriptive reason:
      - >= 20 characters
      - >= 4 words
      - at least 3 words with length >= 3
      - reject trivial/weak phrases
    """
    if not s:
        return False, "Reason is required."
    s = s.strip()
    if len(s) < 20:
        return False, "Please provide a more descriptive reason (≥ 20 characters)."
    words = re.findall(r"[A-Za-z0-9'-]+", s)
    if len(words) < 4:
        return False, "Please include at least 4 words."
    if sum(len(w) >= 3 for w in words) < 3:
        return False, "Add more detail—use at least three meaningful words (≥ 3 letters)."
    low = s.lower()
    if low in WEAK_REASONS:
        return False, "Reason is too vague. Please explain what happened."
    return True, None

async def _send_modlog(bot: commands.Bot, guild: discord.Guild, content: str):
    modlog_channel_id = cfg(bot).int('modlog_channel_id', 0)
    if not modlog_channel_id:
        print("[power] modlog_channel_id not configured; skipping modlog.")
        return
    ch = guild.get_channel(modlog_channel_id) or bot.get_channel(modlog_channel_id)
    if ch:
        try:
            await ch.send(content, allowed_mentions=discord.AllowedMentions.none())
        except Exception as e:
            print("[power] failed to send modlog:", repr(e))
    else:
        print(f"[power] channel id {modlog_channel_id} not found.")

def _current_version(bot: commands.Bot) -> str | None:
    """Best-effort: read last detected version from boot_state."""
    dm = getattr(bot, "data_manager", None)
    if not dm:
        return None
    try:
        st = (dm.get('boot_state') or [{}])[-1] if dm.get('boot_state') else {}
        v = st.get('last_version')
        return v if v else None
    except Exception:
        return None

async def _graceful_restart(bot: commands.Bot, delay: float = 2.0):
    # small delay so modlog flushes out to Discord
    await asyncio.sleep(delay)
    try:
        await bot.close()
    except Exception as e:
        print("[power] bot.close() raised:", repr(e))
    # Force exit so container/wrapper restarts us
    os._exit(0)  # noqa

# ---------------- Cog + slash group ----------------

class PowerActionsCog(commands.Cog):
    """Administrative power actions (mod-only)."""
    def __init__(self, bot: commands.Bot):
        self.bot = bot

    power = app_commands.Group(name="power", description="Administrative power actions (mod-only)")

    @power.command(name="restart", description="[MOD] Restart the bot. Provide a descriptive reason.")
    @app_commands.describe(reason="Explain why a restart is necessary (be specific).")
    async def restart(self, interaction: discord.Interaction, reason: str):
        # Mods only
        if not await require_mod_interaction(interaction):
            return

        ok, err = _reason_ok(reason)
        if not ok:
            return await interaction.response.send_message(f"❌ {err}", ephemeral=True)

        await interaction.response.send_message("🔁 Restart requested — logging to modlog and restarting…", ephemeral=True)

        guild = interaction.guild
        stamp = _now_utc_str()
        ver = _current_version(interaction.client) or "unknown"

        log = (
            "🔁 **Bot Restart Requested**\n"
            f"**By:** {interaction.user.mention}\n"
            f"**When:** {stamp}\n"
            f"**Running version:** `{ver}`\n"
            f"**Reason:** {reason.strip()}"
        )
        if guild:
            await _send_modlog(interaction.client, guild, log)
        else:
            print("[power] no guild on interaction; modlog not sent.")

        await _graceful_restart(interaction.client, delay=2.0)

# ---------------- setup ----------------

async def setup(bot: commands.Bot):
    cog = PowerActionsCog(bot)
    await bot.add_cog(cog)

    home_gid = cfg(bot).int('home_guild_id', 0)
    guild_obj = discord.Object(id=home_gid) if home_gid else None

    # remove any prior 'power' root to keep reloads idempotent
    def _rm(name: str):
        try:
            bot.tree.remove_command(name, guild=guild_obj)
        except Exception:
            try:
                bot.tree.remove_command(name, guild=None)
            except Exception:
                pass

    _rm("power")
    if home_gid:
        bot.tree.add_command(cog.power, guild=guild_obj)
        print("[power] Registered /power group to home guild", home_gid)
    else:
        bot.tree.add_command(cog.power)
        print("[power] Registered /power group globally")
