from pyramid.httpexceptions import HTTPFound
from pyramid.response import Response
from pyramid.security import remember, forget

from pyramid.view import view_config
import transaction
from brewman import groupfinder
from brewman.models.auth import User, Client

@view_config(route_name='logout')
def logout(request):
    request.session.invalidate()
    headers = forget(request)
    return HTTPFound(location=request.route_url('home'), headers=headers)


@view_config(request_method='POST', route_name='api_login', renderer='json')
def login(request):
    username = request.json_body.get('username', None)
    password = request.json_body.get('password', None)
    found, user = User.auth(username, password)

    client = request.cookies.get('ClientID', None)
    otp = request.json_body.get('otp', None)
    client_name = request.json_body.get('ClientName', None)
    allowed, response = check_client(client, otp, client_name, user if found else None)

    if found and allowed:
        headers = remember(request, str(user.id))
        request.response.headers = headers
        if allowed and isinstance(response, Client):
            request.response.set_cookie('ClientID', value=str(response.code), max_age=10 * 365 * 24 * 60 * 60)
        return request.response
    elif not found:
        response = Response("Login failed")
        response.status_int = 403
        return response
    else:
        return response


def check_client(client, otp, client_name, user):
    client = None if client is None else Client.by_code(client)
    outside_login_allowed = False if user is None else True if 'Clients' in groupfinder(user.id, None) else False

    if len(Client.enabled_list()) == 0 and outside_login_allowed:
        client = Client.create()
        client.otp = None
        client.name = 'Created on login by ' + user.name
        client.enabled = True
        transaction.commit()
        return True, client

    if client is None:
        if outside_login_allowed:
            client = Client.create()
            transaction.commit()
            return True, client
        else:
            client = Client.create()
            response = Response("Unknown Client")
            response.status_int = 403
            response.set_cookie('ClientID', value=str(client.code), max_age=10 * 365 * 24 * 60 * 60)
            transaction.commit()
            return False, response

    if client.enabled or outside_login_allowed:
        return True, None

    if client.otp is None:
        response = Response("Client is Forbidden")
        response.status_int = 403
        return False, response

    if otp is None:
        response = Response("OTP not supplied")
        response.status_int = 403
        return False, response
    elif client.otp != int(otp):
        response = Response("OTP is wrong")
        response.status_int = 403
        return False, response
    else:
        client.otp = None
        client.enabled = True
        client.name = client_name
        transaction.commit()
        return True, None
