from datetime import UTC, datetime, timedelta from sqlalchemy import select, update from sqlalchemy.ext.asyncio import AsyncSession from db.models.subscriptions import Subscription, SubscriptionStatus class SubscriptionRepository: async def get_subscriptions_for_autorenewal( self, session: AsyncSession, *, days_before_expiry: int = 1 ) -> list[Subscription]: threshold = datetime.now(UTC) + timedelta(days=days_before_expiry) stmt = ( select(Subscription) .where( Subscription.autorenew == True, # noqa: E712 Subscription.end_date <= threshold, ) .with_for_update() ) result = await session.execute(stmt) return list(result.scalars().all()) async def get_subscription_by_user_id( self, session: AsyncSession, user_id: int ) -> Subscription | None: stmt = select(Subscription).where(Subscription.user_id == user_id) res = await session.execute(stmt) return res.scalar_one_or_none() async def create_subscription( self, session: AsyncSession, *, user_id: int, end_date: datetime, devices: int, duration_days: int, plan_price_paid: int, whitelists: bool, autorenew: bool = False, status: SubscriptionStatus = SubscriptionStatus.EXPIRED, ) -> Subscription: subscription = Subscription( user_id=user_id, end_date=end_date, autorenew=autorenew, status=status, devices=devices, whitelists=whitelists, duration_days=duration_days, plan_price_paid=plan_price_paid, ) session.add(subscription) await session.commit() return subscription async def update_sub( self, session: AsyncSession, user_id: int, *, end_date: datetime, devices: int, whitelists: bool, duration_days: int, plan_price_paid: int, autorenew: bool, status: SubscriptionStatus = SubscriptionStatus.ACTIVE, ) -> Subscription | None: stmt = ( update(Subscription) .where(Subscription.user_id == user_id) .values( end_date=end_date, autorenew=autorenew, status=status, devices=devices, whitelists=whitelists, duration_days=duration_days, plan_price_paid=plan_price_paid, ) .returning(Subscription) ) result = await session.execute(stmt) await session.commit() return result.scalar_one_or_none() async def update_subscription_autorenew( self, session: AsyncSession, user_id: int, autorenew: bool ) -> Subscription | None: stmt = ( update(Subscription) .where(Subscription.user_id == user_id) .values( autorenew=autorenew, ) .returning(Subscription) ) result = await session.execute(stmt) await session.commit() return result.scalar_one_or_none()