from bson.objectid import ObjectId
from fastapi import APIRouter, HTTPException, Depends, status
from mongomapper.errors import DocumentNotFoundError
from app.models import User, Product, Payment, Campaign, Tip, Purchase
from app.models.data import UserData, PaymentData
from app.dependencies import get_current_user

router = APIRouter(prefix='/users')

@router.get('/')
def list_users():
  """Lists users"""
  users = User.all()
  return [user.json(include={'profile', 'created_at', 'modified_at'}) for user in users]

@router.post('/', status_code=status.HTTP_201_CREATED)
def create_user(data: UserData):
  """Creates a user"""
  # Ensures there are no other users with the same email
  if User.all(emails=data.email):
    raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Email address already in use")

  user = User.create(**data.dict())
  return user.json()

@router.get('/{user_id}')
def get_user(user_id: str):
  """Retrieves a user"""
  try: 
    user = User.get(user_id)
  except DocumentNotFoundError:
    raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
    
  return user.json(include={'profile', 'created_at', 'modified_at'})
  
@router.get('/{user_id}/campaigns')
def list_campaigns(user_id: str):
  """Lists campaigns by a user"""
  try:
    campaigns = Campaign.all(user=ObjectId(user_id))
  except DocumentNotFoundError:
    raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)

  return [campaign.json() for campaign in campaigns]

@router.get('/{user_id}/products')
def list_products(user_id: str):
  """Lists products"""
  try:
    products = Product.all(user=ObjectId(user_id))
  except DocumentNotFoundError:
    raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)

  return [product.json() for product in products]

@router.get('/{user_id}/products/{product_id}')
def get_product(user_id: str, product_id: str):
  """Retrieves a user's product"""
  try:
    product = Product.get(product_id, user=ObjectId(user_id))
  except DocumentNotFoundError:
    raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
  
  return product.json()

@router.post('/{user_id}/products/{product_id}/buy')
def buy_product(user_id: str, product_id: str, data: PaymentData, current_user: User = Depends(get_current_user)):
  """Buys a user's product"""
  try:
    product = Product.get(product_id, user=ObjectId(user_id))
  except DocumentNotFoundError:
    raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
  
  payment   = Payment.create(**data.dict())
  purchase  = Purchase.create(user=current_user, target=product, payment=payment)

  return purchase.json()

@router.post('/{user_id}/tip', status_code=status.HTTP_201_CREATED)
def tip_user(user_id: str, data: PaymentData, current_user: User = Depends(get_current_user)):
  """Tips to a user"""
  try:
    user = User.get(user_id)
  except DocumentNotFoundError:
    raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)

  # Makes sure the user is not tipping themself
  if user.reference == current_user.reference:
    raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)

  payment   = Payment.create(**data.dict())
  tip       = Tip.create(user=current_user, target=user, payment=payment)

  return tip.json()
from bson.objectid import ObjectId
from fastapi import APIRouter, HTTPException, Depends, status
from mongomapper.errors import DocumentNotFoundError
from app.models import User, Product, Payment, Campaign, Tip, Purchase
from app.models.data import UserData, PaymentData
from app.dependencies import get_current_user

router = APIRouter(prefix='/users')

@router.get('/')
def list_users():
  """Lists users"""
  users = User.all()
  return [user.json(include={'profile', 'created_at', 'modified_at'}) for user in users]

@router.post('/', status_code=status.HTTP_201_CREATED)
def create_user(data: UserData):
  """Creates a user"""
  # Ensures there are no other users with the same email
  if User.all(emails=data.email):
    raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Email address already in use")

  user = User.create(**data.dict())
  return user.json()

@router.get('/{user_id}')
def get_user(user_id: str):
  """Retrieves a user"""
  try: 
    user = User.get(user_id)
  except DocumentNotFoundError:
    raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
    
  return user.json(include={'profile', 'created_at', 'modified_at'})
  
@router.get('/{user_id}/campaigns')
def list_campaigns(user_id: str):
  """Lists campaigns by a user"""
  try:
    campaigns = Campaign.all(user=ObjectId(user_id))
  except DocumentNotFoundError:
    raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)

  return [campaign.json() for campaign in campaigns]

@router.get('/{user_id}/products')
def list_products(user_id: str):
  """Lists products"""
  try:
    products = Product.all(user=ObjectId(user_id))
  except DocumentNotFoundError:
    raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)

  return [product.json() for product in products]

@router.get('/{user_id}/products/{product_id}')
def get_product(user_id: str, product_id: str):
  """Retrieves a user's product"""
  try:
    product = Product.get(product_id, user=ObjectId(user_id))
  except DocumentNotFoundError:
    raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
  
  return product.json()

@router.post('/{user_id}/products/{product_id}/buy')
def buy_product(user_id: str, product_id: str, data: PaymentData, current_user: User = Depends(get_current_user)):
  """Buys a user's product"""
  try:
    product = Product.get(product_id, user=ObjectId(user_id))
  except DocumentNotFoundError:
    raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
  
  payment   = Payment.create(**data.dict())
  purchase  = Purchase.create(user=current_user, target=product, payment=payment)

  return purchase.json()

@router.post('/{user_id}/tip', status_code=status.HTTP_201_CREATED)
def tip_user(user_id: str, data: PaymentData, current_user: User = Depends(get_current_user)):
  """Tips to a user"""
  try:
    user = User.get(user_id)
  except DocumentNotFoundError:
    raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)

  # Makes sure the user is not tipping themself
  if user.reference == current_user.reference:
    raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)

  payment   = Payment.create(**data.dict())
  tip       = Tip.create(user=current_user, target=user, payment=payment)

  return tip.json()
Lists users Creates a user # Ensures there are no other users with the same email Retrieves a user Lists campaigns by a user Lists products Retrieves a user's product Buys a user's product Tips to a user # Makes sure the user is not tipping themself