from fastapi import APIRouter, HTTPException, Depends
from fastapi.responses import StreamingResponse
from backend.services.youtube import YouTubeService
import requests

router = APIRouter()

def get_youtube_service():
    return YouTubeService()

@router.get("/stream")
async def stream_audio(id: str, yt: YouTubeService = Depends(get_youtube_service)):
    try:
        data = yt.get_stream_url(id)
        if isinstance(data, dict):
            stream_url = data.get("url")
            headers = data.get("headers", {})
        else:
            # Fallback for old cached string values
            stream_url = data
            headers = {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
            }
        
        # Helper function to get stream
        def get_stream(url, headers):
            return requests.get(url, headers=headers, stream=True, timeout=10)

        try:
            r = get_stream(stream_url, headers)
            r.raise_for_status()
        except requests.exceptions.HTTPError as e:
            if e.response.status_code == 403:
                print("Got 403 Forbidden. Invalidating cache and retrying...")
                yt.invalidate_stream_cache(id)
                # Fetch fresh
                data = yt.get_stream_url(id)
                if isinstance(data, dict):
                    stream_url = data.get("url")
                    headers = data.get("headers", {})
                else:
                    stream_url = data
                
                # Retry request
                r = get_stream(stream_url, headers)
                r.raise_for_status()
            else:
                raise e

        def iterfile():
            # Already opened request 'r'
            try:
                for chunk in r.iter_content(chunk_size=64*1024): 
                    yield chunk
            except Exception as e:
                print(f"Chunk Error: {e}")
            finally:
                r.close()

        return StreamingResponse(iterfile(), media_type="audio/mpeg")
    except Exception as e:
        print(f"Stream Error: {e}")
        if isinstance(e, requests.exceptions.HTTPError):
             print(f"Upstream Status: {e.response.status_code}")
        raise HTTPException(status_code=500, detail=str(e))

@router.get("/download")
async def download_audio(id: str, title: str = "audio", yt: YouTubeService = Depends(get_youtube_service)):
    try:
        data = yt.get_stream_url(id)
        if isinstance(data, dict):
            stream_url = data.get("url")
            headers = data.get("headers", {})
        else:
            stream_url = data
            headers = {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
            }
        
        def iterfile():
            with requests.get(stream_url, headers=headers, stream=True, timeout=10) as r:
                r.raise_for_status()
                for chunk in r.iter_content(chunk_size=1024*1024): 
                    yield chunk

        safe_filename = "".join([c for c in title if c.isalnum() or c in (' ', '-', '_')]).strip()
        final_headers = {
            "Content-Disposition": f'attachment; filename="{safe_filename}.mp3"'
        }
        return StreamingResponse(iterfile(), media_type="audio/mpeg", headers=final_headers)
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
