"""
Email functionality for rateloader.

Implements send_mail() function with exact signature from PRD §2.1.
Handles SMTP email sending with attachments and SSL/TLS support.
"""

import smtplib
import os
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
from typing import Optional
from core.logger import get_hotellabexport_logger


def send_mail(
    sendfrom: str,
    sendto: str,
    subject: str,
    body: str,
    attachment_path: str,
    pwd: str,
    mailserver: str,
    port: int,
    ssl: int,
) -> bool:
    """
    Send email with attachment using SMTP.

    Parameters must be in the same order as legacy call from PRD §2.1:
    send_mail(sendfrom, sendto, subject, body, attachment_path, pwd, mailserver, port, ssl)

    Args:
        sendfrom: Sender email address
        sendto: Recipient email address
        subject: Email subject
        body: Email body
        attachment_path: Path to attachment file
        pwd: Email password
        mailserver: SMTP server address
        port: SMTP port
        ssl: SSL/TLS flag (0 for no SSL, 1 for SSL/TLS)

    Returns:
        True if email sent successfully, False otherwise
    """
    logger = get_hotellabexport_logger()

    try:
        logger.info(f"Preparing email to {sendto} with subject: {subject}")

        # Create message
        msg = MIMEMultipart()
        msg["From"] = sendfrom
        msg["To"] = sendto
        msg["Subject"] = subject

        # Add body to email
        msg.attach(MIMEText(body, "plain"))

        # Add attachment if file exists
        if attachment_path and os.path.exists(attachment_path):
            logger.info(f"Attaching file: {attachment_path}")

            # Open the file in binary mode
            with open(attachment_path, "rb") as attachment:
                # Create a MIME base object
                part = MIMEBase("application", "octet-stream")
                part.set_payload(attachment.read())

            # Encode file in ASCII characters to send by email
            encoders.encode_base64(part)

            # Add header as key/value pair to attachment part
            filename = os.path.basename(attachment_path)
            part.add_header("Content-Disposition", f"attachment; filename= {filename}")

            # Add attachment to message
            msg.attach(part)
            logger.info(f"Attachment {filename} added successfully")
        else:
            logger.warning(f"Attachment file not found: {attachment_path}")

        # Create SMTP session
        logger.info(f"Connecting to SMTP server: {mailserver}:{port}")

        if ssl == 1:
            # Use SSL/TLS
            if port == 0:
                # Default to 465 for SSL/TLS if port is 0
                port = 465
                logger.info(f"Using default SSL/TLS port: {port}")
            server = smtplib.SMTP_SSL(mailserver, port)
            logger.info("Using SSL/TLS connection")
        else:
            # Use regular SMTP (with STARTTLS if available)
            if port == 0:
                # Default to 587 for STARTTLS if port is 0
                port = 587
                logger.info(f"Using default STARTTLS port: {port}")
            server = smtplib.SMTP(mailserver, port)
            logger.info("Using SMTP connection with potential STARTTLS")

            # Try to upgrade to TLS if available
            try:
                server.starttls()
                logger.info("Successfully upgraded connection to TLS")
            except Exception as tls_e:
                logger.warning(f"Could not upgrade to TLS: {str(tls_e)}")

        # Login to the server
        logger.info(f"Logging in as: {sendfrom}")
        server.login(sendfrom, pwd)

        # Send email
        text = msg.as_string()
        server.sendmail(sendfrom, sendto, text)
        server.quit()

        logger.info(f"Email sent successfully to {sendto}")
        return True

    except smtplib.SMTPAuthenticationError as e:
        logger.error(f"SMTP authentication failed: {str(e)}")
        logger.error(f"Email send failed - From: {sendfrom}, To: {sendto}, Subject: {subject}")
        return False
    except smtplib.SMTPConnectError as e:
        logger.error(f"Failed to connect to SMTP server: {str(e)}")
        logger.error(f"Email send failed - From: {sendfrom}, To: {sendto}, Subject: {subject}")
        return False
    except smtplib.SMTPException as e:
        logger.error(f"SMTP error occurred: {str(e)}")
        logger.error(f"Email send failed - From: {sendfrom}, To: {sendto}, Subject: {subject}")
        return False
    except Exception as e:
        logger.error(f"Unexpected error sending email: {str(e)}")
        logger.error(f"Email send failed - From: {sendfrom}, To: {sendto}, Subject: {subject}")
        return False


class Mailer:
    """
    Email sender class for the rateloader application.

    Provides convenient methods for sending emails with attachments
    using the configuration from settings.ini.
    """

    def __init__(self):
        """Initialize mailer with logger."""
        self.logger = get_hotellabexport_logger()

    def send_email_with_attachment(
        self,
        subject: str,
        body: str,
        attachment_path: str,
        sendto: Optional[str] = None,
        sendfrom: Optional[str] = None,
    ) -> bool:
        """
        Send email with attachment using configuration from settings.ini.

        Args:
            subject: Email subject
            body: Email body
            attachment_path: Path to attachment file
            sendto: Recipient email (optional, uses config if not provided)
            sendfrom: Sender email (optional, uses config if not provided)

        Returns:
            True if email sent successfully, False otherwise
        """
        from .config import get_config

        try:
            config = get_config()

            # Get email configuration
            if not sendfrom:
                sendfrom = config.get("sendfrom")
            if not sendto:
                sendto = config.get("sendto")

            pwd = config.get("pwd")
            mailserver = config.get("mailserver")
            port = config.get_int("port", 465)  # Default to 465 for Yandex SSL
            ssl = config.get_int("ssl", 1)      # Default to SSL enabled for Yandex

            # Validate required configuration
            if not all([sendfrom, sendto, pwd, mailserver]):
                self.logger.error("Missing required email configuration")
                return False

            # Send email
            return send_mail(
                sendfrom=sendfrom,
                sendto=sendto,
                subject=subject,
                body=body,
                attachment_path=attachment_path,
                pwd=pwd,
                mailserver=mailserver,
                port=port,
                ssl=ssl,
            )

        except Exception as e:
            self.logger.error(f"Error in send_email_with_attachment: {str(e)}")
            return False


def create_mailer() -> Mailer:
    """
    Create a Mailer instance.

    Returns:
        Mailer instance
    """
    return Mailer()
