# Path: auth.py
# class Auth:
#     def login_required(*args, **kwargs):
#     def current_user(self):
#     def init_app(app):
# def load_user(user_id):
# def load_user_from_request(request):
# 
# Path: models.py
# class User(BaseModel, UserMixin):
#     """
#     User represents an user for the application.
# 
#     Attributes:
#         first_name (str): User's first name
#         last_name (str): User's last name
#         email (str): User's **valid** email
#         password (str): User's password
#         admin (bool): User's admin status. Defaults to ``False``
# 
#     .. NOTE::
#         Each User resource must have an unique `email` field, meaning
#         that there cannot be two user's registered with the same email.
# 
#         For this reason, when checking for user's existence, the server requires
#         either the `uuid` of the user or its `email`.
#     """
#     uuid = UUIDField(unique=True)
#     first_name = CharField()
#     last_name = CharField()
#     email = CharField(unique=True)
#     password = CharField()
#     admin = BooleanField(default=False)
#     _schema = UserSchema
# 
#     @staticmethod
#     def exists(email):
#         """
#         Check that an user exists by checking the email field.
# 
#         Args:
#             email (str): User's email to check
#         """
#         try:
#             User.get(User.email == email)
#         except User.DoesNotExist:
#             return False
#         return True
# 
#     @staticmethod
#     def hash_password(password):
#         """
#         Use passlib to get a crypted password.
# 
#         Args:
#             password (str): password to hash
# 
#         Returns:
#             str: hashed password
#         """
#         return pbkdf2_sha256.hash(password)
# 
#     def verify_password(self, password):
#         """
#         Verify a clear password against the stored hashed password of the user
#         using passlib.
# 
#         Args:
#             password (str): Password to verify against the hashed stored password
#         Returns:
#             bool: wether the given email matches the stored one
#         """
#         return pbkdf2_sha256.verify(password, self.password)
# 
#     def add_favorite(user, item):
#         """Link the favorite item to user."""
#         return Favorite.create(
#             uuid=uuid4(),
#             item=item,
#             user=user,
#         )
# 
#     def delete_favorite(self, obj):
#         obj.delete_instance()
# 
# Path: utils.py
# def generate_response(data, status, mimetype='application/vnd.api+json'):
#     """
#     Given a resource model that extends from `BaseModel` generate a Reponse
#     object to be returned from the application endpoints'
#     """
#     return Response(
#         response=data,
#         status=status,
#         mimetype=mimetype
#     )
# 
# Path: notifications.py
# def notify_new_user(first_name, last_name):
#     body = render_template('new_user.html', first_name=first_name, last_name=last_name)
#     send_email("Nuovo Utente", body)


from flask import request
from flask_restful import Resource
from http.client import (CREATED, NO_CONTENT, OK,
                         BAD_REQUEST, CONFLICT, UNAUTHORIZED)
from auth import auth
from models import User
from utils import generate_response
from notifications import notify_new_user
import uuid


class UsersHandler(Resource):
    """
    Handler for main user endpoint.

    Implements:
    * `get` method to retrieve the list of all the users
    * `post` method to add a new user to the database.
    """
    @auth.login_required
    def get(self):
        if not auth.current_user.admin:
            return ({'message': "You can't get the list users."}, UNAUTHORIZED)

        data = User.json_list(User.select())
        return generate_response(data, OK)

    def post(self):
        """ Add an user to the database."""
        data = request.get_json(force=True)

        errors = User.validate_input(data)
        if errors:
            return errors, BAD_REQUEST

        # Extract the user attributes to check and generate the User row
        data = data['data']['attributes']

        # If email is present in the database return a BAD_REQUEST response.

# Path: auth.py
# class Auth:
#     def login_required(*args, **kwargs):
#     def current_user(self):
#     def init_app(app):
# def load_user(user_id):
# def load_user_from_request(request):
# 
# Path: models.py
# class User(BaseModel, UserMixin):
#     """
#     User represents an user for the application.
# 
#     Attributes:
#         first_name (str): User's first name
#         last_name (str): User's last name
#         email (str): User's **valid** email
#         password (str): User's password
#         admin (bool): User's admin status. Defaults to ``False``
# 
#     .. NOTE::
#         Each User resource must have an unique `email` field, meaning
#         that there cannot be two user's registered with the same email.
# 
#         For this reason, when checking for user's existence, the server requires
#         either the `uuid` of the user or its `email`.
#     """
#     uuid = UUIDField(unique=True)
#     first_name = CharField()
#     last_name = CharField()
#     email = CharField(unique=True)
#     password = CharField()
#     admin = BooleanField(default=False)
#     _schema = UserSchema
# 
#     @staticmethod
#     def exists(email):
#         """
#         Check that an user exists by checking the email field.
# 
#         Args:
#             email (str): User's email to check
#         """
#         try:
#             User.get(User.email == email)
#         except User.DoesNotExist:
#             return False
#         return True
# 
#     @staticmethod
#     def hash_password(password):
#         """
#         Use passlib to get a crypted password.
# 
#         Args:
#             password (str): password to hash
# 
#         Returns:
#             str: hashed password
#         """
#         return pbkdf2_sha256.hash(password)
# 
#     def verify_password(self, password):
#         """
#         Verify a clear password against the stored hashed password of the user
#         using passlib.
# 
#         Args:
#             password (str): Password to verify against the hashed stored password
#         Returns:
#             bool: wether the given email matches the stored one
#         """
#         return pbkdf2_sha256.verify(password, self.password)
# 
#     def add_favorite(user, item):
#         """Link the favorite item to user."""
#         return Favorite.create(
#             uuid=uuid4(),
#             item=item,
#             user=user,
#         )
# 
#     def delete_favorite(self, obj):
#         obj.delete_instance()
# 
# Path: utils.py
# def generate_response(data, status, mimetype='application/vnd.api+json'):
#     """
#     Given a resource model that extends from `BaseModel` generate a Reponse
#     object to be returned from the application endpoints'
#     """
#     return Response(
#         response=data,
#         status=status,
#         mimetype=mimetype
#     )
# 
# Path: notifications.py
# def notify_new_user(first_name, last_name):
#     body = render_template('new_user.html', first_name=first_name, last_name=last_name)
#     send_email("Nuovo Utente", body)


# Path: views/user.py
from flask import request
from flask_restful import Resource
from http.client import (CREATED, NO_CONTENT, OK,
                         BAD_REQUEST, CONFLICT, UNAUTHORIZED)
from auth import auth
from models import User
from utils import generate_response
from notifications import notify_new_user
import uuid



class UsersHandler(Resource):
    """
    Handler for main user endpoint.

    Implements:
    * `get` method to retrieve the list of all the users
    * `post` method to add a new user to the database.
    """
    @auth.login_required
    def get(self):
        if not auth.current_user.admin:
            return ({'message': "You can't get the list users."}, UNAUTHORIZED)

        data = User.json_list(User.select())
        return generate_response(data, OK)

    def post(self):
        """ Add an user to the database."""
        data = request.get_json(force=True)

        errors = User.validate_input(data)
        if errors:
            return errors, BAD_REQUEST

        # Extract the user attributes to check and generate the User row
        data = data['data']['attributes']

        # If email is present in the database return a BAD_REQUEST response.

        if User.exists(data['email']):