"""
Settings and configuration models.
Stores user preferences and API keys in encrypted database.
"""

import enum

from sqlalchemy import (
    JSON,
    Boolean,
    Column,
    Enum,
    Float,
    Integer,
    String,
    Text,
)
from sqlalchemy_utc import UtcDateTime, utcnow

from .base import Base


class UserSettings(Base):
    """
    User-specific settings stored in their encrypted database.
    Replaces the need for config files or unencrypted storage.
    """

    __tablename__ = "user_settings"

    id = Column(Integer, primary_key=True)
    key = Column(String(255), unique=True, nullable=False, index=True)
    value = Column(JSON)
    category = Column(String(100))
    description = Column(Text)
    created_at = Column(UtcDateTime, default=utcnow())
    updated_at = Column(UtcDateTime, default=utcnow(), onupdate=utcnow())

    def __repr__(self):
        return f"<UserSettings(key='{self.key}', category='{self.category}')>"


class APIKey(Base):
    """
    Encrypted storage for API keys.
    These are especially sensitive and benefit from database encryption.
    """

    __tablename__ = "api_keys"

    id = Column(Integer, primary_key=True)
    provider = Column(String(100), unique=True, nullable=False, index=True)
    key = Column(Text, nullable=False)  # Encrypted by SQLCipher
    description = Column(Text)
    is_active = Column(Boolean, default=True)
    created_at = Column(UtcDateTime, default=utcnow())
    updated_at = Column(UtcDateTime, default=utcnow(), onupdate=utcnow())
    last_used = Column(UtcDateTime)
    usage_count = Column(Integer, default=0)

    def __repr__(self):
        # Never show the actual key in repr
        return f"<APIKey(provider='{self.provider}', active={self.is_active})>"


class SettingType(str, enum.Enum):
    """Types of settings.

    Inherits from ``str`` so that instances are JSON-serializable and work
    seamlessly with both SQLAlchemy columns and Pydantic models.
    """

    APP = "app"
    CHAT = "chat"
    LLM = "llm"
    SEARCH = "search"
    REPORT = "report"
    DATABASE = "database"


class Setting(Base):
    """
    Global application settings (shared across users).
    For user-specific settings, use UserSettings.
    """

    __tablename__ = "settings"

    id = Column(Integer, primary_key=True)
    key = Column(String(255), nullable=False, unique=True, index=True)
    value = Column(JSON, nullable=True)
    type = Column(Enum(SettingType), nullable=False, index=True)
    name = Column(String(255), nullable=False)
    description = Column(Text, nullable=True)
    category = Column(String(100), nullable=True, index=True)
    ui_element = Column(String(50), default="text", nullable=False)
    options = Column(JSON, nullable=True)  # For select elements
    min_value = Column(Float, nullable=True)  # For numeric inputs
    max_value = Column(Float, nullable=True)  # For numeric inputs
    step = Column(Float, nullable=True)  # For sliders
    visible = Column(Boolean, default=True, nullable=False)
    editable = Column(Boolean, default=True, nullable=False)
    env_var = Column(String(255), nullable=True)  # Environment variable name
    created_at = Column(UtcDateTime, server_default=utcnow(), nullable=False)
    updated_at = Column(
        UtcDateTime, server_default=utcnow(), onupdate=utcnow(), nullable=False
    )

    # unique=True on the key column already creates a unique constraint;
    # the separate UniqueConstraint was removed to avoid Alembic autogenerate drift.

    def __repr__(self):
        return f"<Setting(key='{self.key}', type={self.type.value})>"
