from __future__ import annotations from typing import Any, Literal from pydantic import BaseModel, Field Platform = Literal["tiktok", "instagram_reels", "facebook_shorts", "youtube_shorts"] ApprovalState = Literal["draft", "needs_review", "approved", "rejected", "published"] JobState = Literal["queued", "planned", "running", "rendering", "ready", "scheduled", "published", "failed", "cancelled"] WorkspaceRole = Literal["owner", "admin", "editor", "viewer", "publisher"] IntegrationKind = Literal["n8n", "zapier", "make", "slack", "telegram", "email", "google_drive", "dropbox", "airtable", "notion", "rss", "shopify", "webhook"] class BrandKit(BaseModel): id: str = "" name: str logo_url: str | None = None primary_color: str = "#111111" secondary_color: str = "#ffffff" accent_color: str = "#16a34a" font_family: str = "DejaVu Sans" watermark_enabled: bool = True intro_asset: str | None = None outro_asset: str | None = None voice: str | None = None caption_style: str = "bold_word_highlight" safe_zone: dict[str, int] = Field(default_factory=lambda: {"top": 160, "bottom": 280, "left": 64, "right": 64}) created_at: str = "" updated_at: str = "" class CampaignCreate(BaseModel): name: str topic: str niche: str = "" source_url: str | None = None source_asset: str | None = None source_text: str | None = None brand_kit_id: str | None = None platforms: list[Platform] = Field(default_factory=lambda: ["tiktok", "instagram_reels", "facebook_shorts"]) quantity: int = Field(default=5, ge=1, le=100) language: str = "en" tone: str = "clear, punchy, high-retention" target_audience: str = "" publish_window: dict[str, Any] = Field(default_factory=dict) metadata: dict[str, Any] = Field(default_factory=dict) workspace_id: str | None = None class Campaign(BaseModel): id: str name: str topic: str niche: str = "" source_url: str | None = None source_asset: str | None = None source_text: str | None = None brand_kit_id: str | None = None platforms: list[Platform] quantity: int language: str tone: str target_audience: str = "" publish_window: dict[str, Any] = Field(default_factory=dict) metadata: dict[str, Any] = Field(default_factory=dict) workspace_id: str | None = None status: str = "draft" created_at: str updated_at: str class Variant(BaseModel): id: str campaign_id: str platform: Platform title: str hook: str script: str caption: str hashtags: list[str] cta: str template: str creative_style: str duration_seconds: int aspect_ratio: str = "9:16" safe_zone: dict[str, int] = Field(default_factory=dict) render_payload: dict[str, Any] = Field(default_factory=dict) approval_state: ApprovalState = "draft" job_state: JobState = "planned" scheduled_at: str | None = None publish_targets: list[Platform] = Field(default_factory=list) analytics: dict[str, Any] = Field(default_factory=dict) metadata: dict[str, Any] = Field(default_factory=dict) revision: int = 1 created_at: str updated_at: str class ApprovalDecision(BaseModel): state: ApprovalState reviewer: str = "system" notes: str = "" class CalendarEntry(BaseModel): id: str variant_id: str platform: Platform scheduled_at: str status: str = "scheduled" metadata: dict[str, Any] = Field(default_factory=dict) created_at: str updated_at: str class AnalyticsEvent(BaseModel): variant_id: str platform: Platform views: int = 0 likes: int = 0 comments: int = 0 shares: int = 0 saves: int = 0 watch_time_seconds: float = 0 completion_rate: float = 0 source: str = "manual" captured_at: str | None = None class PublishRequest(BaseModel): variant_id: str platforms: list[Platform] = Field(default_factory=list) scheduled_at: str | None = None draft: bool = True webhook_url: str | None = None class AutomationJob(BaseModel): id: str kind: str state: JobState = "queued" payload: dict[str, Any] = Field(default_factory=dict) result: dict[str, Any] = Field(default_factory=dict) logs: list[str] = Field(default_factory=list) attempts: int = 0 max_attempts: int = 3 lease_id: str | None = None idempotency_key: str | None = None scheduled_at: str | None = None created_at: str updated_at: str class Workspace(BaseModel): id: str = "" name: str client_name: str = "" plan: str = "standard" monthly_quota: int = 1000 metadata: dict[str, Any] = Field(default_factory=dict) created_at: str = "" updated_at: str = "" class WorkspaceMember(BaseModel): id: str = "" workspace_id: str email: str role: WorkspaceRole = "viewer" created_at: str = "" updated_at: str = "" class SocialAccount(BaseModel): id: str = "" workspace_id: str | None = None platform: Platform handle: str display_name: str = "" daily_post_limit: int = 3 warmup_enabled: bool = True active: bool = True auth_status: str = "not_connected" metadata: dict[str, Any] = Field(default_factory=dict) created_at: str = "" updated_at: str = "" class CrossPostRule(BaseModel): id: str = "" workspace_id: str | None = None name: str source_platform: Platform = "tiktok" target_platforms: list[Platform] = Field(default_factory=lambda: ["instagram_reels", "facebook_shorts"]) delay_minutes: int = 30 repost_winners_after_days: int = 14 min_viral_score: float = 20 active: bool = True created_at: str = "" updated_at: str = "" class TrendSignal(BaseModel): id: str = "" platform: Platform keyword: str niche: str = "" score: float = 0 velocity: float = 0 source: str = "manual" examples: list[str] = Field(default_factory=list) created_at: str = "" updated_at: str = "" class CompetitorProfile(BaseModel): id: str = "" platform: Platform handle: str niche: str = "" url: str | None = None posting_frequency: str = "" observed_hooks: list[str] = Field(default_factory=list) observed_formats: list[str] = Field(default_factory=list) notes: str = "" created_at: str = "" updated_at: str = "" class Idea(BaseModel): id: str = "" workspace_id: str | None = None source: str = "manual" text: str url: str | None = None niche: str = "" tags: list[str] = Field(default_factory=list) priority: int = Field(default=3, ge=1, le=5) status: str = "new" created_at: str = "" updated_at: str = "" class ContentCalendarPlanRequest(BaseModel): workspace_id: str | None = None niche: str days: int = Field(default=30, ge=1, le=90) posts_per_day: int = Field(default=2, ge=1, le=10) platforms: list[Platform] = Field(default_factory=lambda: ["tiktok", "instagram_reels", "facebook_shorts"]) start_at: str | None = None class ComplianceCheckRequest(BaseModel): variant_id: str | None = None platform: Platform title: str = "" caption: str = "" hashtags: list[str] = Field(default_factory=list) duration_seconds: int = 30 has_disclosure: bool = False metadata: dict[str, Any] = Field(default_factory=dict) class Integration(BaseModel): id: str = "" workspace_id: str | None = None kind: IntegrationKind name: str endpoint_url: str | None = None active: bool = True secret_ref: str | None = None metadata: dict[str, Any] = Field(default_factory=dict) created_at: str = "" updated_at: str = "" class UsageEvent(BaseModel): id: str = "" workspace_id: str | None = None kind: str quantity: int = 1 cost_units: float = 0 metadata: dict[str, Any] = Field(default_factory=dict) created_at: str = "" updated_at: str = "" class ReportRequest(BaseModel): workspace_id: str | None = None campaign_id: str | None = None format: str = "json" include_recommendations: bool = True class VariantUpdate(BaseModel): title: str | None = None hook: str | None = None script: str | None = None caption: str | None = None hashtags: list[str] | None = None cta: str | None = None template: str | None = None creative_style: str | None = None duration_seconds: int | None = Field(default=None, ge=3, le=600) safe_zone: dict[str, int] | None = None render_payload: dict[str, Any] | None = None metadata: dict[str, Any] | None = None class RepurposeRequest(BaseModel): name: str transcript: str = "" source_url: str | None = None source_asset: str | None = None niche: str = "" target_audience: str = "" quantity: int = Field(default=5, ge=1, le=30) platforms: list[Platform] = Field(default_factory=lambda: ["tiktok", "instagram_reels", "youtube_shorts"]) workspace_id: str | None = None brand_kit_id: str | None = None use_ai: bool = False class ProviderGenerateRequest(BaseModel): provider: Literal["openai", "gemini", "openrouter"] | None = None model: str | None = None instructions: str = "" class AssetRecord(BaseModel): id: str = "" workspace_id: str | None = None filename: str path: str kind: Literal["video", "audio", "image", "subtitle", "font", "document", "other"] = "other" content_type: str = "application/octet-stream" size_bytes: int = 0 checksum: str = "" source_url: str | None = None license: str = "unknown" attribution: str = "" tags: list[str] = Field(default_factory=list) metadata: dict[str, Any] = Field(default_factory=dict) created_at: str = "" updated_at: str = "" class Experiment(BaseModel): id: str = "" campaign_id: str name: str = "Campaign experiment" variable: Literal["hook", "caption", "thumbnail", "duration", "template"] = "hook" variant_ids: list[str] = Field(default_factory=list) success_metric: str = "viral_score" minimum_views: int = 1000 confidence_target: float = Field(default=0.9, ge=0.5, le=0.999) status: Literal["draft", "running", "completed"] = "draft" winner_variant_id: str | None = None results: dict[str, Any] = Field(default_factory=dict) created_at: str = "" updated_at: str = "" class ReviewLink(BaseModel): id: str = "" workspace_id: str | None = None variant_ids: list[str] = Field(default_factory=list) token_hash: str = "" expires_at: str created_by: str = "system" active: bool = True created_at: str = "" updated_at: str = "" class ReviewComment(BaseModel): id: str = "" review_id: str = "" variant_id: str author: str = "Client" body: str timestamp_seconds: float | None = Field(default=None, ge=0) created_at: str = "" updated_at: str = "" class AutomationRule(BaseModel): id: str = "" workspace_id: str | None = None name: str event: Literal["variant_approved", "render_completed", "job_failed", "analytics_winner", "publish_due"] conditions: dict[str, Any] = Field(default_factory=dict) actions: list[dict[str, Any]] = Field(default_factory=list) active: bool = True created_at: str = "" updated_at: str = "" class Notification(BaseModel): id: str = "" workspace_id: str | None = None channel: str = "in_app" subject: str message: str status: Literal["queued", "sent", "failed"] = "queued" metadata: dict[str, Any] = Field(default_factory=dict) created_at: str = "" updated_at: str = "" class AuditEvent(BaseModel): id: str = "" workspace_id: str | None = None actor: str = "system" action: str resource_type: str resource_id: str metadata: dict[str, Any] = Field(default_factory=dict) created_at: str = "" updated_at: str = ""