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 from .pexels import fetch_first 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 SUPER 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 SUPER PRODUCTION plan for a {proj_type} in the {category} category. Theme: {theme} Requirements: 1. Unique Title and a compelling description. 2. A full cinematic screenplay (script) for the entire production, ready to be read. 3. A short query (2-4 words) for a cinematic visual image representing this production. 4. 3 Main Characters with names and detailed physical descriptions (based on REAL humans/actors style). 5. 8 Key Scenes with titles, narrative descriptions, and a unique 'visual_query' (2-4 words) for each scene. 6. Metadata: Estimated budget (e.g., $200M), Age Rating (e.g., PG-13, R), and Duration (e.g., 140 min). Return the result ONLY in JSON format with the following structure: {{ "title": "...", "description": "...", "full_script": "...", "thumbnail_query": "...", "budget": "...", "rating": "...", "duration": "...", "characters": [ {{"name": "...", "description": "...", "type": "CHAR"}} ], "scenes": [ {{"title": "...", "description": "...", "visual_query": "..."}} ] }} """ response = LocalAIApi.create_response({ "input": [ {"role": "system", "content": "You are an expert Hollywood Producer and AI Cinema Director specialized in Super Productions."}, {"role": "user", "content": prompt}, ], "text": {"format": {"type": "json_object"}}, }) if response.get("success"): try: data = LocalAIApi.decode_json_from_response(response) # Fetch thumbnail from Pexels thumbnail_data = fetch_first(data.get('thumbnail_query', data['title'])) thumbnail_url = "" if thumbnail_data: thumbnail_url = thumbnail_data['local_path'] # Create the Project project = Project.objects.create( title=data['title'], project_type=proj_type, category=category, description=data['description'], full_script=data.get('full_script', ''), thumbnail_url=thumbnail_url, is_ai_generated=True, status='DONE', estimated_budget=data.get('budget', '$150M'), rating=data.get('rating', 'PG-13'), duration=data.get('duration', '120 min') ) # Create default Pipeline Steps stages = [s[0] for s in PipelineStep.STAGES] for stage in stages: PipelineStep.objects.create(project=project, name=stage, progress=100, is_completed=True) # 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 and fetch images for i, scene_data in enumerate(data['scenes']): scene_image_url = "" # Fetch image for EACH scene v_query = scene_data.get('visual_query', scene_data['title']) scene_img_data = fetch_first(f"{data['title']} {v_query}", orientation="landscape") if scene_img_data: scene_image_url = scene_img_data['local_path'] Scene.objects.create( project=project, number=i+1, title=scene_data['title'], description=scene_data['description'], visual_prompt=scene_data.get('visual_query', ''), image_url=scene_image_url ) messages.success(request, f"Super Produção '{project.title}' criada e salva na Biblioteca!") return redirect('production_library') 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') @studio_admin_required def production_library(request): """View to see all completed AI productions.""" productions = Project.objects.filter(is_ai_generated=True).order_by('-created_at') return render(request, "core/production_library.html", {"productions": productions}) @studio_admin_required def watch_production(request, slug): """View to 'watch' (read and experience) a complete production.""" project = get_object_or_404(Project.objects.prefetch_related('assets', 'scenes'), slug=slug) return render(request, "core/watch_production.html", {"project": project}) 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)