"""
DALL-E 3 Image Provider – generates images from text prompts via OpenAI.
"""

from __future__ import annotations

import asyncio
import logging
import os
from pathlib import Path
from typing import Any

import httpx

from providers.ports import ImageProvider

logger = logging.getLogger(__name__)


class DallE3ImageProvider(ImageProvider):
    """Wraps the OpenAI Images API (DALL-E 3) for image generation."""

    name = "dalle3"

    def __init__(self):
        api_key = os.getenv("OPENAI_API_KEY")
        if not api_key:
            raise EnvironmentError(
                "OPENAI_API_KEY is required for image generation. "
                "Set it in your .env file."
            )
        from openai import OpenAI

        self.client = OpenAI(api_key=api_key)
        self.model = os.getenv("IMAGE_MODEL", "dall-e-3")
        self.size = os.getenv("IMAGE_SIZE", "1792x1024")
        self.quality = os.getenv("IMAGE_QUALITY", "hd")
        self.style = os.getenv("IMAGE_STYLE", "natural")

    def _generate_sync(self, prompt: str, output_path: str | Path) -> Path:
        """Generate an image from *prompt* and save to *output_path*."""
        output_path = Path(output_path)
        output_path.parent.mkdir(parents=True, exist_ok=True)

        logger.info(
            "Generating image  model=%s  size=%s → %s",
            self.model,
            self.size,
            output_path,
        )

        response = self.client.images.generate(
            model=self.model,
            prompt=prompt,
            size=self.size,
            quality=self.quality,
            style=self.style,
            n=1,
        )

        image_url = response.data[0].url
        revised_prompt = response.data[0].revised_prompt
        logger.debug("Revised prompt: %s", revised_prompt)

        # Download the image
        img_data = httpx.get(image_url, timeout=60).content
        with open(output_path, "wb") as f:
            f.write(img_data)

        logger.info("Image saved: %s", output_path)
        return output_path

    async def generate(self, prompt: str, output_path: Path, **kwargs: Any) -> Path:
        """Generate an image asynchronously."""
        return await asyncio.to_thread(self._generate_sync, prompt, output_path)
