#!/usr/bin/env /usr/pgadmin4/venv/bin/python3
import sys
import click
import sqlite3
from flask import current_app
from werkzeug.local import LocalProxy
from flask_security.utils import config_value, hash_password
from flask_security.signals import password_changed

sys.path.insert(0, '/usr/pgadmin4/web')

from pgadmin import create_app
from pgadmin.model import User


@click.group()
def cli():
    pass


@click.group()
def user():
    pass


@user.command('show')
@click.argument('name')
@click.option('--attributes', '-a', multiple=True, help='Attribut à afficher pour l’utilisateur (utilisable plusieurs fois)')
@click.option('--by_id', '-i', is_flag=True, help='Drapeau indiquant si l’utilisateur est recherché par son id dans la base')
def show_user_entry(name, attributes, by_id):
    """Affichage des informations de l’utilisateur."""
    def print_attributes(user, attributes):
        if not attributes:
            attributes = [a for a in User.__dict__ if not a.startswith('_')]
        if len(attributes) == 1:
            print(getattr(user, attributes[0]))
        else:
            print('\n'.join(['{}: {}'.format(attribute, getattr(user, attribute)) for attribute in attributes]))
    try:
        app = create_app('-cli')
    except:
        return False
    with app.app_context():
        if by_id:
            user = User.query.get(name)
        else:
            user = User.query.filter_by(username=name).first()
        print_attributes(user, attributes)


@user.command('username')
@click.argument('name')
@click.argument('username')
@click.option('--by_id', '-i', is_flag=True)
def change_user_username(name, username, by_id):
    """Modification du nom de l’utilisateur."""
    try:
        app = create_app('-cli')
    except:
        return False
    with app.app_context():
        _security = LocalProxy(lambda: current_app.extensions["security"])
        _datastore = LocalProxy(lambda: _security.datastore)
        if by_id:
            user = User.query.get(name)
        else:
            user = User.query.filter_by(username=name).first()
        if user:
            user.username = username
            _datastore.set_uniquifier(user)
            _datastore.put(user)
            _datastore.commit()
        else:
            raise Exception(f'No such user {name}')


@user.command('email')
@click.argument('name')
@click.argument('email')
@click.option('--by_id', '-i', is_flag=True)
def change_user_email(name, email, by_id):
    """Modification du courriel de l’utilisateur."""
    try:
        app = create_app('-cli')
    except:
        return False
    with app.app_context():
        _security = LocalProxy(lambda: current_app.extensions["security"])
        _datastore = LocalProxy(lambda: _security.datastore)
        if by_id:
            user = User.query.get(name)
        else:
            user = User.query.filter_by(username=name).first()
        if user:
            user.email = email
            _datastore.set_uniquifier(user)
            _datastore.put(user)
            _datastore.commit()
        else:
            raise Exception(f'No such user {name}')


@user.command('password')
@click.argument('name')
@click.argument('password')
@click.option('--by_id', '-i', is_flag=True)
def change_user_password(name, password, by_id):
    """Modification du mot de passe de l’utilisateur."""
    try:
        app = create_app('-cli')
    except:
        return False
    with app.app_context():
        _security = LocalProxy(lambda: current_app.extensions["security"])
        _datastore = LocalProxy(lambda: _security.datastore)
        if by_id:
            user = User.query.get(name)
        else:
            user = User.query.filter_by(username=name).first()
        if user:
            user.password = hash_password(password)
            _datastore.set_uniquifier(user)
            _datastore.put(user)
            _datastore.commit()
            password_changed.send(current_app._get_current_object(), user=user)
        else:
            raise Exception(f'No such user {name}')


if __name__ == '__main__':
    cli.add_command(user)
    cli()
