from typing import List from datetime import datetime, timedelta from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from app.db.session import get_db from app.core.deps import get_current_active_user, get_current_admin_user from app.models.subscription import Subscription, SubscriptionStatus from app.models.membership import MembershipPlan from app.models.user import User from app.schemas.subscription import ( Subscription as SubscriptionSchema, SubscriptionCreate, SubscriptionUpdate, ) router = APIRouter() @router.get("/", response_model=List[SubscriptionSchema]) def read_subscriptions( skip: int = 0, limit: int = 100, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user), ): subscriptions = ( db.query(Subscription) .filter(Subscription.user_id == current_user.id) .offset(skip) .limit(limit) .all() ) return subscriptions @router.get("/{subscription_id}", response_model=SubscriptionSchema) def read_subscription( subscription_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user), ): subscription = ( db.query(Subscription) .filter( Subscription.id == subscription_id, Subscription.user_id == current_user.id ) .first() ) if not subscription: raise HTTPException(status_code=404, detail="Subscription not found") return subscription @router.post("/", response_model=SubscriptionSchema) def create_subscription( subscription_data: SubscriptionCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user), ): plan = ( db.query(MembershipPlan) .filter( MembershipPlan.id == subscription_data.membership_plan_id, MembershipPlan.is_active, ) .first() ) if not plan: raise HTTPException(status_code=404, detail="Membership plan not found") existing_active_subscription = ( db.query(Subscription) .filter( Subscription.user_id == current_user.id, Subscription.membership_plan_id == subscription_data.membership_plan_id, Subscription.status == SubscriptionStatus.ACTIVE, ) .first() ) if existing_active_subscription: raise HTTPException( status_code=400, detail="Active subscription already exists for this plan" ) start_date = datetime.utcnow() end_date = start_date + timedelta(days=plan.duration_days) subscription = Subscription( user_id=current_user.id, membership_plan_id=subscription_data.membership_plan_id, start_date=start_date, end_date=end_date, amount_paid=plan.price, status=SubscriptionStatus.PENDING, ) db.add(subscription) db.commit() db.refresh(subscription) return subscription @router.put("/{subscription_id}", response_model=SubscriptionSchema) def update_subscription( subscription_id: int, subscription_update: SubscriptionUpdate, db: Session = Depends(get_db), current_user=Depends(get_current_admin_user), ): subscription = ( db.query(Subscription).filter(Subscription.id == subscription_id).first() ) if not subscription: raise HTTPException(status_code=404, detail="Subscription not found") update_data = subscription_update.dict(exclude_unset=True) for field, value in update_data.items(): setattr(subscription, field, value) db.commit() db.refresh(subscription) return subscription @router.post("/{subscription_id}/cancel") def cancel_subscription( subscription_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user), ): subscription = ( db.query(Subscription) .filter( Subscription.id == subscription_id, Subscription.user_id == current_user.id ) .first() ) if not subscription: raise HTTPException(status_code=404, detail="Subscription not found") if subscription.status == SubscriptionStatus.CANCELLED: raise HTTPException(status_code=400, detail="Subscription already cancelled") subscription.status = SubscriptionStatus.CANCELLED db.commit() return {"message": "Subscription cancelled successfully"}