"""
Email Skill - SMTP sending and inbox operations.
"""

from __future__ import annotations
import logging
import smtplib
import ssl
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from datetime import datetime
from typing import Optional
import uuid

logger = logging.getLogger(__name__)


class EmailSkill:
    """
    Handles email operations:
    - SMTP sending
    - Email formatting
    - Tracking pixel injection
    - Link wrapping
    """

    def __init__(self, config: dict):
        self.config = config
        self.email_config = config.get("email", {})
        self.provider = self.email_config.get("provider", "smtp")
        self.tracking_enabled = self.email_config.get("tracking", {}).get("opens", True)
        self.click_tracking = self.email_config.get("tracking", {}).get("clicks", True)

        # SMTP settings
        smtp_config = self.email_config.get("smtp", {})
        self.smtp_host = smtp_config.get("host", "")
        self.smtp_port = smtp_config.get("port", 587)
        self.smtp_username = smtp_config.get("username", "")
        self.smtp_password = smtp_config.get("password", "")
        self.use_tls = smtp_config.get("use_tls", True)

    # -------------------------------------------------------------------------
    # Sending
    # -------------------------------------------------------------------------

    def send_email(
        self,
        to_email: str,
        from_email: str,
        subject: str,
        body: str,
        from_name: str = None,
        reply_to: str = None,
        html_body: str = None,
        message_id: str = None,
        dry_run: bool = False,
    ) -> dict:
        """
        Send a single email via SMTP.

        Args:
            to_email: Recipient email
            from_email: Sender email
            subject: Email subject
            body: Plain text body
            from_name: Sender display name
            reply_to: Reply-to address
            html_body: HTML body (optional)
            message_id: Custom message ID for tracking
            dry_run: If True, don't actually send

        Returns:
            {"success": bool, "message_id": str, "error": str|None}
        """
        message_id = message_id or str(uuid.uuid4())

        if dry_run:
            logger.info(f"[EmailSkill] DRY RUN - Would send to {to_email}: {subject}")
            return {
                "success": True,
                "message_id": message_id,
                "dry_run": True,
                "error": None,
            }

        try:
            # Create message
            msg = MIMEMultipart("alternative")
            msg["Subject"] = subject
            msg["From"] = f"{from_name} <{from_email}>" if from_name else from_email
            msg["To"] = to_email
            msg["Message-ID"] = f"<{message_id}@kiessclaw>"

            if reply_to:
                msg["Reply-To"] = reply_to

            # Add plain text part
            msg.attach(MIMEText(body, "plain"))

            # Add HTML part if provided
            if html_body:
                # Inject tracking pixel if enabled
                if self.tracking_enabled:
                    html_body = self._inject_tracking_pixel(html_body, message_id)
                msg.attach(MIMEText(html_body, "html"))

            # Send via SMTP
            if not self.smtp_host:
                return {
                    "success": False,
                    "message_id": message_id,
                    "error": "SMTP not configured",
                }

            context = ssl.create_default_context()

            with smtplib.SMTP(self.smtp_host, self.smtp_port) as server:
                if self.use_tls:
                    server.starttls(context=context)
                if self.smtp_username and self.smtp_password:
                    server.login(self.smtp_username, self.smtp_password)
                server.sendmail(from_email, to_email, msg.as_string())

            logger.info(f"[EmailSkill] Sent email to {to_email}: {subject}")
            return {
                "success": True,
                "message_id": message_id,
                "error": None,
                "sent_at": datetime.now().isoformat(),
            }

        except smtplib.SMTPAuthenticationError as e:
            logger.error(f"[EmailSkill] SMTP auth error: {e}")
            return {
                "success": False,
                "message_id": message_id,
                "error": f"Authentication failed: {str(e)}",
            }
        except smtplib.SMTPRecipientsRefused as e:
            logger.error(f"[EmailSkill] Recipient refused: {e}")
            return {
                "success": False,
                "message_id": message_id,
                "error": f"Recipient refused: {str(e)}",
                "bounce_type": "hard",
            }
        except Exception as e:
            logger.error(f"[EmailSkill] Send error: {e}")
            return {
                "success": False,
                "message_id": message_id,
                "error": str(e),
            }

    def send_bulk(
        self,
        messages: list[dict],
        rate_limit: int = 50,
        dry_run: bool = False,
    ) -> list[dict]:
        """
        Send multiple emails with rate limiting.

        Args:
            messages: List of message dicts with to_email, from_email, subject, body
            rate_limit: Max emails per batch
            dry_run: If True, don't actually send

        Returns:
            List of send results
        """
        results = []

        for i, msg in enumerate(messages[:rate_limit]):
            result = self.send_email(
                to_email=msg["to_email"],
                from_email=msg["from_email"],
                subject=msg["subject"],
                body=msg["body"],
                from_name=msg.get("from_name"),
                reply_to=msg.get("reply_to"),
                html_body=msg.get("html_body"),
                dry_run=dry_run,
            )
            results.append(result)

            # Add small delay between sends to avoid rate limiting
            if not dry_run and i < len(messages) - 1:
                import time
                time.sleep(0.5)  # 500ms between sends

        return results

    # -------------------------------------------------------------------------
    # Email Formatting
    # -------------------------------------------------------------------------

    def text_to_html(self, text: str) -> str:
        """Convert plain text to simple HTML."""
        # Escape HTML entities
        html = text.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")

        # Convert line breaks
        html = html.replace("\n\n", "</p><p>").replace("\n", "<br>")

        # Wrap in paragraph tags
        html = f"<p>{html}</p>"

        # Wrap in basic HTML structure
        return f"""<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body style="font-family: Arial, sans-serif; font-size: 14px; line-height: 1.6; color: #333;">
    {html}
</body>
</html>"""

    def _inject_tracking_pixel(self, html: str, message_id: str) -> str:
        """Inject tracking pixel into HTML email."""
        tracking_domain = self.email_config.get("tracking", {}).get("tracking_domain", "")
        if not tracking_domain:
            return html

        pixel = f'<img src="https://{tracking_domain}/track/open/{message_id}" width="1" height="1" style="display:none;" />'

        # Insert before </body> or at end
        if "</body>" in html.lower():
            html = html.replace("</body>", f"{pixel}</body>")
            html = html.replace("</BODY>", f"{pixel}</BODY>")
        else:
            html += pixel

        return html

    # -------------------------------------------------------------------------
    # Validation
    # -------------------------------------------------------------------------

    def validate_config(self) -> dict:
        """Validate email configuration."""
        issues = []

        if self.provider == "smtp":
            if not self.smtp_host:
                issues.append("SMTP host not configured")
            if not self.smtp_username:
                issues.append("SMTP username not configured")
            if not self.smtp_password:
                issues.append("SMTP password not configured")

        return {
            "valid": len(issues) == 0,
            "issues": issues,
            "provider": self.provider,
        }

    def test_connection(self) -> dict:
        """Test SMTP connection."""
        if not self.smtp_host:
            return {"success": False, "error": "SMTP not configured"}

        try:
            context = ssl.create_default_context()
            with smtplib.SMTP(self.smtp_host, self.smtp_port, timeout=10) as server:
                if self.use_tls:
                    server.starttls(context=context)
                if self.smtp_username and self.smtp_password:
                    server.login(self.smtp_username, self.smtp_password)

            return {"success": True, "error": None}

        except Exception as e:
            return {"success": False, "error": str(e)}

    # -------------------------------------------------------------------------
    # Domain Health (placeholder)
    # -------------------------------------------------------------------------

    def check_domain_health(self, domain: str) -> dict:
        """
        Check email domain health (SPF, DKIM, DMARC).
        Placeholder - would use DNS checks in real implementation.
        """
        return {
            "domain": domain,
            "spf": "unknown",
            "dkim": "unknown",
            "dmarc": "unknown",
            "health_score": 0,
            "message": "Domain health check not implemented",
        }
