import enum

from sqlalchemy import (
    JSON,
    Boolean,
    Column,
    DateTime,
    Enum,
    Float,
    ForeignKey,
    Integer,
    String,
    Text,
    UniqueConstraint,
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func

Base = declarative_base()


class ResearchMode(enum.Enum):
    QUICK = "quick"
    DETAILED = "detailed"


class ResearchStatus(enum.Enum):
    PENDING = "pending"
    IN_PROGRESS = "in_progress"
    COMPLETED = "completed"
    FAILED = "failed"
    CANCELLED = "cancelled"


class Research(Base):
    __tablename__ = "research"

    id = Column(Integer, primary_key=True, index=True)
    query = Column(String, nullable=False)
    status = Column(
        Enum(ResearchStatus), default=ResearchStatus.PENDING, nullable=False
    )
    mode = Column(Enum(ResearchMode), default=ResearchMode.QUICK, nullable=False)
    created_at = Column(DateTime, server_default=func.now(), nullable=False)
    updated_at = Column(
        DateTime, server_default=func.now(), onupdate=func.now(), nullable=False
    )
    progress = Column(Float, default=0.0, nullable=False)
    start_time = Column(DateTime, nullable=True)
    end_time = Column(DateTime, nullable=True)
    error_message = Column(Text, nullable=True)

    # Relationships
    report = relationship(
        "ResearchReport",
        back_populates="research",
        uselist=False,
        cascade="all, delete-orphan",
    )


class ResearchReport(Base):
    __tablename__ = "research_report"

    id = Column(Integer, primary_key=True, index=True)
    research_id = Column(
        Integer,
        ForeignKey("research.id", ondelete="CASCADE"),
        nullable=False,
        unique=True,
    )
    content = Column(Text, nullable=True)
    created_at = Column(DateTime, server_default=func.now(), nullable=False)
    updated_at = Column(
        DateTime, server_default=func.now(), onupdate=func.now(), nullable=False
    )
    report_metadata = Column(
        JSON, nullable=True
    )  # Additional metadata about the report

    # Relationships
    research = relationship("Research", back_populates="report")


class SettingType(enum.Enum):
    APP = "app"
    LLM = "llm"
    SEARCH = "search"
    REPORT = "report"


class Setting(Base):
    """Database model for storing settings"""

    __tablename__ = "settings"

    id = Column(Integer, primary_key=True, index=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)
    created_at = Column(DateTime, server_default=func.now(), nullable=False)
    updated_at = Column(
        DateTime, server_default=func.now(), onupdate=func.now(), nullable=False
    )

    __table_args__ = (UniqueConstraint("key", name="uix_settings_key"),)
