"""
Alert dispatch: e-mail (smtplib) and HTTP webhook.

Alerts are only sent when the assessment level meets or exceeds min_level.
"""
import logging
import os
import smtplib
from email.message import EmailMessage

import requests

from .plain import ampel
from .report import render_markdown

logger = logging.getLogger(__name__)

_LEVEL_ORDER = {"green": 0, "yellow": 1, "red": 2}


def send_alert(report: dict, cfg: dict) -> None:
    """Send alert if the report's level is at or above min_level."""
    alerting = cfg.get("alerting", {})
    level = report.get("assessment", {}).get("level", "green")
    min_level = alerting.get("min_level", "yellow")

    if _LEVEL_ORDER.get(level, 0) < _LEVEL_ORDER.get(min_level, 1):
        logger.debug("Alert suppressed: level=%s < min_level=%s", level, min_level)
        return

    subject = _make_subject(report)
    body = _format_body(report)

    email_cfg = alerting.get("email", {})
    if email_cfg.get("enabled"):
        _send_email(subject, body, email_cfg)

    webhook_cfg = alerting.get("webhook", {})
    if webhook_cfg.get("enabled") and webhook_cfg.get("url"):
        _send_webhook(webhook_cfg["url"], report, subject)


# ---------------------------------------------------------------------------
# Formatting
# ---------------------------------------------------------------------------

def _make_subject(report: dict) -> str:
    level = report.get("assessment", {}).get("level", "green")
    target = report.get("target", "?")
    symbol, _ = ampel(level)
    if level == "red":
        return f"{symbol} Ihre Website {target} braucht Aufmerksamkeit"
    if level == "yellow":
        return f"{symbol} Bitte einmal auf Ihrer Website {target} nachschauen"
    return f"{symbol} Ihre Website {target}: alles in Ordnung"


def _format_body(report: dict) -> str:
    """E-Mail-Body = derselbe Renderer wie der Dateibericht (eine Quelle der
    Wahrheit). So enthalten Report und Mail garantiert denselben Inhalt."""
    return render_markdown(report)


# ---------------------------------------------------------------------------
# Transport
# ---------------------------------------------------------------------------

def _send_email(subject: str, body: str, cfg: dict) -> None:
    password = os.environ.get(cfg.get("smtp_password_env", "SCANNER_SMTP_PASSWORD"), "")
    recipients = cfg.get("to", [])
    if not recipients:
        logger.warning("E-Mail alert enabled but no recipients configured.")
        return

    msg = EmailMessage()
    msg["Subject"] = subject
    msg["From"] = cfg.get("from", "scanner@localhost")
    msg["To"] = ", ".join(recipients)
    msg.set_content(body)

    host = cfg.get("smtp_host", "localhost")
    port = cfg.get("smtp_port", 587)
    use_tls = cfg.get("smtp_tls", True)

    try:
        with smtplib.SMTP(host, port) as server:
            if use_tls:
                server.starttls()
            user = cfg.get("smtp_user", "")
            if user and password:
                server.login(user, password)
            server.send_message(msg)
        logger.info("Alert e-mail sent to %s", recipients)
    except Exception as exc:
        logger.error("E-mail alert failed: %s", exc)


def _send_webhook(url: str, report: dict, subject: str) -> None:
    payload = {
        "text": subject,
        "target": report.get("target"),
        "level": report.get("assessment", {}).get("level"),
        "score": report.get("assessment", {}).get("score"),
        "reasons": report.get("assessment", {}).get("reasons", []),
        "new_external_domains": report.get("diff", {}).get("new_external_domains", []),
        "new_internal_urls": report.get("diff", {}).get("new_internal_urls", []),
        "missing_internal_urls": report.get("diff", {}).get("missing_internal_urls", []),
        "changed_pages": report.get("diff", {}).get("changed_pages", 0),
    }
    try:
        resp = requests.post(url, json=payload, timeout=10)
        logger.info("Webhook delivered: HTTP %s", resp.status_code)
    except Exception as exc:
        logger.error("Webhook alert failed: %s", exc)
