# -*- coding: utf-8 -*-


import flask
import datetime
import json
from flask_jwt_extended import jwt_required, create_access_token, get_current_user, create_refresh_token, jwt_refresh_token_required
from pritunl_dedicated.blueprints import api_user
from pritunl_dedicated.models.pritunl_dedicated import User
from pritunl_dedicated.extensions import db
from pritunl_dedicated.views.api import filter_to_sqlalchemy, sort_to_sqlalchemy


__author__ = "Adam Schubert"
__date__ = "$18.8.2014 23:33:05$"


@api_user.route('', methods=['GET'], defaults={'page': 1})
@api_user.route('/page/<int:page>', methods=['GET'])
@jwt_required
def get_users(page: int):

    order_by = sort_to_sqlalchemy(
        User,
        flask.request.args.get('sort_field'),
        int(flask.request.args.get('sort_order', 1)),
        {
            'first_name': 'first_name',
            'last_name': 'last_name',
            'username': 'username'
        },
        'created'
    )

    users = User.query.order_by(order_by)

    per_page = int(flask.request.args['per_page']) if 'per_page' in flask.request.args else users.count()
    filters = json.loads(flask.request.args['filters']) if 'filters' in flask.request.args else {}
    users_filter = filter_to_sqlalchemy(
        User,
        filters,
        {
            'first_name': 'first_name',
            'last_name': 'last_name',
            'username': 'username'
        }
    )

    paginator = users.filter(*users_filter).paginate(page, per_page)

    data_ret = []
    for user in paginator.items:
        data_ret.append(user.jsonify())

    ret = {
        'has_next': paginator.has_next,
        'has_prev': paginator.has_prev,
        'next_num': paginator.next_num,
        'prev_num': paginator.prev_num,
        'page': paginator.page,
        'pages': paginator.pages,
        'per_page': paginator.per_page,
        'total': paginator.total,
        'data': data_ret,
        'next': flask.url_for('api.user.get_users', page=paginator.next_num, _external=True),
        'prev': flask.url_for('api.user.get_users', page=paginator.prev_num, _external=True)
    }

    return flask.jsonify(ret), 200


@api_user.route('', methods=['PUT'])
@jwt_required
def set_user():
    user_id = flask.request.json.get('id')
    username = flask.request.json.get('username')
    first_name = flask.request.json.get('first_name')
    last_name = flask.request.json.get('last_name')
    password = flask.request.json.get('password')

    user_found = User.query.filter_by(id=user_id).first()
    if not user_found:
        return flask.jsonify({'message': 'User not found'}), 404

    user_username_found = User.query.filter_by(username=username).first()
    if user_username_found and user_username_found != user_found:
        return flask.jsonify({'message': 'User username found'}), 409

    user_found.username = username
    user_found.first_name = first_name
    user_found.last_name = last_name
    if password:
        user_found.set_password(password)
    db.session.add(user_found)
    db.session.commit()

    return flask.jsonify(user_found.jsonify()), 200


@api_user.route('', methods=['POST'])
@jwt_required
def create_user():
    username = flask.request.json.get('username')
    first_name = flask.request.json.get('first_name')
    last_name = flask.request.json.get('last_name')
    password = flask.request.json.get('password')

    user_found = User.query.filter_by(username=username).first()
    if user_found:
        return flask.jsonify({'message': 'This username already exists'}), 409

    new_user = User()
    new_user.username = username
    new_user.first_name = first_name
    new_user.last_name = last_name
    new_user.set_password(password)
    db.session.add(new_user)
    db.session.commit()

    return flask.jsonify(new_user.jsonify()), 200


@api_user.route('/<int:user_id>', methods=['DELETE'])
@jwt_required
def delete_user(user_id: int):
    user_found = User.query.filter_by(id=user_id).first()
    if not user_found:
        return flask.jsonify({'message': 'User not found'}), 404
    db.session.delete(user_found)
    db.session.commit()
    return flask.jsonify(user_found.jsonify()), 200


@api_user.route('/<int:user_id>', methods=['GET'])
@jwt_required
def get_user(user_id: int):
    user_found = User.query.filter_by(id=user_id).first()
    if not user_found:
        return flask.jsonify({'message': 'User not found'}), 404

    return flask.jsonify(user_found.jsonify()), 200


@api_user.route('/authenticate', methods=['POST'])
def authenticate():
    username = flask.request.json.get('username')
    password = flask.request.json.get('password')

    user_found = User.query.filter_by(username=username).first()
    if not user_found:
        return flask.jsonify({'message': 'User not found'}), 404

    if not user_found.check_password(password):
        return flask.jsonify({'message': 'Wrong password'}), 401

    data = user_found.jsonify()

    data['access_token'] = create_access_token(identity=data)
    data['refresh_token'] = create_refresh_token(identity=data)
    if flask.current_app.config.get('JWT_ACCESS_TOKEN_EXPIRES'):
        access_token_expires = datetime.datetime.now(datetime.timezone.utc) + flask.current_app.config.get('JWT_ACCESS_TOKEN_EXPIRES')
        data['access_token_expires'] = access_token_expires.isoformat()
    else:
        data['access_token_expires'] = None

    if flask.current_app.config.get('JWT_REFRESH_TOKEN_EXPIRES'):
        access_token_expires = datetime.datetime.now(datetime.timezone.utc) + flask.current_app.config.get('JWT_REFRESH_TOKEN_EXPIRES')
        data['refresh_token_expires'] = access_token_expires.isoformat()
    else:
        data['refresh_token_expires'] = None

    return flask.jsonify(data), 200


@api_user.route('/refresh', methods=['POST'])
@jwt_refresh_token_required
def refresh():
    current_user = get_current_user()
    data = current_user.jsonify()
    data['access_token'] = create_access_token(identity=data)
    data['refresh_token'] = create_refresh_token(identity=data)
    if flask.current_app.config.get('JWT_ACCESS_TOKEN_EXPIRES'):
        access_token_expires = datetime.datetime.now(datetime.timezone.utc) + flask.current_app.config.get(
            'JWT_ACCESS_TOKEN_EXPIRES')
        data['access_token_expires'] = access_token_expires.isoformat()
    else:
        data['access_token_expires'] = None

    if flask.current_app.config.get('JWT_REFRESH_TOKEN_EXPIRES'):
        access_token_expires = datetime.datetime.now(datetime.timezone.utc) + flask.current_app.config.get(
            'JWT_REFRESH_TOKEN_EXPIRES')
        data['refresh_token_expires'] = access_token_expires.isoformat()
    else:
        data['refresh_token_expires'] = None
    return flask.jsonify(data), 200


@api_user.route('/forgot-password', methods=['POST'])
def forgot_password():
    username = flask.request.json.get('username')
    user_found = User.query.filter_by(username=username).first()
    if not user_found:
        return flask.jsonify({'message': 'User not found'}), 404

    # @TODO send email

    return flask.jsonify({'message': 'Email with recovery information was send'}), 200

"""
@api_user.route("/log-out")
@jwt_required
def log_out():
    logout_user()
    return flask.jsonify({'message': 'Logged out'}), 200
"""
