import json
import logging
import os
import sys
import traceback
from typing import Any

from slack_sdk.webhook import WebhookClient


logger = logging.getLogger(__name__)


def find_traceback_locations():
    _, _, tb = sys.exc_info()
    return [
        (fs.filename, fs.lineno, fs.name)
        for fs in traceback.extract_tb(tb)
        # attempt to show only *our* code, not the many layers of library code
        if "/mavedb/" in fs.filename and "/.direnv/" not in fs.filename
    ]


def send_slack_message(text: str):
    slack_webhook_url = os.getenv("SLACK_WEBHOOK_URL")
    if slack_webhook_url is not None and len(slack_webhook_url) > 0:
        client = WebhookClient(url=slack_webhook_url)
        client.send(
            text=text,
            blocks=[
                {
                    "type": "section",
                    "text": {"type": "plain_text", "text": text},
                }
            ],
        )
    else:
        print(f"EXCEPTION_HANDLER: {text}")


def send_slack_error(err, request=None):
    text = {"type": err.__class__.__name__, "exception": str(err), "location": find_traceback_locations()}

    if request:
        text["client"] = str(request.client.host)
        text["request"] = f"{request.method} {request.url}"

    text = json.dumps(text)
    send_slack_message(text)


def log_and_send_slack_message(msg: str, ctx: dict[str, Any], level: int):
    """
    Log a message and send it to Slack if the SLACK_WEBHOOK_URL environment variable is set.
    """
    logger.log(level, msg, extra=ctx)

    if os.getenv("SLACK_WEBHOOK_URL"):
        send_slack_message(msg)
    else:
        print(f"SLACK_WEBHOOK_URL not set, not sending message: {msg}.")
