import logging
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import formataddr
from typing import Any, Dict, Iterable, Optional

from app import mysql

logger = logging.getLogger(__name__)


def _row_to_dict(row) -> Dict[str, Optional[Any]]:
    columns = [
        "file_size_limit",
        "mail_mailer",
        "mail_host",
        "mail_port",
        "mail_username",
        "mail_password",
        "mail_encryption",
        "mail_from_address",
        "mail_from_name",
        "admin_email",
    ]
    return {column: row[idx] if idx < len(row) else None for idx, column in enumerate(columns)}


def get_admin_settings() -> Optional[Dict[str, Optional[Any]]]:
    cursor = mysql.connection.cursor()
    try:
        cursor.execute(
            """
            SELECT
                file_size_limit,
                mail_mailer,
                mail_host,
                mail_port,
                mail_username,
                mail_password,
                mail_encryption,
                mail_from_address,
                mail_from_name,
                admin_email
            FROM admin_settings
            WHERE id = 1
            """
        )
        row = cursor.fetchone()
        if not row:
            return None
        settings = _row_to_dict(row)
        if settings.get("mail_port") is not None:
            try:
                settings["mail_port"] = int(settings["mail_port"])
            except (TypeError, ValueError):
                logger.warning("Invalid admin SMTP port stored: %s", settings["mail_port"])
                settings["mail_port"] = None
        return settings
    finally:
        cursor.close()


def send_email_via_admin_smtp(
    subject: str,
    html_body: str,
    recipients: Iterable[str],
    admin_settings: Optional[Dict[str, Optional[Any]]] = None,
) -> bool:
    admin_settings = admin_settings or get_admin_settings()
    cleaned: Dict[str, str] = {}
    for email in recipients or []:
        if not email:
            continue
        trimmed = email.strip()
        if not trimmed:
            continue
        cleaned[trimmed.lower()] = trimmed
    recipients = list(cleaned.values())

    if not admin_settings:
        logger.warning("Unable to send email: admin settings missing.")
        return False
    if not recipients:
        logger.info("No recipients supplied for admin SMTP email.")
        return False

    host = admin_settings.get("mail_host")
    port = admin_settings.get("mail_port")
    username = admin_settings.get("mail_username")
    password = admin_settings.get("mail_password")
    encryption = (admin_settings.get("mail_encryption") or "").strip().lower()
    from_address = (admin_settings.get("mail_from_address") or username or "").strip()
    from_name = (admin_settings.get("mail_from_name") or "Admin").strip()

    if not host or not from_address:
        logger.warning("Admin SMTP configuration incomplete. Host or from address missing.")
        return False

    if not port:
        if encryption == "ssl":
            port = 465
        elif encryption in ("tls", "starttls"):
            port = 587
        else:
            port = 25

    message = MIMEMultipart("alternative")
    message["Subject"] = subject
    message["From"] = formataddr((from_name, from_address))
    message["To"] = ", ".join(recipients)
    message.attach(MIMEText(html_body, "html", "utf-8"))

    try:
        if encryption == "ssl":
            with smtplib.SMTP_SSL(host, port, timeout=30) as server:
                if username and password:
                    server.login(username, password)
                server.send_message(message)
        else:
            with smtplib.SMTP(host, port, timeout=30) as server:
                if encryption in ("tls", "starttls"):
                    server.starttls()
                if username and password:
                    server.login(username, password)
                server.send_message(message)
        logger.info("Package notification email sent via admin SMTP.")
        return True
    except Exception as exc:
        logger.error("Failed to send email via admin SMTP: %s", exc, exc_info=True)
        return False

