from typing import Any, Dict, List, Optional

from pydantic import BaseModel, ConfigDict, field_validator

from ...database.models.settings import SettingType


class BaseSetting(BaseModel):
    """Base model for all settings"""

    key: str
    value: Any
    type: SettingType
    name: str
    description: Optional[str] = None
    category: Optional[str] = None
    ui_element: Optional[str] = "text"  # text, select, checkbox, slider, etc.
    options: Optional[List[Dict[str, Any]]] = None  # For select elements
    min_value: Optional[float] = None  # For numeric inputs
    max_value: Optional[float] = None  # For numeric inputs
    step: Optional[float] = None  # For sliders
    visible: bool = True
    editable: bool = True

    model_config = ConfigDict(from_attributes=True)


class LLMSetting(BaseSetting):
    """LLM-specific settings"""

    type: SettingType = SettingType.LLM

    @field_validator("key")
    def validate_llm_key(cls, v):
        # Ensure LLM settings follow a convention
        if not v.startswith("llm."):
            return f"llm.{v}"
        return v


class SearchSetting(BaseSetting):
    """Search-specific settings"""

    type: SettingType = SettingType.SEARCH

    @field_validator("key")
    def validate_search_key(cls, v):
        # Ensure search settings follow a convention
        if not v.startswith("search."):
            return f"search.{v}"
        return v


class ReportSetting(BaseSetting):
    """Report generation settings"""

    type: SettingType = SettingType.REPORT

    @field_validator("key")
    def validate_report_key(cls, v):
        # Ensure report settings follow a convention
        if not v.startswith("report."):
            return f"report.{v}"
        return v


class AppSetting(BaseSetting):
    """Application-wide settings"""

    type: SettingType = SettingType.APP

    @field_validator("key")
    def validate_app_key(cls, v):
        # Ensure app settings follow a convention
        if not v.startswith("app."):
            return f"app.{v}"
        return v


class ChatSetting(BaseSetting):
    """Chat-mode settings (chat.* keys).

    Mirrors the other typed wrappers so chat settings retain their
    ``SettingType.CHAT`` type and ``category="chat"`` when they pass
    through the settings UI save/edit cycle. Without this class, chat
    keys were misclassified as ``AppSetting`` by the manager's prefix
    dispatch and lost their category on save.
    """

    type: SettingType = SettingType.CHAT

    @field_validator("key")
    def validate_chat_key(cls, v):
        if not v.startswith("chat."):
            return f"chat.{v}"
        return v


class SettingsGroup(BaseModel):
    """A group of related settings"""

    name: str
    description: Optional[str] = None
    settings: List[BaseSetting]
