"""
Email Service
Handles sending emails for invoices, credit notes, and other notifications
"""
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
from typing import Optional, List
from pathlib import Path

from app.core.config import settings
from app.utils.logger import get_logger

logger = get_logger(__name__)


class EmailService:
    """Service for sending emails"""

    def __init__(self):
        self.smtp_host = settings.smtp_host
        self.smtp_port = settings.smtp_port
        self.smtp_user = settings.smtp_user
        self.smtp_password = settings.smtp_password

    def _create_smtp_connection(self) -> smtplib.SMTP:
        """Create and authenticate SMTP connection"""
        if not self.smtp_host or not self.smtp_user or not self.smtp_password:
            raise ValueError("SMTP configuration is incomplete. Please configure SMTP settings in .env file.")

        smtp = smtplib.SMTP(self.smtp_host, self.smtp_port)
        smtp.starttls()
        smtp.login(self.smtp_user, self.smtp_password)
        return smtp

    def send_email(
        self,
        to_email: str,
        subject: str,
        body_text: str,
        body_html: Optional[str] = None,
        attachments: Optional[List[tuple[str, bytes]]] = None,
        from_email: Optional[str] = None
    ) -> bool:
        """
        Send an email with optional HTML body and attachments

        Args:
            to_email: Recipient email address
            subject: Email subject
            body_text: Plain text email body
            body_html: Optional HTML email body
            attachments: Optional list of (filename, file_bytes) tuples
            from_email: Optional sender email (defaults to smtp_user)

        Returns:
            True if email sent successfully, False otherwise
        """
        try:
            # Create message
            msg = MIMEMultipart('alternative')
            msg['From'] = from_email or self.smtp_user
            msg['To'] = to_email
            msg['Subject'] = subject

            # Attach text body
            msg.attach(MIMEText(body_text, 'plain'))

            # Attach HTML body if provided
            if body_html:
                msg.attach(MIMEText(body_html, 'html'))

            # Attach files if provided
            if attachments:
                for filename, file_bytes in attachments:
                    attachment = MIMEApplication(file_bytes)
                    attachment.add_header('Content-Disposition', 'attachment', filename=filename)
                    msg.attach(attachment)

            # Send email
            with self._create_smtp_connection() as smtp:
                smtp.send_message(msg)

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

        except Exception as e:
            logger.error(f"Failed to send email to {to_email}: {str(e)}")
            return False

    def send_invoice_email(
        self,
        invoice_number: str,
        to_email: str,
        customer_name: str,
        total_amount: str,
        due_date: str,
        pdf_bytes: Optional[bytes] = None,
        custom_message: Optional[str] = None
    ) -> bool:
        """
        Send invoice via email

        Args:
            invoice_number: Invoice number
            to_email: Customer email address
            customer_name: Customer name
            total_amount: Formatted total amount
            due_date: Formatted due date
            pdf_bytes: Optional PDF bytes to attach
            custom_message: Optional custom message to include

        Returns:
            True if email sent successfully, False otherwise
        """
        subject = f"Invoice {invoice_number}"

        # Create email body
        body_text = f"""Dear {customer_name},

Please find attached invoice {invoice_number} for the amount of {total_amount}.

Payment is due by {due_date}.

{custom_message if custom_message else ''}

Thank you for your business.

Best regards,
{settings.app_name}
"""

        body_html = f"""
<html>
<body>
<p>Dear {customer_name},</p>

<p>Please find attached invoice <strong>{invoice_number}</strong> for the amount of <strong>{total_amount}</strong>.</p>

<p>Payment is due by <strong>{due_date}</strong>.</p>

{f'<p>{custom_message}</p>' if custom_message else ''}

<p>Thank you for your business.</p>

<p>Best regards,<br>
{settings.app_name}</p>
</body>
</html>
"""

        # Prepare attachments
        attachments = []
        if pdf_bytes:
            attachments.append((f"invoice_{invoice_number}.pdf", pdf_bytes))

        return self.send_email(
            to_email=to_email,
            subject=subject,
            body_text=body_text,
            body_html=body_html,
            attachments=attachments if attachments else None
        )

    def send_credit_note_email(
        self,
        credit_note_number: str,
        to_email: str,
        customer_name: str,
        credit_amount: str,
        reason: Optional[str] = None,
        pdf_bytes: Optional[bytes] = None
    ) -> bool:
        """
        Send credit note via email

        Args:
            credit_note_number: Credit note number
            to_email: Customer email address
            customer_name: Customer name
            credit_amount: Formatted credit amount
            reason: Optional reason for credit note
            pdf_bytes: Optional PDF bytes to attach

        Returns:
            True if email sent successfully, False otherwise
        """
        subject = f"Credit Note {credit_note_number}"

        # Create email body
        body_text = f"""Dear {customer_name},

A credit note {credit_note_number} has been issued for the amount of {credit_amount}.

{f'Reason: {reason}' if reason else ''}

This credit will be applied to your account.

Best regards,
{settings.app_name}
"""

        body_html = f"""
<html>
<body>
<p>Dear {customer_name},</p>

<p>A credit note <strong>{credit_note_number}</strong> has been issued for the amount of <strong>{credit_amount}</strong>.</p>

{f'<p><strong>Reason:</strong> {reason}</p>' if reason else ''}

<p>This credit will be applied to your account.</p>

<p>Best regards,<br>
{settings.app_name}</p>
</body>
</html>
"""

        # Prepare attachments
        attachments = []
        if pdf_bytes:
            attachments.append((f"credit_note_{credit_note_number}.pdf", pdf_bytes))

        return self.send_email(
            to_email=to_email,
            subject=subject,
            body_text=body_text,
            body_html=body_html,
            attachments=attachments if attachments else None
        )
