from . import command, STOP_PROCESSING, CONTINUE_PROCESSING, RestartException, USER_SET, users_map, reply_fn
import io
import inspect
import math
import sys
import subprocess
import importlib
import os
import signal
import re
import random
import telegram
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from html import escape
import logging

config = None

logger = logging.getLogger("misc")

@command('units (?:(.+) to )?(.+)', pass_groups=True, inline=True)
def units(bea, bot, update, groups):
    is_inline = update.inline_query is not None
    groups = [x for x in groups if x is not None]
    query = groups[0] if len(groups) == 1 else f"{groups[0]} to {groups[1]}"
    proc = subprocess.run(["units", *groups], capture_output=True, text=True)
    if proc.stderr:
        if (len(proc.stderr) < 1024):
            return bea.reply(f"error running units: {proc.stderr}")
    elif proc.stdout:
        if (len(proc.stdout) < 1024):
            text = proc.stdout.replace('\t', '')
            if is_inline:
                return bea.inline_reply_text(text, f"_{query}_\n{text}", parse_mode="Markdown")
            else:
                return bea.reply(proc.stdout.replace('\t', ''))

def visent(bea, bot, update):
    """visent"""
    if not update.effective_message: return
    if not update.effective_message.text: return
    text = update.effective_message.text
    if (m := re.search(r'\bvis(s?)ent\b', text, flags=re.I)):
        update.message.reply_sticker("CAACAgQAAxkBAAIMIV5pfAABr3CDdAc201jqdCs6w0NUkgACXQIAAug0swKma3yXEo-HlRgE")
        if not m.group(1):
            bea.reply('Maar het is natuurlijk eigenlijk vissent.')
        return STOP_PROCESSING

@command(r'reload (\w+)', pass_groups=True)
def reload_module(bea, bot, update, groups):
    """ Reload a Bea module. """
    modname = groups[0]
    name = 'modules.' + modname
    new_commands = []
    for cmd in bea.commands:
        if inspect.getmodule(cmd).__name__ != name:
            new_commands.append(cmd)

    try:
        old_mod = sys.modules[name]

        if hasattr(old_mod, 'fini'):
            old_mod.fini(bea)

        mod = importlib.reload(old_mod)

        sys.modules[name] = mod
        bea.commands = mod.init(bea, bea.config.get(modname, {})) + new_commands
    except Exception as e:
        update.message.reply_text(f"Error reloading module: {e}")
        return

@command(r'send-message (\S+) (.+)', pass_groups=True, auth=True)
def send_message(bea, bot, update, groups):
    """ Send a message to a chat. Chat ID first, then the message. """
    channel, text = groups
    channel = int(channel)
    print(f"{channel}, {text}")
    bot.send_message(channel, text)

@command('send-sticker (.+) (.+)', pass_groups=True, auth=True)
def send_sticker(bea, bot, update, groups):
    """ Send a sticker to a chat. Chat ID first, then the file ID of the sticker. """
    sticker_chat, sticker = groups
    sticker_chat = int(sticker_chat)
    bot.send_sticker(sticker_chat, sticker)

@command('lenny', inline=True)
def lenny(bea, bot, update):
    """ ( ͡° ͜ʖ ͡°) """
    if update.inline_query is not None:
        bea.inline_reply_text("( ͡° ͜ʖ ͡°)")
    else:
        update.message.reply_text('( ͡° ͜ʖ ͡°)')

@command('delete$', auth=True)
def delete(bea, bot, update):
    """ Delete the message that this is a reply to. """
    m = update.message.reply_to_message
    if not m:
        return
    bot.deleteMessage(update.effective_chat.id, m.message_id)
    bot.deleteMessage(update.effective_chat.id, update.effective_message.message_id)

@command('review', additional_match_fn=reply_fn)
def review(bea, bot, update, reply):
    bea.reply(random.choice(('based', 'cringe')), reply_to_message_id=reply.message_id)

@command('reνiew', additional_match_fn=reply_fn)
def review_based(bea, bot, update, reply):
    bea.reply('based', reply_to_message_id=reply.message_id)

@command('restart', auth=True)
def restart(bea, bot, update):
    """ Restart Bea. """
    bea.is_restarting = True
    os.kill(os.getpid(), signal.SIGINT)

@command(r"@iedereen(')? ?(-?\d+)?", pass_groups=True, prefix=False)
def iedereen(bea, bot, update, groups):
    geenat = groups[0] is not None
    group_id = int(groups[1]) if groups[1] else update.effective_chat.id
    admins = bot.get_chat_administrators(group_id)
    bea.reply(' '.join([('' if geenat else '@')+admin.user.username for admin in admins if admin.user.username]), quote=False)


@command("hide\s?(.+)?", additional_match_fn=reply_fn, pass_groups=True)
def hide(bea, bot, update, reply, groups):
    title = groups[0]
    try:
        res = reply.forward('@beahiddenmsgs')
    except telegram.error.BadRequest as e:
        return bea.reply(f"Error while forwarding: {e}")
    button = InlineKeyboardButton(text='Show', url=f"https://t.me/tfckbot?start=unhide_{res.message_id}")
    keeb = InlineKeyboardMarkup([[button]])
    reply.delete()
    text = "<i>Hidden message</i>" if not title else f"<i>Hidden message: {escape(title)}</i>"
    bea.reply(text, reply_markup=keeb, parse_mode='HTML')


@command('/start (.+)', prefix=False, pass_groups=True)
def handle_start(bea, bot, update, groups):
    data = groups[0]
    if data.startswith('unhide_'):
        hidden_id = int(data.split('_')[1])
        bot.forward_message(update.effective_chat.id, '@beahiddenmsgs', hidden_id)


@command('launder$', additional_match_fn=reply_fn, auth=True)
def launder_audio(bea, bot, update, reply):
    f = reply.audio.get_file()
    buf = io.BytesIO()
    f.download(out=buf)
    buf.seek(0)
    update.message.reply_voice(buf)


@command('cut$', additional_match_fn=reply_fn, auth=True)
def cut(bea, bot, update, reply):
    if reply.from_user.id != 571967181:
        return bea.reply("Can't cut: not the owner")

    if reply.text:
        return reply.edit_text('<snip>')

    if reply.photo:
        media = telegram.InputMediaPhoto("https://via.placeholder.com/1/000000", caption="<snip>")
        return reply.edit_media(media)

    return bea.reply("Can't cut: unsupported media")

def lum(rgb):
    rgb = int(rgb, 16)
    R = ((rgb & 0xff0000) >> 16) / 256
    G = ((rgb & 0x00ff00) >> 8) / 256
    B = (rgb & 0xff) / 256
    return math.sqrt( 0.299*R**2 + 0.587*G**2 + 0.114*B**2 )


def color_code(bea, bot, update):
    """ color code parser """
    if not update.effective_message: return
    if not update.effective_message.text: return
    text = update.effective_message.text
    if (m := re.search(r'\s*#([0-9A-Fa-f]{6})\s*', text, flags=re.I)):
        color_code = m.group(1).lower()
        if lum(color_code) > 0.5:
            text_color = '000000'
        else:
            text_color = 'ffffff'
        media = f"https://via.placeholder.com/256/{color_code}/{text_color}?text=%23{color_code.upper()}"

        update.message.reply_photo(media)

        return STOP_PROCESSING

def init(bea, _config):
    global config
    config = _config
    return [launder_audio, color_code, review_based, cut, handle_start, hide, units, review, iedereen, visent, delete, lenny, send_message, send_sticker, restart, reload_module]
