from database_handler import DbConn
from flask import jsonify
from werkzeug.security import check_password_hash, generate_password_hash
from flask_jwt_extended import create_access_token, get_jwt_identity

from datetime import timedelta
from src.validators.user_validator import ValidateUser


conn = DbConn()
cur = conn.create_connection()
class UserController:

    """User controller interfaces with the database."""

    def __init__(self):
        """Initializes the user controller class."""
        conn.create_users_table()
        if not self.check_admin_exists:
            conn.create_default_admin()

    def create_user(self, data):
        """Creates a user.
        Arguments:
          data {[email, username, password, role ]} --
          [Signup details needed]
        """
        sql = """INSERT INTO users(email, username, password, role)
                    VALUES ('{}', '{}', '{}', '{}')"""

        hashed_password = generate_password_hash(data['password'], '<PASSWORD>')

        sql_command = sql.format(data['email'],
                                 data['username'],
                                 hashed_password,
                                 data['role'])
        cur.execute(sql_command)

    def register_user_controller(self, data):
        validate = ValidateUser(data)
        is_valid = validate.is_valid()

        if is_valid == "valid":
            if not self.check_duplicate_email(data['email']):
                if not self.check_duplicate_username(data['username']):
                    self.create_user(data)
                    return jsonify({"message":
                                    "user registered successfully"}), 201
                return jsonify({"message": "Username already exists"}), 400
            return jsonify({"message": "Email already exists"}), 400
        return jsonify({"message": is_valid}), 400

    def get_role(self, data):
        sql = """SELECT role FROM users WHERE username = '{}'"""
        cur.execute(sql.format(data['username']))
        role = cur.fetchone()
        if role:
            return role

    def login_user(self, data):
        """Logs in a user

        Arguments:
          data {[username, password ]} -- [Login credentials needed]
        """
        sql = """SELECT username,password FROM users WHERE username='{}'"""
        validate = ValidateUser(data)
        is_valid = validate.validate_login()
        if is_valid == "valid":
            role = self.get_role(data)
            identity = {
                'username': data['username'],
                'role': role
            }
            expires = timedelta(hours=23)
            cur.execute(sql.format(data['username']))
            db_user = cur.fetchone()
            if not db_user:
                return jsonify({'message': 'No user found'}), 404
            if not check_password_hash(db_user[1], data['password']):
                return jsonify({'message': 'Invalid password'}), 400
            else:
                access_token = create_access_token(
                    identity=identity, expires_delta=expires)
                return jsonify({'message': 'successfully logged in',
                                'token': access_token
                                }), 200
        else:
            return jsonify({"message": is_valid}), 400

    def check_duplicate_email(self, the_email):
        '''
            checks the email submitted by user
            during registration to see if it already exists
        '''

        sql_email = """SELECT email FROM users WHERE email='{}'"""
        cur.execute(sql_email.format(the_email))
        db_email = cur.fetchone()
        if db_email:
            return True
        else:
            return False

    def check_duplicate_username(self, the_username):
        '''
            checks the email submitted by user
            during registration to see if it already exists
        '''

        sql_username = """SELECT username FROM users WHERE username='{}'"""
        cur.execute(sql_username.format(the_username))
        db_username = cur.fetchone()
        if db_username:
            return True
        else:
            return False

    def get_user_profile_details(self, data):
        sql = """SELECT * FROM users WHERE username = '{}'"""
        cur.execute(sql.format(data['username']))
        profile_details = cur.fetchone()
        if profile_details:
            return profile_details

    #pylint: disable=no-self-use
    def check_admin_user(self):
        """Checks the logged in user is an admin"""
        role = get_jwt_identity()['role'][0]
        if role == 'Admin':
            return True
        else:
            return False

    def check_admin_exists(self):
        sql = """SELECT * FROM users WHERE email='{}' and username='{}'"""
        self.cur.execute(sql.format('<EMAIL>', 'Admin'))
        row = self.cur.fetchone()
        print(row)
        if row:
            return True
        else:
            return False

from database_handler import DbConn
from flask import jsonify
from werkzeug.security import check_password_hash, generate_password_hash
from flask_jwt_extended import create_access_token, get_jwt_identity

from datetime import timedelta
from src.validators.user_validator import ValidateUser


