import base64 import logging from datetime import datetime, timezone from fastapi import APIRouter, HTTPException from app.schemas.common import TaskResponse, TaskStatus from app.schemas.utilities import ClassificationResponse, IconRequest from app.services import freepik_client, task_tracker logger = logging.getLogger(__name__) router = APIRouter(prefix='/api/v1/util', tags=['utilities']) @router.post('/remove-background') async def remove_background(request: dict): """Remove background from an image. Returns processed image as base64.""" image = request.get('image') if not image: raise HTTPException(status_code=400, detail='image field is required') result_bytes = await freepik_client.remove_background(image) return { 'image': base64.b64encode(result_bytes).decode(), 'content_type': 'image/png', } @router.post('/classify', response_model=ClassificationResponse) async def classify_image(request: dict): """Classify whether an image is AI-generated.""" image = request.get('image') if not image: raise HTTPException(status_code=400, detail='image field is required') result = await freepik_client.classify_image(image) data = result.get('data', result) return ClassificationResponse( is_ai_generated=data.get('is_ai_generated', False), ai_probability=data.get('ai_probability', 0.0), human_probability=data.get('human_probability', 0.0), ) @router.post('/audio-isolate', response_model=TaskResponse) async def audio_isolate(request: dict): """Isolate audio tracks from an audio file.""" audio = request.get('audio') if not audio: raise HTTPException(status_code=400, detail='audio field is required') result = await freepik_client.isolate_audio(audio) data = result.get('data', result) freepik_task_id = str(data.get('task_id') or data.get('id', '')) if not freepik_task_id: raise HTTPException(status_code=502, detail='No task_id in Freepik response') internal_id = task_tracker.submit(freepik_task_id, {'operation': 'audio-isolate'}) return TaskResponse( task_id=internal_id, status=TaskStatus.pending, created_at=datetime.now(timezone.utc), ) # Icon generation lives under /api/v1/generate/ but is simple enough to keep here icon_router = APIRouter(prefix='/api/v1/generate', tags=['utilities']) @icon_router.post('/icon', response_model=TaskResponse) async def generate_icon(request: IconRequest): result = await freepik_client.generate_icon( prompt=request.prompt, color=request.color, shape=request.shape, style=request.style, ) data = result.get('data', result) freepik_task_id = str(data.get('task_id') or data.get('id', '')) if not freepik_task_id: raise HTTPException(status_code=502, detail='No task_id in Freepik response') internal_id = task_tracker.submit(freepik_task_id, {'operation': 'icon'}) return TaskResponse( task_id=internal_id, status=TaskStatus.pending, created_at=datetime.now(timezone.utc), )