import json
import random
import string
import uuid
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib import messages
from django.utils import timezone
from datetime import timedelta
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from .models import GameProject, UserSession, AdminConfig, RentalOption, UserPurchase
from ai.local_ai_api import LocalAIApi

# Helper to check authentication
def get_auth_status(request):
    is_admin = request.session.get('is_admin', False)
    user_code = request.session.get('user_code')
    user = None
    if user_code:
        user = UserSession.objects.filter(access_code=user_code).first()
    return is_admin, user

def index(request):
    is_admin, user = get_auth_status(request)
    if is_admin:
        return redirect('admin_dashboard')
    if user:
        return redirect('catalog')
    return render(request, 'core/index.html', {'title': 'Acesso'})

def admin_login(request):
    if request.method == 'POST':
        key = request.POST.get('private_key')
        if AdminConfig.objects.filter(private_key=key).exists():
            request.session['is_admin'] = True
            request.session['user_code'] = None
            return redirect('admin_dashboard')
        messages.error(request, 'Chave Privada Inválida.')
    return render(request, 'core/admin_login.html', {'title': 'Admin Login'})

def generate_code(request):
    if request.method == 'POST':
        phone = request.POST.get('phone')
        code = ''.join(random.choices(string.digits, k=6))
        while UserSession.objects.filter(access_code=code).exists():
            code = ''.join(random.choices(string.digits, k=6))
        
        UserSession.objects.create(access_code=code, phone_number=phone)
        request.session['user_code'] = code
        request.session['is_admin'] = False
        messages.success(request, f'Seu código de acesso é: {code}. Guarde-o bem!')
        return redirect('catalog')
    return redirect('index')

def recover_code(request):
    if request.method == 'POST':
        phone = request.POST.get('phone')
        user = UserSession.objects.filter(phone_number=phone).first()
        if user:
            request.session['user_code'] = user.access_code
            messages.success(request, f'Bem-vindo de volta! Seu código {user.access_code} foi recuperado.')
            return redirect('catalog')
        messages.error(request, 'Nenhum código encontrado para este telefone.')
    return redirect('index')

def logout(request):
    request.session.flush()
    return redirect('index')

# AI Helper - Refined for better functional games
def generate_game_script(prompt, genre):
    system_prompt = (
        "You are an Advanced AI Game Programmer. Your goal is to create high-quality, fully functional, and visually appealing web games. "
        "The game MUST be a single-file HTML (including CSS and JS) that works perfectly in an iframe. "
        "Features to include: "
        "1. A polished Start Screen with a 'Play' button. "
        "2. Score tracking and a Game Over screen with a 'Restart' button. "
        "3. Mobile-friendly touch controls and desktop keyboard support. "
        "4. Vibrant, modern aesthetics using CSS gradients and clean shapes. "
        "5. Fluid animations and sound effects simulation (visual feedback). "
        "Return ONLY the source code starting with <!DOCTYPE html>."
    )
    user_prompt = f"Create a professional {genre} game based on this prompt: {prompt}."
    
    response = LocalAIApi.create_response({
        "input": [
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": user_prompt},
        ],
    })
    
    if response.get("success"):
        return LocalAIApi.extract_text(response)
    return None

# ADMIN VIEWS
def admin_dashboard(request):
    is_admin, _ = get_auth_status(request)
    if not is_admin:
        return redirect('admin_login')
    
    projects = GameProject.objects.all().order_by('-created_at')
    rental_options = RentalOption.objects.all()
    
    return render(request, 'core/admin_dashboard.html', {
        'projects': projects,
        'rental_options': rental_options,
        'title': 'Painel do Administrador'
    })

def admin_create_game(request):
    is_admin, _ = get_auth_status(request)
    if not is_admin:
        return redirect('admin_login')

    if request.method == 'POST':
        title = request.POST.get('title')
        prompt = request.POST.get('prompt', '')
        genre = request.POST.get('genre', 'platformer')
        external_url = request.POST.get('external_url', '')
        image = request.FILES.get('image')
        use_ai = request.POST.get('use_ai') == 'on'
        manual_script = request.POST.get('script_code', '')

        script = manual_script
        if use_ai and prompt:
            ai_script = generate_game_script(prompt, genre)
            if ai_script:
                script = ai_script
            else:
                messages.error(request, 'Falha ao gerar o script com AI.')

        GameProject.objects.create(
            title=title,
            prompt=prompt,
            genre=genre,
            image_reference=image,
            script_code=script,
            external_url=external_url,
            config_json={"player": {"speed": 200}, "entities": []}
        )
        messages.success(request, f'Jogo "{title}" criado!')
        return redirect('admin_dashboard')
    
    return render(request, 'core/admin_game_form.html', {'title': 'Criar Novo Jogo'})

def admin_edit_game(request, pk):
    is_admin, _ = get_auth_status(request)
    if not is_admin:
        return redirect('admin_login')
    
    project = get_object_or_404(GameProject, pk=pk)
    
    if request.method == 'POST':
        project.title = request.POST.get('title')
        project.prompt = request.POST.get('prompt', '')
        project.genre = request.POST.get('genre')
        project.external_url = request.POST.get('external_url', '')
        if request.FILES.get('image'):
            project.image_reference = request.FILES.get('image')
        
        use_ai = request.POST.get('use_ai') == 'on'
        manual_script = request.POST.get('script_code', '')
        
        if use_ai and project.prompt:
            ai_script = generate_game_script(project.prompt, project.genre)
            if ai_script:
                project.script_code = ai_script
        else:
            project.script_code = manual_script
            
        project.save()
        messages.success(request, f'Jogo "{project.title}" atualizado!')
        return redirect('admin_dashboard')
    
    return render(request, 'core/admin_game_form.html', {'project': project, 'title': 'Editar Jogo'})

