import json
from django.conf import settings as django_settings
from django.shortcuts import render, redirect
from django.http import JsonResponse
from django.contrib.auth.models import User
from django.contrib.auth import login as django_login, logout as django_logout
from django.views.decorators.csrf import csrf_exempt
from django.urls import reverse

from .models import ZKPProfile
from .zkp_utils import ZKPVerifier, get_prime, get_generator


def register_view(request):
    if request.method == 'GET':
        return render(request, 'django_zkp_auth/register.html', {
            'prime_p': get_prime(),
            'generator_g': get_generator(),
        })

    if request.method == 'POST':
        data = json.loads(request.body)
        username = data.get('username')
        public_key = data.get('public_key')

        if User.objects.filter(username=username).exists():
            return JsonResponse({'status': 'error', 'message': 'Username already exists'})

        user = User.objects.create_user(username=username, password=None)
        ZKPProfile.objects.create(user=user, public_key=public_key)

        return JsonResponse({'status': 'success', 'redirect': reverse('django_zkp_auth:login')})


def login_view(request):
    return render(request, 'django_zkp_auth/login.html', {
        'prime_p': get_prime(),
        'generator_g': get_generator(),
    })


def logout_view(request):
    django_logout(request)
    redirect_url = getattr(django_settings, 'ZKP_LOGOUT_REDIRECT_URL', '/')
    return redirect(redirect_url)


# --- Interactive ZKP Authentication API ---

@csrf_exempt
def zkp_challenge(request):
    """
    Steps 1–2: Client sends username + commitment t.
    Server generates challenge c, stores state in session, returns c.
    """
    if request.method == 'POST':
        data = json.loads(request.body)
        username = data.get('username')
        commitment_t = int(data.get('commitment_t'))

        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            return JsonResponse({'status': 'error', 'message': 'User not found'})

        challenge_c = ZKPVerifier.generate_challenge()

        request.session['auth_zkp_user_id'] = user.id
        request.session['auth_zkp_commitment_t'] = commitment_t
        request.session['auth_zkp_challenge_c'] = challenge_c

        return JsonResponse({'status': 'challenge_issued', 'challenge_c': challenge_c})


@csrf_exempt
def zkp_verify(request):
    """
    Steps 3–5: Client sends proof response s.
    Server verifies g^s == t * y^c (mod p) and logs the user in on success.
    """
    if request.method == 'POST':
        data = json.loads(request.body)
        response_s = int(data.get('response_s'))

        user_id = request.session.get('auth_zkp_user_id')
        commitment_t = request.session.get('auth_zkp_commitment_t')
        challenge_c = request.session.get('auth_zkp_challenge_c')

        if not all([user_id, commitment_t, challenge_c]):
            return JsonResponse({'status': 'error', 'message': 'Session expired or invalid'})

        user = User.objects.get(id=user_id)
        public_key_y = int(user.zkp_auth_profile.public_key)

        p = get_prime()
        g = get_generator()

        # Verify: g^s == t * y^c (mod p)
        lhs = pow(g, response_s, p)
        rhs = (commitment_t * pow(public_key_y, challenge_c, p)) % p
        is_valid = (lhs == rhs)

        if is_valid:
            user.backend = 'django.contrib.auth.backends.ModelBackend'
            django_login(request, user)
            return JsonResponse({
                'status': 'success',
                'redirect': '/',
                'debug': {
                    'lhs': lhs,
                    'rhs': rhs,
                    'public_key_y': public_key_y,
                    'challenge_c': challenge_c,
                }
            })
        else:
            return JsonResponse({
                'status': 'error',
                'message': 'Zero-Knowledge Proof verification failed.',
                'debug': {'lhs': lhs, 'rhs': rhs}
            })