conn = DbConn()
cur = conn.create_connection()
class UserController:

    """User controller interfaces with the database."""

    def __init__(self):
        """Initializes the user controller class."""
        conn.create_users_table()
        if not self.check_admin_exists:
            conn.create_default_admin()

    def create_user(self, data):
        """Creates a user.
        Arguments:
          data {[email, username, password, role ]} --
          [Signup details needed]
        """
        sql = """INSERT INTO users(email, username, password, role)
                    VALUES ('{}', '{}', '{}', '{}')"""

        hashed_password = generate_password_hash(data['password'], '<PASSWORD>')

        sql_command = sql.format(data['email'],
                                 data['username'],
                                 hashed_password,
                                 data['role'])
        cur.execute(sql_command)

    def register_user_controller(self, data):
        validate = ValidateUser(data)
        is_valid = validate.is_valid()

        if is_valid == "valid":
            if not self.check_duplicate_email(data['email']):
                if not self.check_duplicate_username(data['username']):
                    self.create_user(data)
                    return jsonify({"message":
                                    "user registered successfully"}), 201
                return jsonify({"message": "Username already exists"}), 400
            return jsonify({"message": "Email already exists"}), 400
        return jsonify({"message": is_valid}), 400

    def get_role(self, data):
        sql = """SELECT role FROM users WHERE username = '{}'"""
        cur.execute(sql.format(data['username']))
        role = cur.fetchone()
        if role:
            return role

    def login_user(self, data):
        """Logs in a user

        Arguments:
          data {[username, password ]} -- [Login credentials needed]
        """
        sql = """SELECT username,password FROM users WHERE username='{}'"""
        validate = ValidateUser(data)
        is_valid = validate.validate_login()
        if is_valid == "valid":
            role = self.get_role(data)
            identity = {
                'username': data['username'],
                'role': role
            }
            expires = timedelta(hours=23)
            cur.execute(sql.format(data['username']))
            db_user = cur.fetchone()
            if not db_user:
                return jsonify({'message': 'No user found'}), 404
            if not check_password_hash(db_user[1], data['password']):
                return jsonify({'message': 'Invalid password'}), 400
            else:
                access_token = create_access_token(
                    identity=identity, expires_delta=expires)
                return jsonify({'message': 'successfully logged in',
                                'token': access_token
                                }), 200
        else:
            return jsonify({"message": is_valid}), 400

    def check_duplicate_email(self, the_email):
        '''
            checks the email submitted by user
            during registration to see if it already exists
        '''

        sql_email = """SELECT email FROM users WHERE email='{}'"""
        cur.execute(sql_email.format(the_email))
        db_email = cur.fetchone()
        if db_email:
            return True
        else:
            return False

    def check_duplicate_username(self, the_username):
        '''
            checks the email submitted by user
            during registration to see if it already exists
        '''

        sql_username = """SELECT username FROM users WHERE username='{}'"""
        cur.execute(sql_username.format(the_username))
        db_username = cur.fetchone()
        if db_username:
            return True
        else:
            return False

    def get_user_profile_details(self, data):
        sql = """SELECT * FROM users WHERE username = '{}'"""
        cur.execute(sql.format(data['username']))
        profile_details = cur.fetchone()
        if profile_details:
            return profile_details

    #pylint: disable=no-self-use
    def check_admin_user(self):
        """Checks the logged in user is an admin"""
        role = get_jwt_identity()['role'][0]
        if role == 'Admin':
            return True
        else:
            return False

    def check_admin_exists(self):
        sql = """SELECT * FROM users WHERE email='{}' and username='{}'"""
        self.cur.execute(sql.format('<EMAIL>', 'Admin'))
        row = self.cur.fetchone()
        print(row)
        if row:
            return True
        else:
            return False

User controller interfaces with the database. Initializes the user controller class. Creates a user.         Arguments:           data {[email, username, password, role ]} --           [Signup details needed] INSERT INTO users(email, username, password, role)                     VALUES ('{}', '{}', '{}', '{}') SELECT role FROM users WHERE username = '{}' Logs in a user          Arguments:           data {[username, password ]} -- [Login credentials needed] SELECT username,password FROM users WHERE username='{}' checks the email submitted by user             during registration to see if it already exists SELECT email FROM users WHERE email='{}' checks the email submitted by user             during registration to see if it already exists SELECT username FROM users WHERE username='{}' SELECT * FROM users WHERE username = '{}' #pylint: disable=no-self-use Checks the logged in user is an admin SELECT * FROM users WHERE email='{}' and username='{}'