from __future__ import annotations

from contextlib import contextmanager
from datetime import datetime, timezone
from pathlib import Path
from typing import Iterator

from sqlalchemy import Column, DateTime, Integer, String, Text, create_engine
from sqlalchemy.orm import declarative_base, sessionmaker, Session

Base = declarative_base()


def utc_now() -> datetime:
    return datetime.now(timezone.utc)


class ClipboardEvent(Base):
    __tablename__ = "clipboard_events"

    id = Column(Integer, primary_key=True)
    timestamp = Column(DateTime(timezone=True), default=utc_now, nullable=False)
    hostname = Column(String(255), nullable=False)
    action = Column(String(32), nullable=False)
    content = Column(Text, nullable=False)


def ensure_directory(path: Path) -> None:
    path.parent.mkdir(parents=True, exist_ok=True)


def create_session_factory(db_path: Path):
    ensure_directory(db_path)
    engine = create_engine(
        f"sqlite:///{db_path}",
        connect_args={"check_same_thread": False},
        future=True,
    )
    Base.metadata.create_all(engine)
    return sessionmaker(bind=engine, autoflush=False, autocommit=False, future=True)


@contextmanager
def session_scope(session_factory) -> Iterator[Session]:
    session: Session | None = None
    try:
        session = session_factory()
        yield session
        session.commit()
    except Exception:
        if session is not None:
            session.rollback()
        raise
    finally:
        if session is not None:
            session.close()
