""" API Routes for Content Recycling. """ from datetime import datetime from typing import List, Optional from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.orm import Session from pydantic import BaseModel from app.core.database import get_db from app.services.recycling_service import recycling_service router = APIRouter() class RecycleRequest(BaseModel): """Schema for recycling a post.""" content: Optional[str] = None hashtags: Optional[List[str]] = None image_url: Optional[str] = None scheduled_for: Optional[datetime] = None platforms: Optional[List[str]] = None reason: str = "manual" @router.get("/candidates") async def get_recyclable_candidates( platform: Optional[str] = None, content_type: Optional[str] = None, min_engagement_rate: float = Query(2.0, ge=0), min_days: int = Query(30, ge=7, le=365), limit: int = Query(20, ge=1, le=50), db: Session = Depends(get_db) ): """ Get posts that are good candidates for recycling. - **platform**: Filter by platform - **content_type**: Filter by content type - **min_engagement_rate**: Minimum engagement rate (default 2.0%) - **min_days**: Minimum days since original publish (default 30) """ candidates = await recycling_service.find_recyclable_posts( platform=platform, content_type=content_type, min_engagement_rate=min_engagement_rate, min_days_since_publish=min_days, limit=limit ) return { "candidates": candidates, "count": len(candidates), "filters": { "platform": platform, "content_type": content_type, "min_engagement_rate": min_engagement_rate, "min_days": min_days } } @router.post("/{post_id}") async def recycle_post( post_id: int, recycle_data: RecycleRequest = None, db: Session = Depends(get_db) ): """ Recycle a post by creating a new version. You can optionally modify: - **content**: New content text - **hashtags**: New hashtag list - **image_url**: New image URL - **scheduled_for**: When to publish (default: 1 hour from now) - **platforms**: Override platforms - **reason**: Reason for recycling (manual, high_performer, evergreen, seasonal) """ modifications = None scheduled_for = None platforms = None reason = "manual" if recycle_data: modifications = {} if recycle_data.content: modifications["content"] = recycle_data.content if recycle_data.hashtags: modifications["hashtags"] = recycle_data.hashtags if recycle_data.image_url: modifications["image_url"] = recycle_data.image_url scheduled_for = recycle_data.scheduled_for platforms = recycle_data.platforms reason = recycle_data.reason result = await recycling_service.recycle_post( post_id=post_id, modifications=modifications if modifications else None, scheduled_for=scheduled_for, platforms=platforms, reason=reason ) if not result.get("success"): raise HTTPException( status_code=400, detail=result.get("error", "Failed to recycle post") ) return { "message": "Post recycled successfully", **result } @router.post("/auto") async def auto_recycle_posts( platform: Optional[str] = None, count: int = Query(1, ge=1, le=5), min_engagement_rate: float = Query(2.0, ge=0), db: Session = Depends(get_db) ): """ Automatically recycle top-performing posts. - **platform**: Filter by platform - **count**: Number of posts to recycle (max 5) - **min_engagement_rate**: Minimum engagement rate threshold """ result = await recycling_service.auto_recycle( platform=platform, count=count, min_engagement_rate=min_engagement_rate ) return result @router.get("/history") async def get_recycling_history( original_post_id: Optional[int] = None, limit: int = Query(50, ge=1, le=200), db: Session = Depends(get_db) ): """ Get recycling history. - **original_post_id**: Filter by original post """ history = await recycling_service.get_recycling_history( original_post_id=original_post_id, limit=limit ) return { "history": history, "count": len(history) } @router.post("/{post_id}/disable") async def disable_recycling( post_id: int, db: Session = Depends(get_db) ): """ Mark a post as not eligible for recycling. """ result = await recycling_service.mark_post_not_recyclable(post_id) if not result.get("success"): raise HTTPException( status_code=400, detail=result.get("error", "Failed to disable recycling") ) return result