"""
linked_playlist.py — Håndter linkede server-playlister.
Pull ved åbning, push ved gem.
"""
import json
import sqlite3
import urllib.request
import urllib.error
import logging
from pathlib import Path

logger = logging.getLogger(__name__)


class LinkedPlaylistManager:
    def __init__(self, db_path: str, server_url: str, token: str):
        self._db_path    = db_path
        self._server_url = server_url.rstrip("/")
        self._token      = token

    def _headers(self):
        return {
            "Content-Type":  "application/json",
            "Authorization": f"Bearer {self._token}",
        }

    def pull(self, playlist_id: int) -> list[dict]:
        """
        Hent seneste version fra serveren og opdater lokal liste.
        Returnerer sang-liste klar til playlist_panel.
        """
        conn = sqlite3.connect(self._db_path)
        conn.row_factory = sqlite3.Row

        pl = conn.execute(
            "SELECT api_project_id, server_permission FROM playlists WHERE id=?",
            (playlist_id,)
        ).fetchone()
        if not pl or not pl["api_project_id"]:
            conn.close()
            return []

        # Hent fra server
        req = urllib.request.Request(
            f"{self._server_url}/sharing/playlists/{pl['api_project_id']}",
            headers=self._headers()
        )
        with urllib.request.urlopen(req, timeout=10) as resp:
            data = json.loads(resp.read())

        # Slet eksisterende sange og erstat med server-version
        conn.execute(
            "DELETE FROM playlist_songs WHERE playlist_id=?", (playlist_id,)
        )

        songs = []
        for song_data in sorted(data.get("songs", []), key=lambda x: x["position"]):
            # Match lokalt på titel+artist
            local = conn.execute(
                "SELECT id, local_path, bpm, duration_sec, file_format, file_missing "
                "FROM songs WHERE title=? AND artist=? AND file_missing=0 LIMIT 1",
                (song_data["title"], song_data["artist"])
            ).fetchone()

            if local:
                conn.execute("""
                    INSERT OR IGNORE INTO playlist_songs
                    (playlist_id, song_id, position, status, is_workshop, dance_override)
                    VALUES (?,?,?,?,?,?)
                """, (
                    playlist_id, local["id"],
                    song_data["position"], song_data["status"],
                    1 if song_data.get("is_workshop") else 0,
                    song_data.get("dance_override", ""),
                ))

                # Hent danse
                dances = conn.execute("""
                    SELECT d.name FROM song_dances sd
                    JOIN dances d ON d.id = sd.dance_id
                    WHERE sd.song_id=? ORDER BY sd.dance_order
                """, (local["id"],)).fetchall()

                songs.append({
                    "id":           local["id"],
                    "title":        song_data["title"],
                    "artist":       song_data["artist"],
                    "album":        song_data.get("album", ""),
                    "bpm":          local["bpm"] or 0,
                    "duration_sec": local["duration_sec"] or 0,
                    "local_path":   local["local_path"],
                    "file_format":  local["file_format"] or "",
                    "file_missing": False,
                    "dances":       [d["name"] for d in dances],
                    "active_dance": song_data.get("dance_override", ""),
                    "is_workshop":  bool(song_data.get("is_workshop")),
                    "status":       song_data.get("status", "pending"),
                })

        conn.commit()
        conn.close()
        return songs

    def push(self, playlist_id: int):
        """Push lokal version til serveren."""
        conn = sqlite3.connect(self._db_path)
        conn.row_factory = sqlite3.Row

        pl = conn.execute(
            "SELECT api_project_id, server_permission, name FROM playlists WHERE id=?",
            (playlist_id,)
        ).fetchone()
        if not pl or not pl["api_project_id"]:
            conn.close()
            raise Exception("Playlisten er ikke linket til serveren")

        if pl["server_permission"] not in ("edit",):
            conn.close()
            raise Exception(f"Du har ikke rettighed til at redigere denne liste (du har: {pl['server_permission']})")

        # Byg payload til sync/push
        songs_raw = conn.execute("""
            SELECT s.id, s.title, s.artist, s.album, s.bpm, s.duration_sec,
                   s.file_format, ps.position, ps.status, ps.is_workshop, ps.dance_override
            FROM playlist_songs ps
            JOIN songs s ON s.id = ps.song_id
            WHERE ps.playlist_id=? ORDER BY ps.position
        """, (playlist_id,)).fetchall()
        conn.close()

        from local.sync_manager import SyncManager
        mgr = SyncManager(self._db_path, self._server_url, self._token)

        # Byg mini-payload med kun denne playliste
        song_ids = [row["id"] for row in songs_raw]
        songs_payload = []
        for row in songs_raw:
            songs_payload.append({
                "local_id": str(row["id"]),
                "title": row["title"] or "",
                "artist": row["artist"] or "",
                "album": row["album"] or "",
                "bpm": row["bpm"] or 0,
                "duration_sec": row["duration_sec"] or 0,
                "file_format": row["file_format"] or "",
            })

        pl_payload = [{
            "local_id": str(playlist_id),
            "name": pl["name"],
            "description": "",
            "tags": "",
            "visibility": "shared",
            "songs": [
                {
                    "song_local_id": str(row["id"]),
                    "position": int(row["position"]),
                    "status": row["status"] or "pending",
                    "is_workshop": bool(row["is_workshop"]),
                    "dance_override": row["dance_override"] or "",
                }
                for row in songs_raw
            ]
        }]

        result = mgr._post("/sync/push", {
            "songs": songs_payload,
            "dances": [],
            "song_dances": [],
            "song_alts": [],
            "playlists": pl_payload,
        })
        return result
