import json
from fastapi import APIRouter, WebSocket, WebSocketDisconnect, Depends, Query
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.models import Project, ProjectSong

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


class ConnectionManager:
    def __init__(self):
        # project_id -> liste af aktive forbindelser
        self.rooms: dict[str, list[WebSocket]] = {}

    async def connect(self, project_id: str, ws: WebSocket):
        await ws.accept()
        self.rooms.setdefault(project_id, []).append(ws)

    def disconnect(self, project_id: str, ws: WebSocket):
        if project_id in self.rooms:
            self.rooms[project_id].discard(ws) if hasattr(self.rooms[project_id], 'discard') else None
            try:
                self.rooms[project_id].remove(ws)
            except ValueError:
                pass

    async def broadcast(self, project_id: str, message: dict):
        dead = []
        for ws in self.rooms.get(project_id, []):
            try:
                await ws.send_text(json.dumps(message))
            except Exception:
                dead.append(ws)
        for ws in dead:
            self.disconnect(project_id, ws)


manager = ConnectionManager()


@router.websocket("/{project_id}")
async def project_live(
    project_id: str,
    websocket: WebSocket,
    db: Session = Depends(get_db),
):
    project = db.query(Project).filter(Project.id == project_id).first()
    if not project:
        await websocket.close(code=4004)
        return

    await manager.connect(project_id, websocket)

    # Send nuværende tilstand med det samme ved opkobling
    songs = db.query(ProjectSong).filter_by(project_id=project_id).order_by(ProjectSong.position).all()
    await websocket.send_text(json.dumps({
        "event": "state",
        "project_id": project_id,
        "songs": [
            {"id": ps.id, "position": ps.position, "status": ps.status, "song_id": ps.song_id}
            for ps in songs
        ],
    }))

    try:
        while True:
            await websocket.receive_text()  # hold forbindelsen åben
    except WebSocketDisconnect:
        manager.disconnect(project_id, websocket)


async def notify_status_change(project_id: str, project_song_id: str, new_status: str):
    """Kaldes fra projects-router når en sangs status ændres."""
    await manager.broadcast(project_id, {
        "event": "status_update",
        "project_song_id": project_song_id,
        "status": new_status,
    })
