"""Controller and routes for users."""
import os
import logger
from flask import request, jsonify
from api import app, mongo, flask_bcrypt, jwt
from api.schemas import (validate_user_authentication, validate_user_registration)
from flask_jwt_extended import (create_access_token, create_refresh_token,
                                jwt_required, jwt_refresh_token_required, get_jwt_identity,
                                set_access_cookies, set_refresh_cookies, unset_jwt_cookies)


ROOT_PATH = os.environ.get('ROOT_PATH')
LOG = logger.get_root_logger(__name__, filename=os.path.join(ROOT_PATH, 'output.log'))

LOG.info("Loaded api.controllers.user.py")


@jwt.unauthorized_loader
def unauthorized_response(callback):
    return jsonify({
        'ok': False,
        'message': 'Missing Authorization'
    }), 401


@app.route('/auth', methods=['POST'])  # login/authentification route
def auth_user():
    ''' auth endpoint '''
    data = validate_user_authentication(request.get_json())
    if data['ok']:
        data = data['data']
        user = mongo.db.users.find_one({'email': data['email']})
        if user and flask_bcrypt.check_password_hash(user['password'], data['password']): #check for user and password
            del user['password']
            # Copy roles and id from user to JWT
            data['roles'] = user['roles']
            data['_id'] = user['_id']
            access_token = create_access_token(identity=data)
            refresh_token = create_refresh_token(identity=data)
            resp = jsonify({'ok': True, 'roles': user['roles']})
            # resp.set_cookie('roles', str(user['roles']), 
            #                 samesite="strict", 
            #                 secure=os.environ.get('ENV') == 'production')
            set_access_cookies(resp, access_token)
            set_refresh_cookies(resp, refresh_token)
            return resp, 200
        else:
            return jsonify({'ok': False, 'message': 'invalid username or password'}), 401
    else:
        return jsonify({'ok': False, 'message': 'Bad request parameters: {}'.format(data['message'])}), 400


@app.route('/register', methods=['POST'])  # registering a new user
def register():
    ''' register user endpoint '''
    data = validate_user_registration(request.get_json())  # check if received data valid and in required format
    if data['ok']:
        data = data['data']
        data['password'] = <PASSWORD>.generate_password_hash(
            data['password'])  # encrypt password
        data['roles'] = ['member']
        mongo.db.users.insert_one(data)  # store data in db
        return jsonify({'ok': True, 'message': 'User created successfully!'}), 200
    else:
        return jsonify({'ok': False, 'message': 'Bad request parameters: {}'.format(data['message'])}), 400


@app.route('/refresh', methods=['POST'])
@jwt_refresh_token_required
def refresh():
    ''' refresh token endpoint '''
    current_user = get_jwt_identity()
    access_token = create_access_token(identity=current_user)

    # Set the access JWT and CSRF double submit protection cookies
    # in this response
    resp = jsonify({'refresh': True})
    set_access_cookies(resp, access_token)
    return resp, 200


@app.route('/logout', methods=['POST'])
def logout():
    resp = jsonify({'ok': True, 'roles': []})
    unset_jwt_cookies(resp)
    return resp, 200


@app.route('/api/user', methods=['GET', 'DELETE', 'PATCH'])
@jwt_required
def user():
    ''' route read user '''
    if request.method == 'GET':
        query = request.args
        data = mongo.db.users.find_one(query, {"_id": 0})
        return jsonify({'ok': True, 'data': data}), 200

    data = request.get_json()
    if request.method == 'DELETE':
        if data.get('email', None) is not None:
            db_response = mongo.db.users.delete_one({'email': data['email']})
            if db_response.deleted_count == 1:
                response = {'ok': True, 'message': 'record deleted'}
            else:
                response = {'ok': True, 'message': 'no record found'}
            return jsonify(response), 200
        else:
            return jsonify({'ok': False, 'message': 'Bad request parameters!'}), 400

    if request.method == 'PATCH':
        if data.get('query', {}) != {}:
            mongo.db.users.update_one(
                data['query'], {'$set': data.get('payload', {})})
            return jsonify({'ok': True, 'message': 'record updated'}), 200
        else:
            return jsonify({'ok': False, 'message': 'Bad request parameters!'}), 400
