from typing import Any, List, Literal, Optional
import httpx
import asyncio
from mcp.server.fastmcp import FastMCP

# Initialize FastMCP server
mcp = FastMCP("suno")

# Constants
API_TOKEN = ""


# Make a new generate clip request to suno
async def generate_clip(prompt: str, tag: str, title: str, cover_clip_id: Optional[str] = None) -> dict[str, Any] | None:
    """Given a prompt and a tag, generate a clip from suno"""
    url = "https://studio-api.prod.suno.com/api/generate/v2-web/"
    
    request_payload = {
        "token": None,
        "prompt": prompt,
        "generation_type": "TEXT",
        "tags": tag,
        "negative_tags": "",
        "mv": "chirp-v4",
        "title": title,
    }
    if cover_clip_id:
        request_payload["cover_clip_id"] = cover_clip_id
        request_payload["continue_at"] = 0
        request_payload["mv"] = "chirp-v4-tau"
        request_payload["task"] = "cover"

    headers = {
        "Authorization": f"Bearer {API_TOKEN}",
        "Content-Type": "application/json",
    }

    async with httpx.AsyncClient() as client:
        response = await client.post(url, headers=headers, json=request_payload)
        return response.json()    
    
async def get_clip_comments(clip_id: str) -> dict[str, Any] | None:
    url = f"https://studio-api.prod.suno.com/api/gen/{clip_id}/comments"
    headers = {
        "Authorization": f"Bearer {API_TOKEN}",
        "Content-Type": "application/json",
    }

    async with httpx.AsyncClient() as client:
        response = await client.get(url, headers=headers)
        return response.json()
    
    
@mcp.tool()
async def generate_clip_tool(lyrics: str, genre: str, title: str, cover_clip_id: Optional[str] = None) -> dict[str, Any] | None:
    """Given a lyrics and a genre, generate a clip from suno
    to generate a clip that's a cover of an existing clip, set cover_clip_id to the id of the existing clip
    
    Args:
        lyrics (str): The lyrics to generate the clip from
        genre (str): The genre/style of the clip
        title (str): The title of the clip
        cover_clip_id (Optional[str]): The id of the clip to cover
    Returns:
        dict[str, Any] | None: The generated clip
    """
    resp =  await generate_clip(lyrics, genre, title, cover_clip_id)
    clips = resp['clips']
    clip_id1 = clips[0]['id']
    clip_id2 = clips[1]['id']

    return {
        "clip_id1": clip_id1,
        "clip_id2": clip_id2,
        "message": f"Generated clips are available at https://suno.com/song/{clip_id1} and https://suno.com/song/{clip_id2}",
    }

@mcp.tool()
async def sequential_lyrics_writing(existing_lyrics: List[str], story_context: str, type: Literal["single_line", "verse"]="single_line") -> dict[str, Any]:
    """Given existing lyrics and a story context, instruct the AI to generate several new verses of lyrics"""
    if len(existing_lyrics) == 0:
        return {
            "error": "No existing lyrics provided, please provide at least one line of lyrics",
            "status": "error",
        }
    
    SINGLE_LINE_PROMPT = f"""Let's play a lyric continuation game.  
        I’ll give you:  
        * One line of lyrics  
        * A brief story context  

        Your job is to come up with **4 possible next lyric lines** that:  
        * **Rhyme** with the line I gave you  
        * **Fit the story context**  
        * Sound like something a real artist would write—natural, emotional, and creative. Avoid sounding generic or overly 'AI'. Make them feel human.  

        Each line should have a distinct tone or flavor:  
        1. A line that fits naturally and meaningfully with the story (grounded and coherent)  
        2. A line with a **spicy** or flirtatious twist  
        3. A line that’s **super funny and spicy**—feel free to get wild  
        4. A **banger** line that hits hard, sounds cool, or leaves a strong impression  

        Only output the 4 lines, numbered 1 to 4—no explanation, no extra text.  
        Ask **the user** to pick one of the 4, then continue the game from there. Don’t keep generating unless the user gives the green light.

        **Story**: {story_context}  
        **Existing Line**: "{existing_lyrics}"  
        """
    
    VERSE_PROMPT = f"""Let's play a lyric continuation game.  
        I’ll give you:  
        * One line of lyrics  
        * A brief story context  

        Your job is to come up with **4 possible lyrics sections that start with the line I gave you** that:  
        * **Rhyme** with the first line I gave you  
        * **Fit the story context**  
        * Sound like something a real artist would write—natural, emotional, and creative. Avoid sounding generic or overly 'AI'. Make them feel human.  

        Each line should have a distinct tone or flavor:  
        1. A line that fits naturally and meaningfully with the story (grounded and coherent)  
        2. A line with a **spicy** or flirtatious twist  
        3. A line that’s **super funny and spicy**—feel free to get wild  
        4. A **banger** line that hits hard, sounds cool, or leaves a strong impression  

        Only output the 4 lines, numbered 1 to 4—no explanation, no extra text.  
        Ask **the user** to pick one of the 4, then continue the game from there. Don’t keep generating unless the user gives the green light.

        **Story**: {story_context}  
        **Existing Line**: "{existing_lyrics}"  
        """
    if type == "single_line":
        prompt = SINGLE_LINE_PROMPT
    elif type == "verse":
        prompt = VERSE_PROMPT

    return {
        "status": "success",
        "message": prompt,
    }

if __name__ == "__main__":
    # Initialize and run the server
    mcp.run(transport='stdio')

    
