from typing import Literal

from pydantic import BaseModel, EmailStr, Field, field_validator, model_validator


SettingsSource = Literal["database", "environment", "missing"]


def normalize_text(value: object) -> str:
    if value is None:
        return ""
    return str(value).strip()


class SmtpSettingsResponse(BaseModel):
    host: str = ""
    port: int = 587
    username: str = ""
    password_is_set: bool = False
    from_email: str = ""
    from_name: str = "Funktechnik Schubert"
    use_tls: bool = True
    enabled: bool = False
    source: SettingsSource


class SmtpSettingsUpdate(BaseModel):
    host: str = Field(default="", max_length=255)
    port: int = Field(default=587, ge=1, le=65535)
    username: str = Field(default="", max_length=255)
    password: str | None = Field(default=None, max_length=1000)
    from_email: str = Field(default="", max_length=255)
    from_name: str = Field(default="Funktechnik Schubert", max_length=255)
    use_tls: bool = True
    enabled: bool = False

    @field_validator("host", "username", "password", "from_email", "from_name", mode="before")
    @classmethod
    def normalize_strings(cls, value: object) -> str:
        return normalize_text(value)

    @model_validator(mode="after")
    def validate_enabled_configuration(self):
        if self.enabled and (not self.host or not self.from_email):
            raise ValueError("SMTP Host und Absenderadresse sind erforderlich, wenn SMTP aktiviert ist")
        return self


class SmtpTestRequest(BaseModel):
    recipient: EmailStr


class SmtpTestResponse(BaseModel):
    success: bool
    message: str
    source: SettingsSource


class PublicLinksSettingsResponse(BaseModel):
    repair_status_base_url: str = ""
    source: SettingsSource


class PublicLinksSettingsUpdate(BaseModel):
    repair_status_base_url: str = Field(default="", max_length=500)

    @field_validator("repair_status_base_url", mode="before")
    @classmethod
    def normalize_url(cls, value: object) -> str:
        return normalize_text(value).rstrip("/")
