from rest_framework.request import Request

from django.http import HttpResponseBadRequest, HttpResponse, JsonResponse, HttpRequest

from .models import User, AuthToken

import ipware as iplib, time, requests, uuid
ipware = iplib.IpWare();

def client_ip(req: HttpRequest):
    return ipware.get_client_ip(req.META)[0].exploded;

def register(oid, provider_id, name):
    user = User(
        favorites_apartments='',    
        comparison_apartments='', 
        name=name, 
        about_me='', 
        gender='?', 
        role='s', 
        photo_provider='VVSU', 
        openid_addr=oid, 
        openid_id=provider_id, 
    );
    user.save();
    return user;

def get_oauth_token(remote, data):
    return requests.post(remote + '/oauth2/token', data,
            headers={
                'Origin': 'https://pairent.vvsu.ru',
                'Referer': 'https://pairent.vvsu.ru'
            }).json();

def get_oauth_data(remote, key):
    return requests.get(remote + '/userinfo', headers={
                'Origin': 'https://pairent.vvsu.ru',
                'Authorization': 'Bearer ' + key,
                'User-Agent': 'curl/8.1'
            }).json();

def create_auth_token(userid, ip):

    try:
        token = AuthToken.objects.get(user=userid, ip=ip);
        if (verify_auth_token(token.key, token.ip)):
            return token;
    except AuthToken.DoesNotExist:
        0 # ignore

    token = AuthToken(
        user=userid,
        key=str(uuid.uuid4()),
        #                          2 days
        #                            vvv
        expires=time.time() + 60 * 60 * 24 * 2,
        ip=ip
    );
    token.save();
    return token;

def verify_auth_token(key, ip):
    
    try:
        token = AuthToken.objects.get(key=key);
    except AuthToken.DoesNotExist:
        return False;       

    if (token.ip != ip):
        token.delete();
        return False;
    
    if (token.expires < time.time()):
        token.delete();
        return False;
    
    return True;

def auth_required(func):
    """
        Use authorization for this route.
    """
    def inner(req: HttpRequest, *args, **kwargs):

        if ('Authorization' not in req.headers.keys()):
            return JsonResponse({'error': 'no auth token'});
        if (not verify_auth_token(req.headers['Authorization'], client_ip(req))):
            return JsonResponse({'error': 'auth token invalid or expired'});
        func(req, *args, **kwargs);
    
    return inner;

def rest_auth_required(func):
    """
        Use authorization for this restframework view.
    """
    def inner(self, req: HttpRequest, *args, **kwargs):
        
        if ('Authorization' not in req.headers.keys()):
            return JsonResponse({'error': 'no auth token'});
        if (not verify_auth_token(req.headers['Authorization'], client_ip(req))):
            return JsonResponse({'error': 'auth token invalid or expired'});
        func(self, req, *args, **kwargs);
    
    return inner;