# Handles incoming messages and URLs unique for TeLLMgramBot
import re
from typing import Optional
import validators

from .initialize import init_url_prompt
from .models import TokenLimits
from .web_utils import fetch_url, strip_html_markup, InvalidURLException, InsecureURLException, SusURLException
from .providers.factory import get_provider

def handle_greetings(text: str) -> Optional[str]:
    """
    Respond quickly with single-word greetings like these examples:
    - ' hello ' -> 'Hello!'
    - 'Hey...?' -> 'Hey!'
    - 'SUP?!?!' -> 'Sup!'
    """
    greetings = {'Hello', 'Hi', 'Hey', 'Heya', 'Sup', 'Yo'}
    word = re.sub(r'[^\w]', '', text.title().strip())
    if word in greetings:
        return f'{word}!'
    return None

def handle_common_queries(text: str) -> Optional[str]:
    """
    Send messages for assistant bot to respond quickly with some example phrases:
    - ' How you doing ' -> 'How YOU doin?'
    - 'What's up!' -> 'Wassup?'
    """
    phrase = re.sub(r'[^\w]', '', text.lower().strip())
    if phrase.startswith('howyoudoin'):
        return 'How YOU doin?'
    elif phrase == 'wassup' or phrase == 'whatup' or phrase == 'whatsup':
        return 'Wassup?'
    return None

async def handle_url_ask(text: str, model='gpt-4o') -> Optional[str]:
    """
    Process URL content in another Generative AI model to provide a summary.
    - Check if the message contains a URL wrapped in square brackets [] only.
    - Ensure URL exists and VirusTotal does not flag it suspicious.
    - Note URLs may be case-sensitive especially with subdirectories.
    """
    url_match = re.search(r'\[http(s)?://\S+]', text.strip())
    if url_match:
        # Extract the URL from the message, but not the square brackets
        url = url_match.group()[1:-1]

        # Fetch the URL content
        try:
            # The function strips the HTML markup and ensures the URL is valid and safe
            url_content = strip_html_markup(await fetch_url(url))

            # Check if the URL is valid real quick
            if not validators.url(url):
                raise InvalidURLException(f'Invalid URL parsed by message_handlers.handle_url_ask(): {url}')

            # Build messages:
            # 1. URL content to be added into the system prompt template
            # 2. User message requesting URL in [square brackets]
            messages = [
                {"role": "system", "content": url_content},
                {"role": "user", "content": text}
            ]

            # Consider the maximum amount of tokens a LLM can support.
            # If the URL content is too big, we need to prune it down to a reasonable size.
            # Let's also reserve 500 tokens for prompt and response.
            lengthy_url = False
            pruned_tail = ''
            token_model = TokenLimits(model)
            token_count = await token_model.num_tokens_from_messages(messages)
            token_limit = token_model.max_tokens() - 500
            if token_count > token_limit:
                lengthy_url = True
                while token_count > token_limit:
                    # Remove every last word until the token limit is satisfied
                    messages[0]["content"] = messages[0]["content"].rsplit(' ', 1)[0]
                    token_count = await token_model.num_tokens_from_messages(messages)
                # Show the last 50 characters of the pruned URL content
                pruned_tail = messages[0]["content"][-50:]

            # Load system prompt template to insert URL content
            with open(init_url_prompt('url_analysis.prmpt'), 'r') as f:
                template = f.read()
            messages[0]["content"] = template.format(url_content=messages[0]["content"])

            # Call the LLM for the response that summarizes URL content
            try:
                response = await get_provider(model).complete(model, messages)
            except Exception as e:
                print(f"Error calling LLM provider: {e}")
                return "Something went wrong while fetching the URL. Please try again later."

            # If the URL content was too long, let the user know
            if lengthy_url:
                response += ("\n\n"
                             "*NOTE*: The URL content was too long and needed to be pruned for my summary."
                             f" If the text after \"{pruned_tail}\" is crucial, insert the rest for me."
                             )
            return response

        except InvalidURLException:
            return "The URL you provided appears to be invalid. Could you please check it and try again?"
        except InsecureURLException:
            return ("The URL you provided is not secure. Could you please try another URL, or just pasting the "
                    "relevant content here?")
        except SusURLException:
            return ("The URL you provided is potentially unsafe, based on my internal scans. You can check the safety "
                    "of URLS using this site: https://www.virustotal.com/gui/home/url")
        except Exception as e:
            return f"Something went wrong while fetching the URL: {e}"

    return None
