import os import json from functools import wraps from django.shortcuts import render, get_object_or_404, redirect from django.utils import timezone from django.contrib import messages from django.http import JsonResponse from .models import Project, PipelineStep, CgiAsset, StudioConfig, Scene from ai.local_ai_api import LocalAIApi def studio_admin_required(view_func): """Decorator to restrict access to studio admin only.""" @wraps(view_func) def _wrapped_view(request, *args, **kwargs): if not request.session.get('is_studio_admin', False): messages.warning(request, "Acesso restrito. Por favor, insira sua chave de administrador.") return redirect('admin_login') return view_func(request, *args, **kwargs) return _wrapped_view def home(request): """Render the CGI Studio Command Center.""" config, created = StudioConfig.objects.get_or_create(id=1) if created or not config.admin_access_key: config.save() projects = Project.objects.prefetch_related('steps').all().order_by('-created_at') total_projects = projects.count() active_productions = projects.filter(status='PROD').count() completed_projects = projects.filter(status='DONE').count() context = { "projects": projects, "total_projects": total_projects, "active_productions": active_productions, "completed_projects": completed_projects, "current_time": timezone.now(), "is_admin": request.session.get('is_studio_admin', False), } return render(request, "core/index.html", context) @studio_admin_required def studio_ai(request): """Page to configure and launch AI-automated productions.""" return render(request, "core/studio_ai.html") @studio_admin_required def generate_production(request): """AI logic to create a full production automatically.""" if request.method == "POST": category = request.POST.get("category", "Sci-Fi") proj_type = request.POST.get("project_type", "MOVIE") theme = request.POST.get("theme", "Future of humanity") prompt = f""" Create a detailed production plan for a {proj_type} in the {category} category. Theme: {theme} Requirements: 1. Unique Title and a compelling description. 2. 3 Main Characters with names and detailed physical descriptions (based on REAL humans/actors style). 3. 5 Key Scenes with titles and narrative descriptions. Return the result ONLY in JSON format with the following structure: {{ "title": "...", "description": "...", "characters": [ {{"name": "...", "description": "...", "type": "CHAR"}} ], "scenes": [ {{"title": "...", "description": "..."}} ] }} """ response = LocalAIApi.create_response({ "input": [ {"role": "system", "content": "You are an expert Hollywood Producer and AI Cinema Director."}, {"role": "user", "content": prompt}, ], "text": {"format": {"type": "json_object"}}, }) if response.get("success"): try: data = LocalAIApi.decode_json_from_response(response) # Create the Project project = Project.objects.create( title=data['title'], project_type=proj_type, category=category, description=data['description'], is_ai_generated=True, status='PRE' ) # Create default Pipeline Steps stages = [s[0] for s in PipelineStep.STAGES] for stage in stages: PipelineStep.objects.create(project=project, name=stage, progress=0) # Create Characters (Assets) for char in data['characters']: CgiAsset.objects.create( project=project, name=char['name'], asset_type='CHAR', physical_description=char['description'] ) # Create Scenes for i, scene in enumerate(data['scenes']): Scene.objects.create( project=project, number=i+1, title=scene['title'], description=scene['description'] ) messages.success(request, f"Super Produção '{project.title}' criada com sucesso pelo Studio AI!") return redirect('project_detail', slug=project.slug) except Exception as e: messages.error(request, f"Erro ao processar resposta da AI: {str(e)}") else: messages.error(request, f"Erro na API de IA: {response.get('error')}") return redirect('studio_ai') def admin_login(request): """View to enter the unique admin access key.""" if request.method == "POST": key = request.POST.get("access_key") try: config = StudioConfig.objects.get(id=1) if key == config.admin_access_key: request.session['is_studio_admin'] = True messages.success(request, "Bem-vindo, Comandante do Estúdio!") return redirect('home') else: messages.error(request, "Chave de acesso inválida.") except StudioConfig.DoesNotExist: messages.error(request, "Configuração do estúdio não encontrada.") return render(request, "core/admin_login.html") def admin_logout(request): """Logout the studio admin.""" request.session['is_studio_admin'] = False return redirect('home') @studio_admin_required def asset_library(request): """View all digital assets (Characters, Props, Environments).""" assets = CgiAsset.objects.select_related('project').all() asset_types = { 'CHAR': assets.filter(asset_type='CHAR'), 'PROP': assets.filter(asset_type='PROP'), 'ENV': assets.filter(asset_type='ENV'), } context = { "assets": assets, "asset_types": asset_types, } return render(request, "core/asset_library.html", context) def project_detail(request, slug): """Render the detailed pipeline for a specific production.""" project = get_object_or_404(Project.objects.prefetch_related('steps', 'assets', 'scenes'), slug=slug) context = { "project": project, "steps": project.steps.all(), "assets": project.assets.all(), "scenes": project.scenes.all(), } return render(request, "core/project_detail.html", context)