"""Perfil de músico del usuario autenticado: crear/editar, ubicación, disponibilidad, media."""
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status
from sqlalchemy.orm import Session

from app import models
from app.catalog import VALID_SLUGS
from app.core import security
from app.core.database import get_db
from app.schemas.musician import (
    LocationIn,
    MediaItemOut,
    MusicianDetailOut,
    MusicianOut,
    MusicianUpsertIn,
    VideoLinkIn,
)
from app.services.geo import point, to_detail, to_out
from app.services.storage import ALLOWED_IMAGE_TYPES, MAX_IMAGE_BYTES, storage

router = APIRouter(prefix="/musicians", tags=["musicians"])


def _validate_services(slugs: list[str]) -> None:
    invalid = [s for s in slugs if s not in VALID_SLUGS]
    if invalid:
        raise HTTPException(
            status.HTTP_422_UNPROCESSABLE_ENTITY,
            f"Tipos de servicio inválidos: {', '.join(invalid)}",
        )


def _my_profile(current: models.User) -> models.MusicianProfile:
    """Perfil de músico del usuario, o error si todavía no lo creó."""
    if current.musician_profile is None:
        raise HTTPException(status.HTTP_400_BAD_REQUEST, "Primero creá tu perfil de músico")
    return current.musician_profile


def _detect_provider(url: str) -> str:
    u = url.lower()
    if "youtube.com" in u or "youtu.be" in u:
        return "youtube"
    if "instagram.com" in u:
        return "instagram"
    if "tiktok.com" in u:
        return "tiktok"
    if "vimeo.com" in u:
        return "vimeo"
    return "video"


@router.get("/me", response_model=MusicianDetailOut | None)
def get_my_profile(current: models.User = Depends(security.get_current_user)):
    """Perfil del músico logueado para editar (None si todavía no lo creó)."""
    return to_detail(current.musician_profile) if current.musician_profile else None


@router.get("/{musician_id}", response_model=MusicianDetailOut)
def get_musician(musician_id: int, db: Session = Depends(get_db)):
    profile = db.get(models.MusicianProfile, musician_id)
    if not profile:
        raise HTTPException(status.HTTP_404_NOT_FOUND, "Músico no encontrado")
    return to_detail(profile)


@router.put("/me", response_model=MusicianOut)
def upsert_my_profile(
    data: MusicianUpsertIn,
    db: Session = Depends(get_db),
    current: models.User = Depends(security.get_current_user),
):
    """Crea o actualiza el perfil de músico de la cuenta autenticada."""
    _validate_services(data.service_types)

    profile = current.musician_profile
    if profile is None:
        profile = models.MusicianProfile(user_id=current.id)
        db.add(profile)

    for field, value in data.model_dump().items():
        setattr(profile, field, value)

    db.commit()
    db.refresh(profile)
    return to_out(profile)


@router.patch("/me/location", response_model=MusicianOut)
def update_my_location(
    data: LocationIn,
    db: Session = Depends(get_db),
    current: models.User = Depends(security.get_current_user),
):
    """Actualiza ubicación en vivo y, opcionalmente, la disponibilidad."""
    profile = current.musician_profile
    if profile is None:
        raise HTTPException(status.HTTP_400_BAD_REQUEST, "Primero creá tu perfil de músico")

    profile.location = point(data.lat, data.lng)
    if data.is_available is not None:
        profile.is_available = data.is_available

    db.commit()
    db.refresh(profile)
    return to_out(profile)


def _next_position(profile: models.MusicianProfile) -> int:
    return (max((m.position for m in profile.media), default=-1)) + 1


@router.post("/me/media/photo", response_model=MediaItemOut, status_code=status.HTTP_201_CREATED)
async def upload_photo(
    file: UploadFile = File(...),
    db: Session = Depends(get_db),
    current: models.User = Depends(security.get_current_user),
):
    """Sube una foto del portfolio (jpg/png/webp, hasta 5 MB) al storage."""
    profile = _my_profile(current)

    ext = ALLOWED_IMAGE_TYPES.get(file.content_type or "")
    if not ext:
        raise HTTPException(status.HTTP_422_UNPROCESSABLE_ENTITY, "Formato inválido: solo JPG, PNG o WEBP")

    data = await file.read()
    if len(data) > MAX_IMAGE_BYTES:
        raise HTTPException(status.HTTP_413_REQUEST_ENTITY_TOO_LARGE, "La foto supera los 5 MB")

    url = storage.save(data, ext)
    item = models.MediaItem(
        musician_id=profile.id, kind="photo", url=url, provider="upload",
        position=_next_position(profile),
    )
    db.add(item)
    db.commit()
    db.refresh(item)
    return MediaItemOut.model_validate(item)


@router.post("/me/media/video", response_model=MediaItemOut, status_code=status.HTTP_201_CREATED)
def add_video(
    data: VideoLinkIn,
    db: Session = Depends(get_db),
    current: models.User = Depends(security.get_current_user),
):
    """Agrega un video al portfolio por link (detecta la plataforma)."""
    profile = _my_profile(current)

    if data.is_featured:
        # Solo un video destacado a la vez.
        for m in profile.media:
            m.is_featured = False

    item = models.MediaItem(
        musician_id=profile.id, kind="video", url=data.url, provider=_detect_provider(data.url),
        caption=data.caption, is_featured=data.is_featured, position=_next_position(profile),
    )
    db.add(item)
    db.commit()
    db.refresh(item)
    return MediaItemOut.model_validate(item)


@router.delete("/me/media/{media_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_media(
    media_id: int,
    db: Session = Depends(get_db),
    current: models.User = Depends(security.get_current_user),
):
    """Borra un ítem del portfolio (y la foto del storage si era subida)."""
    profile = _my_profile(current)
    item = db.get(models.MediaItem, media_id)
    if not item or item.musician_id != profile.id:
        raise HTTPException(status.HTTP_404_NOT_FOUND, "Media no encontrada")

    if item.kind == "photo" and item.provider == "upload":
        storage.delete(item.url)
    db.delete(item)
    db.commit()
