from flask import render_template, flash, redirect, request, url_for, session, Blueprint
from flask_login import login_required, current_user, login_user
from forms import RegisterForm, UpdateUserPass, UpdateUser
from passlib.hash import sha256_crypt
from db_manager import db, User, Actions, get_user_by_username, VirtualMachine
import secrets
import os

user_blueprint = Blueprint('user', __name__)


@user_blueprint.route('/logout')
@login_required
def logout():
    session.clear()
    flash('Вы вышли из системы', 'success')
    return redirect(url_for('index'))


@user_blueprint.route('/register', methods=['GET', 'POST'])
def register():
    if (os.environ.get('REGISTER_OFF')).lower() == 'false':
        form = RegisterForm(request.form)
        if request.method == 'POST' and form.validate():
            name = form.name.data
            email = form.email.data
            username = form.username.data
            password = sha256_crypt.hash(str(form.password.data))

            existing_user = User.query.filter_by(username=username).first()
            existing_email = User.query.filter_by(email=email).first()

            if existing_user:
                flash('Пользователь с таким именем уже существует.', 'danger')
                return redirect(url_for('user.register'))

            if existing_email:
                flash('Пользователь с таким email уже существует.', 'danger')
                return redirect(url_for('user.register'))

            new_user = User(name=name, email=email, username=username, password=password, is_admin=False)

            new_user.token = secrets.token_hex(16)

            db.session.add(new_user)
            db.session.commit()

            flash('Теперь вы зарегистрированы и можете войти. Добро пожаловать в PrintumVMs!!', 'success')

            return redirect(url_for('user.login'))

        return render_template('register.html', form=form)
    else:
        return render_template('register_off.html', img='/static/image/stop.png')


@user_blueprint.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password_candidate = request.form['password']
        users = User.query.filter_by(username=username).first()

        if users and sha256_crypt.verify(password_candidate, users.password):
            session['logged_in'] = True
            session['username'] = username
            session['names'] = users.name
            session['user_ip'] = request.remote_addr
            session['is_admin'] = users.is_admin

            users.last_successful_entry = datetime.now()
            users.last_address = session['user_ip']
            db.session.commit()

            login_user(users)

            new_action = Actions(user_id=get_user_by_username(username).id,
                                 action_type='login_user',
                                 action_info=request.remote_addr)
            db.session.add(new_action)
            db.session.commit()

            flash('Вы успешно авторизовались', 'success')

            return redirect(url_for('index'))
        else:
            flash('Неверное имя пользователя или пароль', 'danger')
            return render_template('login.html')

    return render_template('login.html')


@user_blueprint.route('/update_user_info', methods=['GET', 'POST'])
@login_required
def update_user_info():
    if request.method == 'POST':

        form = UpdateUser(request.form)

        if form.validate():
            current_user.name = form.name.data
            current_user.user_information = form.user_information.data

            db.session.commit()
            flash('Информация о пользователе успешно обновлена.', 'success')
        else:
            flash('Ошибка при обновлении информации о пользователе.', 'danger')

        return redirect(url_for('index'))

    users = User.query.filter_by(username=session['username']).first()

    return render_template('edit_info.html', user=users)


@user_blueprint.route('/update_pass', methods=['GET', 'POST'])
@login_required
def update_pass():
    if request.method == 'POST':

        form = UpdateUserPass(request.form)

        if form.new_password.data and form.validate():
            current_user.password = sha256_crypt.hash(str(form.new_password.data))

            db.session.commit()
            flash('Пароль именён!.', 'success')
        else:
            flash('Ошибка смены пароля!.', 'danger')

        return redirect(url_for('index'))

    users = User.query.filter_by(username=session['username']).first()

    return render_template('edit_pass.html', user=users)


@user_blueprint.route('/delete_user/<string:username>', methods=['POST'])
@login_required
def delete_user(username):
    if current_user.is_admin:
        user_to_delete = User.query.filter_by(username=username).first()

        if user_to_delete:
            db.session.delete(user_to_delete)
            db.session.commit()
            flash('Пользователь успешно удален.', 'success')
            return redirect(url_for('admin'))
        else:
            flash('Ошибка при удалении пользователя.', 'danger')
            return redirect(url_for('admin'))
    else:
        flash('🔔 Вы не администратор! 🔔', 'danger')
        return redirect(url_for('index'))


@user_blueprint.route('/user_info/<string:username>', methods=['GET'])
@login_required
def user_info(username):
    if current_user.is_admin:
        page = request.args.get('page', 1, type=int)
        user = User.query.filter_by(username=username).first()
        user_data = db.session.query(Actions, VirtualMachine.name, VirtualMachine.hyper) \
            .outerjoin(VirtualMachine, Actions.vm == VirtualMachine.id) \
            .filter(Actions.user_id == user.id) \
            .order_by(Actions.action_timestamp.desc()) \
            .paginate(page=page, per_page=50)

        return render_template('user_info.html', user_data=user_data, user_pg=user.username)
    else:
        flash('🔔 Вы не администратор! 🔔', 'danger')
        return redirect(url_for('index'))
