from typing import Optional

from loguru import logger

from app.lib import models, utils

from datetime import datetime
from typing import Optional

from shortuuid import ShortUUID
from sqlmodel import Field, SQLModel, create_engine, Session, select

engine = create_engine(
    utils.settings.DB_URI,
    echo=True,
    connect_args={"check_same_thread": False}
)


def create_db_and_tables():
    SQLModel.metadata.create_all(engine)
    logger.info("Created tables")


def get_conn():
    with Session(engine, expire_on_commit=False) as session:
        yield session

s = ShortUUID(alphabet="0123456789")


def generate_suid():
    return s.random(length=21)


class UserBase(SQLModel):
    id: str = Field(primary_key=True, min_length=21, max_length=21)
    name: str = Field(nullable=False)
    email: str = Field(unique=True, index=True)
    display: Optional[str] = Field(default=None)

    is_verified: bool = Field(default=False)
    is_active: bool = Field(default=True)

    @staticmethod
    def read(conn: Session, count: int = 1, **kwargs):
        query = select(User)
        for key, value in kwargs.items():
            query = query.where(getattr(User, key) == value)
        matches = conn.exec(query).all()
        return matches if count == -1 else matches[:count]

    def save(self, conn: Session):
        try:
            conn.add(self)
            conn.commit()
            conn.refresh(self)
            return self
        except Exception as e:
            logger.error(f"Failed to save user {self!r}: {e!r}")
            return None


class UserCreate(UserBase):
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)


class User(UserBase, table=True):
    created_at: datetime = Field(nullable=False)
    updated_at: datetime = Field(nullable=False)


def create_user(conn: Session, user: UserCreate) -> User:
    db_user = User.model_validate(user)
    conn.add(db_user)
    conn.commit()
    conn.refresh(db_user)
    return db_user

def read_user_by_email(conn: Session, email: str) -> User:
    query = select(User).where(User.email == email)
    return conn.exec(query).first()
