from app import db
from flask_bcrypt import Bcrypt
from flask import current_app
import jwt
from datetime import datetime, timedelta


class User(db.Model):
    """Maps to users table """

    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(256), nullable=False, unique=True)
    password = db.Column(db.String(256), nullable=False)
    bucketlists = db.relationship(
        'Bucketlist', order_by='Bucketlist.id', cascade="all, delete-orphan")

    def __init__(self, email, password):
        self.email = email
        self.password = Bcrypt().generate_password_hash(password).decode()

    def password_is_valid(self, password):
        """Validates user password """
        return Bcrypt().check_password_hash(self.password, password)

    def save(self):
        db.session.add(self)
        db.session.commit()

    def generate_token(self, user_id):
        """ Generates the access token"""

        try:
            payload = {
                'exp': datetime.utcnow() + timedelta(minutes=5),
                'iat': datetime.utcnow(),
                'sub': user_id
            }
            jwt_string = jwt.encode(
                payload,
                current_app.config.get('SECRET'),
                algorithm='HS256'
            )
            return jwt_string

        except Exception as e:
            return str(e)

    @staticmethod
    def decode_token(token):
        """Decode the access token from the Authorization header."""
        try:
            payload = jwt.decode(token, current_app.config.get('SECRET'))
            return payload['sub']
        except jwt.ExpiredSignatureError:
            return "Expired token. Please log in to get a new token"
        except jwt.InvalidTokenError:
            return "Invalid token. Please register or login"


class Bucketlist(db.Model):
    """This class represents the bucketlist table."""

    __tablename__ = 'bucketlists'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255))
    date_created = db.Column(db.DateTime, default=db.func.current_timestamp())
    date_modified = db.Column(
        db.DateTime, default=db.func.current_timestamp(),
        onupdate=db.func.current_timestamp())
    created_by = db.Column(db.Integer, db.ForeignKey(User.id))

    def __init__(self, name, created_by):
        """initialize with name."""
        self.name = name
        self.created_by = created_by

    def save(self):
        db.session.add(self)
        db.session.commit()

    @staticmethod
    def get_all():
        return Bucketlist.query.all()

    def delete(self):
        db.session.delete(self)
        db.session.commit()

    def __repr__(self):
        return "<Bucketlist: {}>".format(self.name)

@@ -161,15 +161,30 @@
  %22%22%22
-Maps to
+This class defines the
  use
@@ -222,24 +222,99 @@
  = 'users'%0A%0A
+    # Define the columns of the users table, starting with the primary key%0A
     id = db.
@@ -621,32 +621,96 @@
 ail, password):%0A
+        %22%22%22Initialize the user with an email and a password.%22%22%22%0A
         self.ema
@@ -854,9 +854,50 @@
  %22%22%22
-V
+Checks the password against it's hash to v
 alid
@@ -901,20 +901,26 @@
 lidates 
+the 
 user
+'s
  passwor
@@ -920,17 +920,16 @@
 password
- 
 %22%22%22%0A    
@@ -1006,32 +1006,143 @@
 def save(self):%0A
+        %22%22%22Save a user to the database.%0A        This includes creating a new user and editing one.%0A        %22%22%22%0A
         db.sessi
@@ -1233,17 +1233,16 @@
      %22%22%22
- 
 Generate
@@ -1263,25 +1263,119 @@
 oken
-%22%22%22%0A%0A        try:
+ to be used as the Authorization header%22%22%22%0A%0A        try:%0A            # set up a payload with an expiration time
 %0A   
@@ -1547,16 +1547,77 @@
       %7D%0A
+            # encode the payload to get an byte string token%0A
         
@@ -1830,16 +1830,86 @@
 n as e:%0A
+            # return an error in string format if an exception occurs%0A
         
@@ -2426,17 +2426,14 @@
 ass 
-represent
+define
 s th

document models.py