"""
Security related functions including user credential authentication and JWT based authentication integration.

:copyright: Copyright 2013-2017, Dorian Pula <dorian.pula@amber-penguin-software.ca>
:license: AGPL v3+
"""

import collections
import logging

import flask
from werkzeug import security

from rookeries import database, errors
from rookeries.users import models
from rookeries.vendors import flask_jwt

Credentials = collections.namedtuple('Credentials', ['username', 'password'])
ADMIN_USERNAME = 'ADMIN_USERNAME'
ADMIN_PASSWORD = 'ADMIN_PASSWORD'
DEFAULT_JWT_SECRET_KEY = 'problematic_penguins'

jwt = flask_jwt.JWT()
logger = logging.getLogger(__name__)


@jwt.authentication_handler
def valid_admin_user_credentials(username, password):
    """Checks if the supplied password matches the stored password hash."""
    # TODO: Attach DB to Flask app context.
    db = database.CouchDB.configure_from_env()
    found_user = db.find_first_document({
        'type': models.User.doc_type(),
        'username': username,
    })

    if not found_user:
        raise errors.InvalidCredentialsError(username)

    user = models.User(**found_user)
    if security.check_password_hash(user.password, password):
        return user.to_json()
    else:
        raise errors.InvalidCredentialsError(username)


@jwt.identity_handler
def load_user(payload):
    user = models.User.query.filter_by(id=payload['identity']).first_or_404()
    return user.to_json()


@jwt.auth_response_handler
def jwt_token_response(access_token, identity):
    response = {
        'access_token': access_token.decode(encoding="utf-8"),
        'username': identity['username']
    }
    return flask.jsonify(response)
