"""Audio streaming and download endpoints."""
from fastapi import APIRouter, Depends, HTTPException, Request, Query, status
from fastapi.responses import FileResponse
from sqlalchemy.orm import Session
from uuid import UUID
from pathlib import Path
from typing import Optional

from ...models.database import get_db
from ...models import crud
from ...core.waveform_generator import get_waveform_data
from ...core.auth import verify_token, require_auth
from ...utils.logging import get_logger

router = APIRouter()
logger = get_logger(__name__)


@router.get("/stream/{track_id}")
async def stream_audio(
    track_id: UUID,
    request: Request,
    token: Optional[str] = Query(None),
    db: Session = Depends(get_db),
):
    """Stream audio file with range request support.

    Uses the transcoded MP3 128kbps file for fast streaming if available,
    otherwise falls back to the original file.

    Args:
        track_id: Track UUID
        request: HTTP request
        token: Optional JWT token for authentication (for <audio> tag compatibility)
        db: Database session

    Returns:
        Audio file for streaming

    Raises:
        HTTPException: 404 if track not found or file doesn't exist
    """
    # Verify authentication via query parameter for <audio> tag
    if not token:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Authentication required",
            headers={"WWW-Authenticate": "Bearer"},
        )
    verify_token(token)

    track = crud.get_track_by_id(db, track_id)

    if not track:
        raise HTTPException(status_code=404, detail="Track not found")

    # Prefer stream_filepath (transcoded MP3) if available
    if track.stream_filepath and Path(track.stream_filepath).exists():
        file_path = Path(track.stream_filepath)
        media_type = "audio/mpeg"
        logger.debug(f"Streaming transcoded file: {file_path}")
    else:
        # Fallback to original file
        file_path = Path(track.filepath)

        if not file_path.exists():
            logger.error(f"File not found: {track.filepath}")
            raise HTTPException(status_code=404, detail="Audio file not found on disk")

        # Determine media type based on format
        media_types = {
            "mp3": "audio/mpeg",
            "wav": "audio/wav",
            "flac": "audio/flac",
            "m4a": "audio/mp4",
            "ogg": "audio/ogg",
        }
        media_type = media_types.get(track.format, "audio/mpeg")
        logger.debug(f"Streaming original file: {file_path}")

    return FileResponse(
        path=str(file_path),
        media_type=media_type,
        filename=track.filename,
        headers={
            "Accept-Ranges": "bytes",
            "Content-Disposition": f'inline; filename="{track.filename}"',
        },
    )


@router.get("/download/{track_id}")
async def download_audio(
    track_id: UUID,
    token: Optional[str] = Query(None),
    db: Session = Depends(get_db),
):
    """Download audio file.

    Args:
        track_id: Track UUID
        token: Optional JWT token for authentication (for <a> tag compatibility)
        db: Database session

    Returns:
        Audio file for download

    Raises:
        HTTPException: 404 if track not found or file doesn't exist
    """
    # Verify authentication via query parameter for <a> tag
    if not token:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Authentication required",
            headers={"WWW-Authenticate": "Bearer"},
        )
    verify_token(token)

    track = crud.get_track_by_id(db, track_id)

    if not track:
        raise HTTPException(status_code=404, detail="Track not found")

    file_path = Path(track.filepath)

    if not file_path.exists():
        logger.error(f"File not found: {track.filepath}")
        raise HTTPException(status_code=404, detail="Audio file not found on disk")

    # Determine media type
    media_types = {
        "mp3": "audio/mpeg",
        "wav": "audio/wav",
        "flac": "audio/flac",
        "m4a": "audio/mp4",
        "ogg": "audio/ogg",
    }
    media_type = media_types.get(track.format, "audio/mpeg")

    return FileResponse(
        path=str(file_path),
        media_type=media_type,
        filename=track.filename,
        headers={
            "Content-Disposition": f'attachment; filename="{track.filename}"',
        },
    )


@router.get("/waveform/{track_id}")
async def get_waveform(
    track_id: UUID,
    num_peaks: int = 800,
    db: Session = Depends(get_db),
    current_user: dict = Depends(require_auth),
):
    """Get waveform peak data for visualization.

    Uses pre-computed waveform if available, otherwise generates on-the-fly.

    Args:
        track_id: Track UUID
        num_peaks: Number of peaks to generate
        db: Database session
        current_user: Current authenticated user

    Returns:
        Waveform data with peaks and duration

    Raises:
        HTTPException: 404 if track not found or file doesn't exist
    """
    track = crud.get_track_by_id(db, track_id)

    if not track:
        raise HTTPException(status_code=404, detail="Track not found")

    file_path = Path(track.filepath)

    if not file_path.exists():
        logger.error(f"File not found: {track.filepath}")
        raise HTTPException(status_code=404, detail="Audio file not found on disk")

    try:
        # Use pre-computed waveform if available
        waveform_cache_path = track.waveform_filepath if track.waveform_filepath else None

        waveform_data = get_waveform_data(
            str(file_path),
            num_peaks=num_peaks,
            waveform_cache_path=waveform_cache_path
        )
        return waveform_data

    except Exception as e:
        logger.error(f"Failed to generate waveform for {track_id}: {e}")
        raise HTTPException(status_code=500, detail="Failed to generate waveform")
