""" Musica service routes """
from typing import List, Optional, Any
from uuid import UUID

from fastapi import APIRouter, HTTPException, Query
from sqlmodel import Session

from app.api.deps import CurrentUser, SessionDep, get_current_active_superuser
from app import crud
from app.models import Musica, MusicaCreate, MusicaUpdate, MusicaOut, MusicaEstilo, Generos, Canciones, ServiceMusicaOut, ServiceMusicasOut, ServiceCreateMusica, ServiceUpdateMusica


router = APIRouter()

# -- Endpoints para obtener servicios de música --

@router.get("/by_id/{musica_id}", response_model=ServiceMusicaOut)
def get_musica(
    musica_id: UUID,
    session: SessionDep,
) -> ServiceMusicaOut:
    """
    Obtener un servicio de música por su ID
    """
    musica = crud.musica.get_musica(db=session, musica_id=musica_id)
    if not musica:
        raise HTTPException(status_code=404, detail="Servicio de música no encontrado")

    return musica

@router.get("/all", response_model=ServiceMusicasOut)
def get_musicas(
    session: SessionDep,
    skip: int = Query(0, ge=0),
    limit: int = Query(10, ge=1, le=100)
) -> ServiceMusicasOut:
    """
    Obtener todos los servicios de música (paginados)
    """
    # Administradores pueden ver todos los servicios
    musicas, total = crud.musica.get_musicas(db=session, skip=skip, limit=limit)
    return ServiceMusicasOut(data=musicas, count=total)

@router.get("/all_me", response_model=ServiceMusicasOut)
def get_musicas_me(
    session: SessionDep,
    current_user: CurrentUser,
    skip: int = Query(0, ge=0),
    limit: int = Query(10, ge=1, le=100)
) -> ServiceMusicasOut:
    """
    Obtener todos los servicios de música del usuario actual (paginados)
    """
    # Usuarios normales solo ven sus propios servicios
    musicas, total = crud.musica.get_musicas_by_account(
        db=session, 
        account_id=current_user.id, 
        skip=skip, 
        limit=limit
    )
    
    return ServiceMusicasOut(data=musicas, count=total)

@router.post("/", response_model=ServiceMusicaOut)
def create_musica(
    musica_in: ServiceCreateMusica,
    session: SessionDep,
    current_user: CurrentUser
) -> ServiceMusicaOut:
    """
    Crear un nuevo servicio de música
    """
    if not current_user.is_superuser and not crud.user.is_user_vendor(session=session, user_id=current_user.id):
        raise HTTPException(status_code=403, detail="User must be a vendor or superuser")

    return crud.musica.create_musica(
        db=session, 
        musica_in=musica_in, 
        account_id=current_user.id
    )

@router.get("/filter", response_model=ServiceMusicasOut)
def get_musicas_filtered(
    session: SessionDep,
    musica_type: Optional[MusicaEstilo] = None,
    genero: Optional[List[Generos]] = Query(default=None, description="Puedes añadir varios: ?genero=rock&genero=salsa"),
    canciones: Optional[Canciones] = None,
    min_duracion: Optional[float] = None,
    max_duracion: Optional[float] = None,
    instrumento: Optional[List[str]] = Query(default=None, description="Puedes añadir varios: ?instrumento=Piano&instrumento=Saxofón"),
    skip: int = Query(0, ge=0),
    limit: int = Query(10, ge=1, le=100)
) -> ServiceMusicasOut:
    """
    Obtener servicios de música con filtros opcionales:
    - Tipo de música (DJ/Músico)
    - Género musical (puede especificar múltiples géneros usando ?genero=rock&genero=salsa)
    - Tipo de canciones (propias/versiones)
    - Duración mínima (en horas, puede ser decimal)
    - Duración máxima (en horas, puede ser decimal)
    - Instrumento (puede especificar múltiples instrumentos usando ?instrumento=Piano&instrumento=Saxofón)
    """
    # Normalizar los parámetros para que siempre sean listas
    if genero is not None and not isinstance(genero, list):
        genero = [genero]
    if instrumento is not None and not isinstance(instrumento, list):
        instrumento = [instrumento]

    result = crud.musica.get_musicas_filtered(
        db=session,
        musica_type=musica_type,
        genero=genero,
        canciones=canciones,
        min_duracion=min_duracion,
        max_duracion=max_duracion,
        instrumento=instrumento,
        skip=skip,
        limit=limit
    )
    
    return result

