"""
Email Template Delivery Service — the missing integration layer.

Combines: template loading → published version → variable rendering → SMTP → audit log.
Used by DSR workflow, document reviews, and other modules that need to send
templated emails.
"""

import logging
import uuid
from typing import Any, Optional

from sqlalchemy.orm import Session

from compliance.db.email_template_models import (
    EmailSendLogDB,
    EmailTemplateDB,
    EmailTemplateVersionDB,
)

logger = logging.getLogger(__name__)


def _render(html: str, variables: dict[str, str]) -> str:
    """Replace {{variable}} placeholders with values."""
    result = html
    for key, value in variables.items():
        result = result.replace(f"{{{{{key}}}}}", str(value))
    return result


class EmailDeliveryService:
    """Load template → render → send via SMTP → log."""

    def __init__(self, db: Session) -> None:
        self.db = db

    def get_published_version(
        self, tenant_id: str, template_type: str,
    ) -> Optional[EmailTemplateVersionDB]:
        """Get the latest published version of a template by type."""
        tid = uuid.UUID(tenant_id)
        template = (
            self.db.query(EmailTemplateDB)
            .filter(EmailTemplateDB.tenant_id == tid, EmailTemplateDB.template_type == template_type)
            .first()
        )
        if not template:
            return None
        return (
            self.db.query(EmailTemplateVersionDB)
            .filter(
                EmailTemplateVersionDB.template_id == template.id,
                EmailTemplateVersionDB.status == "published",
            )
            .order_by(EmailTemplateVersionDB.created_at.desc())
            .first()
        )

    def send(
        self,
        tenant_id: str,
        template_type: str,
        recipient: str,
        variables: dict[str, str],
        fallback_subject: Optional[str] = None,
        fallback_html: Optional[str] = None,
    ) -> dict[str, Any]:
        """Send a templated email. Falls back to inline HTML if no published template.

        Args:
            tenant_id: Tenant UUID string.
            template_type: E.g. 'dsr_receipt', 'dsr_completion'.
            recipient: Email address.
            variables: Dict of {{key}}: value for rendering.
            fallback_subject: Subject if no template found.
            fallback_html: HTML body if no template found.
        """
        from compliance.services.smtp_sender import send_email

        tid = uuid.UUID(tenant_id)
        version = self.get_published_version(tenant_id, template_type)

        if version:
            subject = _render(version.subject, variables)
            body_html = _render(version.body_html, variables)
            version_id = version.id
        elif fallback_subject and fallback_html:
            subject = _render(fallback_subject, variables)
            body_html = _render(fallback_html, variables)
            version_id = None
        else:
            logger.warning("No published template for '%s' and no fallback provided", template_type)
            return {"success": False, "error": f"No template for {template_type}"}

        result = send_email(recipient=recipient, subject=subject, body_html=body_html)

        # Audit log
        try:
            log = EmailSendLogDB(
                tenant_id=tid,
                template_type=template_type,
                version_id=version_id,
                recipient=recipient,
                subject=subject,
                status=result.get("status", "unknown"),
                variables=variables,
                error_message=result.get("error"),
            )
            self.db.add(log)
            self.db.commit()
        except Exception as e:
            logger.warning("Failed to log email send: %s", e)

        return {
            "success": result.get("status") == "sent",
            "template_type": template_type,
            "recipient": recipient,
            "subject": subject,
            "used_template": version is not None,
            "status": result.get("status"),
        }
