# -*- coding: utf-8 -*-
"""Doubao MCP server entrypoint."""

from __future__ import annotations

import os
from typing import Annotated, Any, Dict, Optional

import httpx
from mcp.server.fastmcp import Context, FastMCP
from dotenv import load_dotenv

try:
    from .entities import (
        build_create_video_payload,
        build_create_video_response,
        build_video_task_result,
    )
except ImportError:
    import sys
    from pathlib import Path

    sys.path.append(str(Path(__file__).resolve().parents[1]))
    from doubao_mcp.entities import (  # type: ignore[import-not-found]
        build_create_video_payload,
        build_create_video_response,
        build_video_task_result,
    )

load_dotenv()
API_URL = "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks"
MODEL_NAME = "doubao-seedance-1-0-pro-250528"

app = FastMCP("doubao-mcp")


def _get_api_key() -> str:
    api_key = os.getenv("ARK_API_KEY")
    if not api_key:
        raise RuntimeError("ARK_API_KEY environment variable is not set")
    return api_key


def _build_headers(api_key: str) -> Dict[str, str]:
    return {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {api_key}",
    }


@app.tool(name="create_viceo")
async def create_viceo(
    ctx: Context,
    text: Annotated[str, "Text prompt used for Doubao video generation"],
    ratio: Annotated[Optional[str], "Optional ratio, e.g. 16:9"] = None,
    resolution: Annotated[Optional[str], "Optional resolution, e.g. 720p"] = None,
    duration: Annotated[Optional[int], "Optional duration in seconds"] = None,
    frames_per_second: Annotated[Optional[int], "Optional frames per second value"] = None,
    seed: Annotated[Optional[int], "Optional deterministic seed"] = None,
) -> Dict[str, Any]:
    """Create a Doubao video generation task and return its identifier."""

    payload = build_create_video_payload(
        text=text,
        model_name=MODEL_NAME,
        extra_params=_collect_optional_params(
            ratio=ratio,
            resolution=resolution,
            duration=duration,
            frames_per_second=frames_per_second,
            seed=seed,
        ),
    )

    api_key = _get_api_key()
    data = await _request_json("POST", API_URL, headers=_build_headers(api_key), payload=payload)
    task_id = data.get("id")
    if not task_id:
        raise RuntimeError("Doubao API did not return a task id")

    return build_create_video_response(task_id=task_id, payload=payload, raw_response=data)


@app.tool()
async def get_video_result(
    ctx: Context,
    task_id: Annotated[str, "Doubao generation task id"],
) -> Dict[str, Any]:
    """Fetch the latest status for a Doubao video generation task."""

    api_key = _get_api_key()
    url = f"{API_URL}/{task_id.strip()}"

    data = await _request_json("GET", url, headers=_build_headers(api_key))
    return build_video_task_result(data)


def _collect_optional_params(
    *,
    ratio: Optional[str],
    resolution: Optional[str],
    duration: Optional[int],
    frames_per_second: Optional[int],
    seed: Optional[int],
) -> Dict[str, Any]:
    """Collect optional Doubao fields, trimming empty values."""

    params: Dict[str, Any] = {}

    def _assign(key: str, value: Optional[Any]) -> None:
        if value is None:
            return
        if isinstance(value, str):
            trimmed = value.strip()
            if not trimmed:
                return
            params[key] = trimmed
        else:
            params[key] = value

    _assign("ratio", ratio)
    _assign("resolution", resolution)
    _assign("duration", duration)
    _assign("framespersecond", frames_per_second)
    _assign("seed", seed)

    return params


async def _request_json(
    method: str,
    url: str,
    *,
    headers: Dict[str, str],
    payload: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
    """Perform an HTTPX request and return the parsed JSON response."""

    try:
        async with httpx.AsyncClient(timeout=httpx.Timeout(60)) as client:
            response = await client.request(
                method=method.upper(),
                url=url,
                headers=headers,
                json=payload,
            )
            response.raise_for_status()
            return response.json()
    except httpx.HTTPStatusError as exc:
        text = exc.response.text
        status = exc.response.status_code
        raise RuntimeError(f"Doubao API error ({status}): {text}") from exc
    except httpx.RequestError as exc:
        raise RuntimeError(f"Unable to reach Doubao API: {exc}") from exc


def run() -> None:
    """Start the MCP server via stdio."""

    app.run()


__all__ = ["app", "create_viceo", "get_video_result", "run"]


if __name__ == "__main__":
    run()