@router.get("/filter_me", response_model=ServiceMusicasOut)
def get_musicas_filtered_me(
    session: SessionDep,
    current_user: CurrentUser,
    musica_type: Optional[MusicaEstilo] = (None),
    genero: Optional[List[Generos]] = Query(default=None, description="Puedes añadir varios: ?genero=rock&genero=salsa"),
    canciones: Optional[Canciones] = None,
    min_duracion: Optional[float] = None,
    max_duracion: Optional[float] = None,
    instrumento: Optional[List[str]] = Query(default=None, description="Puedes añadir varios: ?instrumento=Piano&instrumento=Saxofón"),
    skip: int = Query(0, ge=0),
    limit: int = Query(10, ge=1, le=100)
) -> ServiceMusicasOut:
    """
    Obtener servicios de música del usuario actual con filtros opcionales:
    - Tipo de música (DJ/Músico)
    - Género musical
    - Tipo de canciones (propias/versiones)
    - Duración mínima (en horas, puede ser decimal)
    - Duración máxima (en horas, puede ser decimal)
    - Instrumento
    """
    result = crud.musica.get_musicas_filtered(
        db=session,
        musica_type=musica_type,
        genero=genero,
        canciones=canciones,
        min_duracion=min_duracion,
        max_duracion=max_duracion,
        instrumento=instrumento,
        account_id=current_user.id,
        skip=skip,
        limit=limit
    )
    
    return result

@router.put("/{musica_id}", response_model=ServiceMusicaOut)
def update_musica(
    musica_id: UUID,
    musica_in: ServiceUpdateMusica,
    session: SessionDep,
    current_user: CurrentUser
) -> ServiceMusicaOut:
    """
    Actualizar un servicio de música existente
    """
    musica = crud.musica.get_musica(db=session, musica_id=musica_id)
    if not musica:
        raise HTTPException(status_code=404, detail="Servicio de música no encontrado")
    
    # Verificar permisos (superusuario o propietario)
    if not current_user.is_superuser and musica.account_id != current_user.id:
        raise HTTPException(status_code=403, detail="No tienes permiso para modificar este servicio")
    
    return crud.musica.update_musica(
        db=session, 
        musica_id=musica_id, 
        musica_in=musica_in
    )

@router.patch("/{musica_id}", response_model=ServiceMusicaOut)
def patch_musica(
    musica_id: UUID,
    musica_in: ServiceUpdateMusica,
    session: SessionDep,
    current_user: CurrentUser
) -> ServiceMusicaOut:
    """
    Actualizar parcialmente un servicio de música existente
    """
    musica = crud.musica.get_musica(db=session, musica_id=musica_id)
    if not musica:
        raise HTTPException(status_code=404, detail="Servicio de música no encontrado")
    
    # Verificar permisos (superusuario o propietario)
    if not current_user.is_superuser and musica.account_id != current_user.id:
        raise HTTPException(status_code=403, detail="No tienes permiso para modificar este servicio")
    
    return crud.musica.update_musica(
        db=session, 
        musica_id=musica_id, 
        musica_in=musica_in
    )

@router.delete("/{musica_id}")
def delete_musica(
    musica_id: UUID,
    session: SessionDep,
    current_user: CurrentUser
):
    """
    Eliminar un servicio de música
    """
    musica = crud.musica.get_musica(db=session, musica_id=musica_id)
    if not musica:
        raise HTTPException(status_code=404, detail="Servicio de música no encontrado")
    
    # Verificar permisos (superusuario o propietario)
    if not current_user.is_superuser and musica.account_id != current_user.id:
        raise HTTPException(status_code=403, detail="No tienes permiso para eliminar este servicio")
    
    if not crud.musica.delete_musica(db=session, musica_id=musica_id):
        raise HTTPException(status_code=404, detail="Servicio de música no encontrado")
    
    return {"Servicio de música eliminado correctamente"} 