class PasswordReset(db.Model):
    id: int
    user_id: int
    code: str

    __tablename__ = "password_resets"
    __bind_key__ = "app"
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False)
    code = db.Column(db.String)
class CachedRange(db.Model):
    id: int
    low: int
    high: int
    type: str

    __tablename__ = "cached_ranges"
    __bind_key__ = "data"
    id = db.Column(db.Integer, primary_key=True)
    low = db.Column(db.Integer)
    high = db.Column(db.Integer)
    type = db.Column(db.String)
class Session(db.Model):
    id: int
    token: str
    user_id: int
    expiration: int

    __tablename__ = "sessions"
    __bind_key__ = "app"
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False)
    token = db.Column(db.String(16), nullable=False)
    expiration = db.Column(db.Integer, nullable=False)

    user = db.relationship("User", back_populates="sessions")
class Trigger(db.Model):
    id: int
    follow_id: int
    time_window: str
    threshold: int
    notifications: List['Notification']

    __tablename__ = "triggers"
    __bind_key__ = "app"
    id = db.Column(db.Integer, primary_key=True)
    follow_id = db.Column(db.Integer, db.ForeignKey("follows.id"), nullable=False)
    time_window = db.Column(db.String, nullable=False)
    threshold = db.Column(db.Integer, nullable=False)
    notifications = db.relationship("Notification", back_populates='trigger', cascade="all, delete", lazy=True)

    follow = db.relationship("Follow", back_populates='triggers')
class Follow(db.Model):
    id: int
    user_id: int
    type: FollowType
    target: str
    notify_email: bool
    triggers: List['Trigger']

    __tablename__ = "follows"
    __bind_key__ = "app"
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False)
    type = db.Column(db.Enum(FollowType), nullable=False)
    target = db.Column(db.String, nullable=False)
    notify_email = db.Column(db.Boolean, nullable=False, default=False)
    triggers = db.relationship("Trigger", back_populates="follow", cascade="all, delete", lazy=True)

    user = db.relationship("User", back_populates="follows")
class User(db.Model):
    id: int
    username: str
    email: str
    password: str
    salt: str
    follows: List['Follow']
    sessions: List['Session']

    __tablename__ = "users"
    __bind_key__ = "app"
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String, unique=True, nullable=False)
    email = db.Column(db.String, unique=True, nullable=False)
    password = db.Column(db.String, nullable=False)
    salt = db.Column(db.String(16), nullable=False)
    follows = db.relationship("Follow", back_populates="user", cascade="all, delete", lazy=True)
    sessions = db.relationship("Session", back_populates="user", cascade="all, delete", lazy=True)
    notifications = db.relationship("Notification", cascade="all, delete")
class Price(db.Model):
    id: int
    coin_type: CoinType
    price: float
    time: int
    volume: float
    type: str

    __tablename__ = "prices"
    __bind_key__ = "data"
    id = db.Column(db.Integer, primary_key=True)
    coin_type = db.Column(db.Enum(CoinType))
    price = db.Column(db.Float)
    time = db.Column(db.Integer)
    volume = db.Column(db.Float)
    type = db.Column(db.String)
class Notification(db.Model):
    id: int
    user_id: int
    trigger_id: int
    content: str
    time: int
    read: bool

    __tablename__ = "notifications"
    __bind_key__ = "app"
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False)
    trigger_id = db.Column(db.Integer, db.ForeignKey("triggers.id"), nullable=True)
    content = db.Column(db.Text)
    time = db.Column(db.Integer, nullable=False)
    read = db.Column(db.Boolean, nullable=False, default=False)

    trigger = db.relationship("Trigger", back_populates="notifications")
class StreamedPost(db.Model):
    id: int
    coin_type: CoinType
    user: str
    content: str
    source: str
    time: int

    __tablename__ = "streamed_posts"
    __bind_key__ = "stream"
    id = db.Column(db.Integer, primary_key=True)
    coin_type = db.Column(db.Enum(CoinType))
    user = db.Column(db.String)
    content = db.Column(db.Text)
    source = db.Column(db.String)
    time = db.Column(db.Integer)

    def copy(self):
        return dataclasses.replace(self)
class Post(db.Model):
    id: int
    coin_type: CoinType
    user: str
    content: str
    source: str
    interaction: int
    time: int
    unique_id: str
    impact: bytes
    avg_impact: float
    type: str

    __tablename__ = "posts"
    __bind_key__ = "data"
    id = db.Column(db.Integer, primary_key=True)
    coin_type = db.Column(db.Enum(CoinType))
    user = db.Column(db.String)
    content = db.Column(db.Text)
    source = db.Column(db.String)
    interaction = db.Column(db.Integer)
    time = db.Column(db.Integer)
    unique_id = db.Column(db.String)
    impact = db.Column(db.LargeBinary, default=b'')
    avg_impact = db.Column(db.Float, default=0.0)
    type = db.Column(db.String)

    def copy(self):
        return dataclasses.replace(self)