"""Render the email body as a generated image, hosted for mail clients to fetch.

HTML generation gave inconsistent layouts between sends. An image is visually
consistent and gets real iconography, at the cost of clickable links and text --
so the caller keeps the header, links and footer as HTML around it, and every
email still carries a plain-text part.

Images are uploaded to a public blob container because mail clients cannot render
base64 data URIs: Gmail strips them and Outlook ignores them.
"""
import base64
import hashlib
import logging
import time

from azure.storage.blob import BlobServiceClient, ContentSettings, PublicAccess
from openai import AzureOpenAI

from app.core.config import settings
from app.core.prompts import EMAIL_BODY_IMAGE_PROMPT

logger = logging.getLogger(__name__)

CONTAINER = "email-assets"
IMAGE_SIZE = "1024x1536"

_image_client = None


def _client():
    """The image model lives on a separate Azure resource from the chat model."""
    global _image_client
    if _image_client is None:
        if not (settings.AZURE_OPENAI_ENDPOINT_IMAGE and settings.AZURE_OPENAI_API_KEY_IMAGE):
            return None
        _image_client = AzureOpenAI(
            api_key=settings.AZURE_OPENAI_API_KEY_IMAGE,
            api_version=settings.AZURE_OPENAI_API_VERSION_IMAGE,
            azure_endpoint=settings.AZURE_OPENAI_ENDPOINT_IMAGE,
        )
    return _image_client


def image_generation_available() -> bool:
    return bool(settings.EMAIL_BODY_IMAGE and _client())


def _upload(tenant_id: str, png_bytes: bytes) -> str:
    """Upload and return a public URL, or '' if hosting is unavailable."""
    try:
        service = BlobServiceClient.from_connection_string(settings.AZURE_STORAGE_CONNECTION_STRING)
        container = service.get_blob_client(container=CONTAINER, blob="x").container_name
        if not service.get_container_client(container).exists():
            service.create_container(container, public_access=PublicAccess.BLOB)

        digest = hashlib.sha1(png_bytes).hexdigest()[:12]
        path = f"body/{tenant_id}/{int(time.time())}-{digest}.png"
        blob = service.get_blob_client(container=CONTAINER, blob=path)
        blob.upload_blob(png_bytes, overwrite=True,
                         content_settings=ContentSettings(content_type="image/png"))
        return blob.url
    except Exception as ex:
        logger.error(f"Could not host email body image: {ex}")
        return ""


def generate_body_image(*, brand, subject: str, body_text: str, tenant_id: str = None) -> dict:
    """Generate the body panel as an image. Returns {} when unavailable."""
    client = _client()
    if not client:
        return {}

    prompt = EMAIL_BODY_IMAGE_PROMPT.format(
        brand_name=brand.name,
        primary_color=brand.primary_color or "#4B4B8F",
        accent_color=brand.accent_color or "#222222",
        subject=subject,
        body_text=body_text,
    )
    started = time.time()
    try:
        result = client.images.generate(
            model=settings.AZURE_OPENAI_DEPLOYMENT_IMAGE,
            prompt=prompt, n=1, size=IMAGE_SIZE,
        )
        png = base64.b64decode(result.data[0].b64_json)
    except Exception as ex:
        logger.error(f"Email body image generation failed: {ex}")
        return {}

    url = _upload(tenant_id or "shared", png)
    if not url:
        return {}
    logger.info(f"Generated email body image in {time.time() - started:.1f}s -> {url}")
    return {"url": url, "width": 1024, "height": 1536}