def admin_delete_game(request, pk):
    is_admin, _ = get_auth_status(request)
    if not is_admin:
        return redirect('admin_login')
    
    project = get_object_or_404(GameProject, pk=pk)
    project.delete()
    messages.success(request, 'Jogo excluído.')
    return redirect('admin_dashboard')

def admin_edit_rental(request, pk):
    is_admin, _ = get_auth_status(request)
    if not is_admin:
        return redirect('admin_login')
    
    option = get_object_or_404(RentalOption, pk=pk)
    if request.method == 'POST':
        option.title = request.POST.get('title')
        option.price = request.POST.get('price')
        option.duration_days = request.POST.get('duration_days')
        if request.FILES.get('qr1'):
            option.qr_code_1 = request.FILES.get('qr1')
        if request.FILES.get('qr2'):
            option.qr_code_2 = request.FILES.get('qr2')
        option.save()
        messages.success(request, 'Opção de aluguel atualizada.')
        return redirect('admin_dashboard')
    
    return render(request, 'core/admin_rental_form.html', {'option': option, 'title': 'Editar Preço'})

# USER VIEWS
def catalog(request):
    is_admin, user = get_auth_status(request)
    if not user and not is_admin:
        return redirect('index')
    
    projects = GameProject.objects.filter(is_active=True).order_by('-created_at')
    return render(request, 'core/catalog.html', {'projects': projects, 'title': 'Catálogo de Jogos'})

def purchase_game(request, pk):
    is_admin, user = get_auth_status(request)
    if not user:
        return redirect('index')
    
    game = get_object_or_404(GameProject, pk=pk)
    options = RentalOption.objects.all()
    
    if request.method == 'POST':
        confirm_code = request.POST.get('confirm_code')
        purchase_id = request.POST.get('purchase_id')
        purchase = get_object_or_404(UserPurchase, pk=purchase_id, user_session=user)
        
        if confirm_code == purchase.confirmation_code and purchase.is_paid:
            purchase.is_confirmed = True
            purchase.save()
            messages.success(request, f'Pagamento confirmado! Aproveite o jogo.')
            return redirect('play_game', pk=game.pk)
        else:
            messages.error(request, 'Código inválido ou pagamento não identificado.')
            
    return render(request, 'core/purchase.html', {
        'game': game,
        'options': options,
        'title': f'Alugar {game.title}'
    })

def generate_purchase(request, game_pk, option_pk):
    is_admin, user = get_auth_status(request)
    if not user:
        return JsonResponse({'success': False, 'error': 'Unauthorized'})
    
    game = get_object_or_404(GameProject, pk=game_pk)
    option = get_object_or_404(RentalOption, pk=option_pk)
    
    # Code is initially None or a placeholder; will be set when "payment detected"
    expires = timezone.now() + timedelta(days=option.duration_days)
    purchase = UserPurchase.objects.create(
        user_session=user,
        game=game,
        rental_option=option,
        confirmation_code="PENDING", 
        expires_at=expires,
        is_paid=False,
        is_confirmed=False
    )
    
    return JsonResponse({
        'success': True, 
        'purchase_id': purchase.id
    })

@csrf_exempt
def simulate_payment(request, purchase_id):
    """
    Simulates the intelligent anti-fraud system detecting a real payment.
    In a real scenario, this would be an endpoint called by a payment webhook.
    """
    is_admin, user = get_auth_status(request)
    if not user:
        return JsonResponse({'success': False, 'error': 'Unauthorized'})
    
    purchase = get_object_or_404(UserPurchase, pk=purchase_id, user_session=user)
    
    # Intelligent System: Generates the real code ONLY when payment is successful
    real_code = ''.join(random.choices(string.digits, k=6))
    purchase.confirmation_code = real_code
    purchase.is_paid = True
    purchase.save()
    
    return JsonResponse({
        'success': True, 
        'message': 'SISTEMA INTELIGENTE: Pagamento identificado e validado.'
    })

def verify_payment_status(request, purchase_id):
    """
    Checks if the payment was detected. 
    Returns the real code if paid, or an invalid random code if fraud/timeout.
    """
    is_admin, user = get_auth_status(request)
    if not user:
        return JsonResponse({'success': False, 'error': 'Unauthorized'})
    
    purchase = get_object_or_404(UserPurchase, pk=purchase_id, user_session=user)
    
    if purchase.is_paid and purchase.confirmation_code != "PENDING":
        return JsonResponse({
            'success': True, 
            'paid': True, 
            'confirmation_code': purchase.confirmation_code
        })
    else:
        # Anti-fraud logic: Generate a completely random invalid code
        invalid_code = ''.join(random.choices(string.digits, k=6))
        # Reset the purchase state to allow retry
        purchase.confirmation_code = "INVALID"
        purchase.is_paid = False
        purchase.save()
        
        return JsonResponse({
            'success': True, 
            'paid': False, 
            'invalid_code': invalid_code
        })

def play_game(request, pk):
    is_admin, user = get_auth_status(request)
    if not user and not is_admin:
        return redirect('index')
    
    game = get_object_or_404(GameProject, pk=pk)
    
    if not is_admin:
        purchase = UserPurchase.objects.filter(
            user_session=user, 
            game=game, 
            expires_at__gt=timezone.now(),
            is_confirmed=True
        ).first()
        
        if not purchase:
            messages.error(request, 'Você não tem tempo de jogo para este título.')
            return redirect('purchase_game', pk=game.pk)
            
    return render(request, 'core/play.html', {'game': game, 'title': f'Jogando {game.title}'})