import json
import httpx
import logging
from typing import Optional, Dict, Tuple
import asyncio
from pathlib import Path
import uuid
from datetime import datetime

from app.models import SunoGenerateResponse, SunoMetadata

logger = logging.getLogger(__name__)

class SunoService:
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.base_url = "https://studio-api.prod.suno.com/api/v2/external"
        self.headers = {
            "Authorization": f"Bearer {self.api_key}",
            "X-Auth-Type": "alexa",
            "Content-Type": "text/plain;charset=UTF-8",
        }

    async def get_song_status(self, song_id: str) -> SunoGenerateResponse:
        try:
            async with httpx.AsyncClient() as client:
                response = await client.get(
                    f"{self.base_url}/clips",
                    headers=self.headers,
                    params={"ids": song_id},
                    timeout=30.0
                )
                response.raise_for_status()
                response_data = response.json()
                
                # Handle the case when response contains a list of clips
                if isinstance(response_data, list) and len(response_data) > 0:
                    clip_data = response_data[0]
                    
                    # Create a metadata object with available fields
                    metadata = SunoMetadata(
                        tags=clip_data.get("metadata", {}).get("tags"),
                        prompt=clip_data.get("metadata", {}).get("prompt"),
                        gpt_description_prompt=clip_data.get("metadata", {}).get("gpt_description_prompt"),
                        lyrics=clip_data.get("metadata", {}).get("lyrics"),
                        type=clip_data.get("metadata", {}).get("type", "gen"),
                        duration=clip_data.get("metadata", {}).get("duration"),
                        error_type=clip_data.get("metadata", {}).get("error_type"),
                        error_message=clip_data.get("metadata", {}).get("error_message")
                    )
                    
                    return SunoGenerateResponse(
                        id=clip_data.get("id"),
                        request_id=clip_data.get("request_id"),
                        video_url=clip_data.get("video_url"),
                        audio_url=clip_data.get("audio_url"),
                        image_url=clip_data.get("image_url"),
                        image_large_url=clip_data.get("image_large_url"),
                        created_at=clip_data.get("created_at"),
                        status=clip_data.get("status"),
                        title=clip_data.get("title"),
                        metadata=metadata
                    )
                else:
                    logger.error(f"Invalid response format or no clips found: {response_data}")
                    raise ValueError("Invalid response format or no clips found")
                
        except httpx.HTTPStatusError as e:
            logger.error(f"HTTP error fetching song status: {str(e)}")
            if e.response.status_code == 404:
                # For 404 errors, return a response with default values
                return SunoGenerateResponse(
                    id=str(uuid.uuid4()),
                    created_at=datetime.now(),
                    status="not_found",
                    metadata=SunoMetadata(
                        type="gen",
                        error_type="not_found",
                        error_message="Song not found"
                    )
                )
            raise
        except Exception as e:
            logger.error(f"Error fetching song status: {str(e)}")
            raise

    async def generate_song(self, topic: str, tags: Optional[str] = None, model: Optional[str] = None) -> SunoGenerateResponse:
        try:
            content = json.dumps({
                "topic": topic,
                "tags": tags or "children friendly, music",
                "model": model,
                "extra": {
                    "early_callback": True
                }
            })
            print(content)
            async with httpx.AsyncClient() as client:
                response = await client.post(
                    f"{self.base_url}/generate/",
                    headers=self.headers,
                    content=content,
                    timeout=30.0
                )
                response.raise_for_status()
                response_data = response.json()
                
                # Extract request_id if present in the response
                response_obj = SunoGenerateResponse(**response_data)
                
                # If request_id is in the raw response but not captured by the model
                if 'request_id' in response_data and not response_obj.request_id:
                    response_obj.request_id = response_data['request_id']
                    
                return response_obj

        except Exception as e:
            logger.error(f"Song generation error: {str(e)}")
            raise