from typing import List, Optional

from pydantic import BaseModel, ConfigDict, Field, model_validator


class GenerateAiImageRequest(BaseModel):
    model_config = ConfigDict(populate_by_name=True)

    system_prompt: str = Field(default="", description="System prompt sent to the Responses API")
    user_prompt: str = Field(default="", description="User prompt sent to the Responses API")
    language: Optional[str] = Field(
        default=None,
        description="Language for all visible text in the generated image, e.g. Macedonian, Bulgarian, English",
    )
    content: Optional[str] = Field(
        default=None,
        description="Visible text/content that should be written in the requested language with correct grammar and spelling",
    )
    logo_image_url: str = Field(..., min_length=1, description="Public logo image URL sent as an input_image")
    reference_image_url: Optional[str] = Field(default=None, description="Single public reference image URL")
    reference_image_url_2: Optional[str] = Field(default=None, description="Second optional public reference image URL")
    reference_image_urls: List[str] = Field(default_factory=list, description="Additional public reference image URLs")
    city: Optional[str] = Field(default=None, description="Optional city identifier for analytics")
    zavedenia_id: Optional[int] = Field(default=None, description="Optional Zavedenia restaurant identifier for analytics")
    model: Optional[str] = Field(default=None, description="Optional OpenAI model override")
    image_size: Optional[str] = Field(default=None, description="Optional image_generation size override")
    image_quality: Optional[str] = Field(default=None, description="Optional image_generation quality override")
    mock_data: bool = Field(default=False, description="If true, skip OpenAI and return a mock base64 image")

    @property
    def selected_model(self) -> Optional[str]:
        return self.model.strip() if self.model and self.model.strip() else None

    @model_validator(mode="before")
    @classmethod
    def apply_aliases(cls, data):
        if not isinstance(data, dict):
            return data

        mapped = data.copy()
        aliases = {
            "system_prompt": ("systemPrompt",),
            "user_prompt": ("userPrompt", "prompt"),
            "language": ("targetLanguage", "target_language"),
            "content": ("textContent", "text_content", "visibleText", "visible_text"),
            "logo_image_url": ("logoImageUrl", "logo"),
            "reference_image_url": ("referenceImageUrl", "referenceImage"),
            "reference_image_url_2": ("referenceImageUrl2", "reference_image_2", "referenceImage2"),
            "reference_image_urls": ("referenceImageUrls", "referenceImages"),
            "zavedenia_id": ("zavedeniaId", "zId", "z_id"),
            "image_size": ("imageSize", "size"),
            "image_quality": ("imageQuality", "quality"),
            "mock_data": ("mockData",),
        }
        for canonical, names in aliases.items():
            if canonical not in mapped:
                for name in names:
                    if name in mapped:
                        mapped[canonical] = mapped[name]
                        break

        if "city" not in mapped and "City" in mapped:
            mapped["city"] = mapped["City"]

        return mapped

    @model_validator(mode="after")
    def normalize_reference_images(self):
        self.system_prompt = (self.system_prompt or "").strip()
        self.user_prompt = (self.user_prompt or "").strip()

        urls: List[str] = []
        if self.reference_image_url and self.reference_image_url.strip():
            urls.append(self.reference_image_url.strip())
        if self.reference_image_url_2 and self.reference_image_url_2.strip():
            urls.append(self.reference_image_url_2.strip())
        for image_url in self.reference_image_urls:
            if image_url and image_url.strip():
                urls.append(image_url.strip())

        deduped = list(dict.fromkeys(urls))
        self.reference_image_urls = deduped
        self.reference_image_url = deduped[0] if deduped else None
        self.reference_image_url_2 = deduped[1] if len(deduped) > 1 else None
        return self
