"""Loom API client for video management.

Loom uses OAuth2 for authentication. This client supports Bearer token authentication
for the Loom API. Users must obtain an access token through Loom's OAuth2 flow.

Note: Loom's public API access may be limited. This client implements endpoints
based on the PRD specification. Enterprise users may have additional API access.

Generated by GRIMLOCK MCP Factory
"""

import logging
import os
from typing import Any

import httpx

logger = logging.getLogger("loom_mcp")


class LoomClient:
    """Client for interacting with the Loom API."""

    BASE_URL = "https://api.loom.com/v1"

    def __init__(
        self,
        access_token: str | None = None,
        base_url: str | None = None,
    ):
        """Initialize the Loom client.

        Args:
            access_token: OAuth2 access token. Defaults to LOOM_ACCESS_TOKEN env var.
            base_url: API base URL. Defaults to LOOM_BASE_URL env var or production URL.
        """
        self.access_token = access_token or os.environ.get("LOOM_ACCESS_TOKEN", "")
        self.base_url = (
            base_url or os.environ.get("LOOM_BASE_URL", self.BASE_URL)
        ).rstrip("/")

    def _get_headers(self) -> dict[str, str]:
        """Get request headers with OAuth2 Bearer authentication.

        Returns:
            Dictionary of HTTP headers
        """
        return {
            "Authorization": f"Bearer {self.access_token}",
            "Content-Type": "application/json",
            "Accept": "application/json",
        }

    async def _request(
        self,
        method: str,
        endpoint: str,
        params: dict[str, Any] | None = None,
        json_data: dict[str, Any] | None = None,
    ) -> dict[str, Any]:
        """Make an authenticated request to the Loom API.

        Args:
            method: HTTP method (GET, POST, PATCH, DELETE)
            endpoint: API endpoint (e.g., /videos)
            params: Optional query parameters
            json_data: Optional JSON body data

        Returns:
            API response as dictionary

        Raises:
            httpx.HTTPStatusError: If the request fails
        """
        url = f"{self.base_url}{endpoint}"

        async with httpx.AsyncClient(timeout=30.0) as client:
            response = await client.request(
                method=method,
                url=url,
                headers=self._get_headers(),
                params=params,
                json=json_data,
            )
            response.raise_for_status()

            if response.status_code == 204:
                return {}

            return response.json()

    async def list_videos(
        self,
        limit: int = 50,
        offset: int = 0,
        folder_id: str | None = None,
    ) -> dict[str, Any]:
        """List recorded videos.

        Args:
            limit: Maximum number of videos to return (default 50)
            offset: Pagination offset (default 0)
            folder_id: Optional folder ID to filter by

        Returns:
            Dictionary containing videos list and pagination info
        """
        params: dict[str, Any] = {
            "limit": limit,
            "offset": offset,
        }

        if folder_id:
            params["folder_id"] = folder_id

        result = await self._request("GET", "/videos", params=params)

        # Normalize response structure
        if isinstance(result, list):
            return {"videos": result, "total": len(result)}

        return result

    async def get_video(self, video_id: str) -> dict[str, Any]:
        """Get a specific video by ID.

        Args:
            video_id: Unique identifier for the video

        Returns:
            Video object with full details
        """
        return await self._request("GET", f"/videos/{video_id}")

    async def update_video(
        self,
        video_id: str,
        title: str | None = None,
        description: str | None = None,
    ) -> dict[str, Any]:
        """Update video metadata.

        Args:
            video_id: Unique identifier for the video
            title: Optional new title
            description: Optional new description

        Returns:
            Updated video object
        """
        data: dict[str, Any] = {}

        if title is not None:
            data["title"] = title
        if description is not None:
            data["description"] = description

        return await self._request("PATCH", f"/videos/{video_id}", json_data=data)

    async def edit_video(
        self,
        video_id: str,
        editing_details: dict[str, Any],
    ) -> dict[str, Any]:
        """Edit a video by adding clips or trimming sections.

        Args:
            video_id: Unique identifier for the video
            editing_details: Dictionary containing edit instructions:
                - trim_start: Start time in seconds to trim from beginning
                - trim_end: End time in seconds to trim from end
                - clips: List of clip objects with start/end times
                - title: Optional new title for edited video

        Returns:
            Edited video object or edit job status
        """
        data = {
            "video_id": video_id,
            **editing_details,
        }

        return await self._request("POST", f"/videos/{video_id}/edit", json_data=data)

    async def merge_videos(
        self,
        video_ids: list[str],
        title: str | None = None,
    ) -> dict[str, Any]:
        """Combine multiple videos into one.

        Args:
            video_ids: List of video IDs to merge (in order)
            title: Optional title for the merged video

        Returns:
            Merged video object or merge job status
        """
        data: dict[str, Any] = {
            "video_ids": video_ids,
        }

        if title:
            data["title"] = title

        return await self._request("POST", "/videos/merge", json_data=data)

    async def delete_video(self, video_id: str) -> dict[str, Any]:
        """Delete a video.

        Args:
            video_id: Unique identifier for the video

        Returns:
            Empty dict on success
        """
        return await self._request("DELETE", f"/videos/{video_id}")

    async def get_video_transcript(self, video_id: str) -> dict[str, Any]:
        """Get the transcript for a video.

        Args:
            video_id: Unique identifier for the video

        Returns:
            Transcript object with text and timestamps
        """
        return await self._request("GET", f"/videos/{video_id}/transcript")

    async def list_folders(self) -> dict[str, Any]:
        """List all folders.

        Returns:
            Dictionary containing folders list
        """
        return await self._request("GET", "/folders")

    async def get_folder(self, folder_id: str) -> dict[str, Any]:
        """Get a specific folder by ID.

        Args:
            folder_id: Unique identifier for the folder

        Returns:
            Folder object with details
        """
        return await self._request("GET", f"/folders/{folder_id}")
