# -*- coding: utf-8 -*-
import os
from flask import Flask, Blueprint, abort, session, g, current_app, request, render_template, send_from_directory, jsonify, flash, redirect
from flask_login import login_user, current_user, logout_user, login_required

from user_agents import parse
from webinterface import db, bcrypt
from sqlalchemy import func
from datetime import datetime, date
from webinterface.models.system import Persona, Ipaddr, Dispositivo, Identidad, Sesion, Registro, Conexion, Ruta, Sitio, Correo
from webinterface.content.forms import mMiCuenta, LoginForm,  RequestResetForm, ResetPasswordForm
from webinterface.content.utils import clean_str, es_local

main = Blueprint('main', __name__)

if os.environ.get('COOKIE_DOMAIN'):
    systemuri = "https://app.{}/".format(os.environ.get('COOKIE_DOMAIN'))
else:
    systemuri = 'https://app.tpmc.ilab.cl/'


@main.route("/system/login", methods=['GET', 'POST'])
def login():

    if current_user.is_authenticated:
        return redirect(systemuri)

    form = LoginForm()
    if form.validate_on_submit():
        form.login.data = clean_str(form.login.data.lower().strip())
        user = Persona.query.filter(Persona.rut==form.login.data).first()
        if user and bcrypt.check_password_hash(user.clave, form.clave.data):
            login_user(user, remember=form.remember.data)
            g.user = user
            g.sesion.identidad = user
            db.session.commit()

            next_page = request.args.get('next')
            current_app.logger.info('Acceso exitoso: IP({}), USER({}), UA({})'.format(g.ip.ipaddr,form.login.data, g.dispositivo.parsed_ua))
            return redirect(next_page) if next_page else redirect(systemuri)
        else:
            flash(u'El nombre de usuario o la contraseña son incorrectos.', 'danger')
            current_app.logger.warning('Intento de ingreso fallido: IP({}), USER({}), UA({})'.format(g.ip.ipaddr,form.login.data, g.dispositivo.parsed_ua))
    return render_template('system/login.html', title='Ingreso de Usuarios del Sistema', form=form)


@main.route("/system/logout")
def logout():

    logout_user()
    session.pop('sid', None)

    return redirect('https://tpmc.ilab.cl/')

@main.route("/system/me", methods=['GET', 'POST'])
@login_required
def micuenta():
    form = mMiCuenta()

    if form.validate_on_submit():
        if form.clave.data:
            hashed_password = bcrypt.generate_password_hash(form.clave.data).decode('utf-8')
            current_user.clave = hashed_password

        trimmed = form.correo.data.strip().lower()

        correo = Correo.query.filter_by(correo=trimmed).first()
        if correo is None:
            correo = Correo(correo=trimmed, cuenta=current_user)

        current_user.correodefecto=correo
        current_user.telefono = form.fono.data.replace(" ", "")
        db.session.commit()

        flash(u'Los datos de tu cuenta han sido actualizados.', 'success')
        return redirect(url_for('main.micuenta'))

    elif request.method == 'GET':

        if current_user.correodefecto is not None:
            form.correo.data = current_user.correodefecto.correo

        form.id.data = current_user.id
        form.login.data = current_user.rut
        form.nombrecompleto.data = current_user.nombrecompleto
        form.fono.data = current_user.telefono

    return render_template('system/me.html', title='Mi Cuenta', form=form)


@main.before_app_request
def registra_sesion():
    if request.headers.getlist("X-Forwarded-For"):
        remote_ip = request.headers.getlist("X-Forwarded-For")[0]
    else:
        remote_ip = request.environ['REMOTE_ADDR']
    uadata = parse(request.user_agent.string)

    ip = Ipaddr.query.filter_by(ipaddr=remote_ip).one_or_none()
    if ip is None:
        ip = Ipaddr(ipaddr=remote_ip)
        db.session.add(ip)
        db.session.commit()

    if 'sid' in session:
        sesion = Sesion.query.filter_by(id=session['sid']).one_or_none()
        if sesion is None:
            session.pop('sid', None)
        else:
            dispositivo = Dispositivo.query.filter_by(id=sesion.dispositivoid, parsed_ua=str(uadata)).one_or_none()
            if dispositivo is None:
                session.pop('sid', None)
            else:
                conexion = Conexion.query.filter_by(ipaddrid=ip.id, sesionid=sesion.id).one_or_none()
                Ident = sesion.identidad
                if conexion is None:
                    conexion = Conexion(ipaddr=ip, sesion=sesion)
                    db.session.add(conexion)
                    db.session.commit()

    if 'sid' not in session:

        dispositivo = Dispositivo.query.filter_by(useragent=request.user_agent.string).one_or_none()
        if dispositivo is None:
            dev = uadata.is_pc and "PC" or uadata.device.family
            os = ("%s %s" % (uadata.os.family, uadata.os.version_string)).strip()
            browser = ("%s %s" % (uadata.browser.family, uadata.browser.version_string)).strip()

            dispositivo = Dispositivo(useragent=request.user_agent.string, dev=dev , os=os , browser=browser, parsed_ua=str(uadata))
            db.session.add(dispositivo)
            db.session.commit()

        if uadata.is_bot:
            Ident = Identidad.query.filter_by(login='Buscador').one()
        elif es_local(remote_ip):
            Ident = Identidad.query.filter_by(login='Intranet').one()
        else:
            Ident = Identidad.query.filter_by(login='Internet').one()

        sesion = Sesion(identidad=Ident, dispositivo=dispositivo)
        db.session.add(sesion)
        db.session.commit()

        conexion = Conexion(ipaddr=ip, sesion=sesion)
        db.session.add(conexion)
        db.session.commit()


# agregamos el registro asociado a la solicitud actual
# a la sesion que esta actualmente cargada. Dejamos la sesion guardada en
# la variable global g.

    if '/reset_password' in str(request.path):
        rpth = '/reset_password'
    else:
        rpth = str(request.path)

    solicitud = Ruta.query.filter_by(ruta=rpth).first()
    if solicitud is None:
        solicitud = Ruta(ruta=str(request.path))
        db.session.add(solicitud)
        db.session.commit()

    host = Sitio.query.filter_by(sitio=request.host).first()
    if host is None:
        host = Sitio(sitio=request.host)
        db.session.add(host)
        db.session.commit()

    tamano = int(request.headers.get('Content-Length') or 0)

    now = datetime.now()

    registro = Registro(sitio=host, ruta=solicitud, sesion=sesion, ipaddr=ip, tamano=tamano)
    db.session.add(registro)
    db.session.commit()

    conexion.ultimo = now
    sesion.ultimo = now
    db.session.commit()

    g.ip = ip
    g.user = Ident
    g.sesion = sesion
    g.conexion = conexion
    g.registro = registro
    g.dispositivo = dispositivo
    session['sid'] = g.sesion.id
