from crewai.tools import BaseTool
from pydantic import BaseModel, Field
from typing import Type
import requests
import json
from datetime import datetime


class VideoUploadToolInput(BaseModel):
    """Input schema for VideoUploadTool."""

    video_url: str = Field(
        ...,
        description="A publicly accessible or pre-signed URL pointing to the rendered video file in cloud storage (e.g. S3, GCS, CDN).",
    )
    oauth2_token: str = Field(
        ...,
        description="Bearer token for OAuth2 authentication with the target platform.",
    )
    title: str = Field(
        ...,
        max_length=60,
        description="Title of the video (max 60 characters).",
    )
    description: str = Field(
        ...,
        description="Description/caption for the video, including hashtags.",
    )
    target_platform: str = Field(
        ...,
        description='Target platform slug — must be one of: "youtube", "tiktok", or "instagram".',
    )


class VideoUploadTool(BaseTool):
    """Tool for publishing a video to a social media platform via a pre-signed cloud storage URL."""

    name: str = "VideoUploadTool"
    description: str = (
        "Publishes a video to a social media platform (YouTube, TikTok, or Instagram) "
        "by submitting a pre-signed or publicly accessible cloud storage URL to the platform's API. "
        "Requires a valid OAuth2 Bearer token and accepts video metadata such as title and description."
    )
    args_schema: Type[BaseModel] = VideoUploadToolInput

    def _run(
        self,
        video_url: str,
        oauth2_token: str,
        title: str,
        description: str,
        target_platform: str,
    ) -> str:
        """
        Uploads a video to the specified social media platform using a pre-signed URL.

        Args:
            video_url: Pre-signed or public URL of the video in cloud storage.
            oauth2_token: Bearer token for OAuth2 authentication.
            title: Title of the video (max 60 characters).
            description: Description/caption with hashtags.
            target_platform: One of "youtube", "tiktok", or "instagram".

        Returns:
            A JSON string with status_code, platform, response_body, and timestamp.
        """
        # Platform-to-endpoint mapping
        platform_endpoints = {
            "youtube": "https://www.googleapis.com/youtube/v3/videos?part=snippet,status",
            "tiktok": "https://open.tiktokapis.com/v2/post/publish/video/init/",
            "instagram": "https://graph.facebook.com/v18.0/me/videos",
        }

        # Normalise platform slug
        platform_key = target_platform.strip().lower()

        # Validate platform
        if platform_key not in platform_endpoints:
            return json.dumps(
                {"error": "Platform not supported", "platform": target_platform}
            )

        endpoint = platform_endpoints[platform_key]

        # Build platform-specific request body
        if platform_key == "youtube":
            payload = {
                "snippet": {
                    "title": title,
                    "description": description,
                },
                "status": {
                    "privacyStatus": "public",
                },
                "videoUrl": video_url,
            }
        elif platform_key == "tiktok":
            payload = {
                "post_info": {
                    "title": title,
                    "description": description,
                },
                "source_info": {
                    "source": "PULL_FROM_URL",
                    "video_url": video_url,
                },
            }
        elif platform_key == "instagram":
            payload = {
                "file_url": video_url,
                "caption": f"{title}\n\n{description}",
            }

        # Build request headers
        headers = {
            "Authorization": f"Bearer {oauth2_token}",
            "Content-Type": "application/json",
        }

        try:
            response = requests.post(
                endpoint,
                headers=headers,
                json=payload,
                timeout=30,
            )

            # Attempt to parse response as JSON, fall back to raw text
            try:
                response_body = response.json()
            except ValueError:
                response_body = response.text

            result = {
                "status_code": response.status_code,
                "platform": platform_key,
                "response_body": response_body,
                "timestamp": datetime.utcnow().isoformat(),
            }
            return json.dumps(result)

        except requests.exceptions.Timeout as e:
            return json.dumps(
                {
                    "error": "Request timed out while contacting the platform API.",
                    "details": str(e),
                }
            )
        except requests.exceptions.ConnectionError as e:
            return json.dumps(
                {
                    "error": "Failed to connect to the platform API.",
                    "details": str(e),
                }
            )
        except Exception as e:
            return json.dumps(
                {
                    "error": "An unexpected error occurred during video upload.",
                    "details": str(e),
                }
            )
