"""
playlist_browser.py — Dialog til at hente og gemme danselister med tag-organisering.

Viser en liste over alle gemte danselister med:
  - Navn, dato, antal sange
  - Tag-filtrering i venstre side
  - Gem ny liste med tags
"""

from PyQt6.QtWidgets import (
    QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit,
    QPushButton, QListWidget, QListWidgetItem, QWidget,
    QSplitter, QFrame, QMessageBox, QInputDialog,
)
from PyQt6.QtCore import Qt, pyqtSignal
from PyQt6.QtGui import QColor


class PlaylistBrowserDialog(QDialog):
    """Kombineret gem/hent dialog til danselister."""

    playlist_selected = pyqtSignal(str, str)  # playlist_id, name
    sync_requested    = pyqtSignal()           # bed main_window om at køre sync

    def __init__(self, mode: str = "load", current_songs: list = None,
                 current_name: str = "", parent=None):
        super().__init__(parent)
        self._mode = mode  # "load" eller "save"
        self._current_songs = current_songs or []
        self._current_name = current_name
        self._all_playlists = []
        self._active_tag = None

        title = "Gem danseliste" if mode == "save" else "Hent danseliste"
        self.setWindowTitle(title)
        self.setMinimumSize(700, 480)
        self.resize(780, 520)

        self._build_ui()
        self._load_data()

    def _build_ui(self):
        layout = QVBoxLayout(self)
        layout.setContentsMargins(12, 12, 12, 12)
        layout.setSpacing(8)

        # Gem-felter (kun i save-mode)
        if self._mode == "save":
            save_frame = QFrame()
            save_frame.setObjectName("track_display")
            save_layout = QVBoxLayout(save_frame)
            save_layout.setContentsMargins(10, 8, 10, 8)

            row1 = QHBoxLayout()
            row1.addWidget(QLabel("Navn:"))
            self._name_input = QLineEdit()
            self._name_input.setText(self._current_name)
            self._name_input.setPlaceholderText("Navn på danselisten...")
            row1.addWidget(self._name_input)
            save_layout.addLayout(row1)

            row2 = QHBoxLayout()
            row2.addWidget(QLabel("Tags:"))
            self._tags_input = QLineEdit()
            self._tags_input.setPlaceholderText("stævne, øvning, workshop  (komma-separeret)")
            self._tags_input.textChanged.connect(self._suggest_tags)
            row2.addWidget(self._tags_input)
            save_layout.addLayout(row2)

            # Tag-forslag
            self._tag_suggestions = QListWidget()
            self._tag_suggestions.setMaximumHeight(80)
            self._tag_suggestions.hide()
            self._tag_suggestions.itemClicked.connect(self._add_tag_suggestion)
            save_layout.addWidget(self._tag_suggestions)

            lbl = QLabel(f"{len(self._current_songs)} sange vil blive gemt")
            lbl.setObjectName("result_count")
            save_layout.addWidget(lbl)

            layout.addWidget(save_frame)

        # Splitter: tags til venstre, lister til højre
        splitter = QSplitter(Qt.Orientation.Horizontal)

        # ── Venstre: tag-filtrering ──
        tag_panel = QWidget()
        tag_layout = QVBoxLayout(tag_panel)
        tag_layout.setContentsMargins(0, 0, 0, 0)
        tag_layout.setSpacing(4)
        lbl_tags = QLabel("FILTRÉR PÅ TAG")
        lbl_tags.setObjectName("section_title")
        tag_layout.addWidget(lbl_tags)
        self._tag_list = QListWidget()
        self._tag_list.currentItemChanged.connect(self._on_tag_selected)
        tag_layout.addWidget(self._tag_list)
        tag_panel.setMaximumWidth(180)
        splitter.addWidget(tag_panel)

        # ── Højre: danseliste-oversigt ──
        list_panel = QWidget()
        list_layout = QVBoxLayout(list_panel)
        list_layout.setContentsMargins(0, 0, 0, 0)
        list_layout.setSpacing(4)

        # Søgefelt
        self._search = QLineEdit()
        self._search.setPlaceholderText("Søg i navn...")
        self._search.textChanged.connect(self._filter)
        list_layout.addWidget(self._search)

        self._count_label = QLabel("")
        self._count_label.setObjectName("result_count")
        list_layout.addWidget(self._count_label)

        self._list = QListWidget()
        self._list.itemDoubleClicked.connect(self._on_double_click)
        list_layout.addWidget(self._list)
        splitter.addWidget(list_panel)

        splitter.setSizes([160, 580])
        layout.addWidget(splitter, stretch=1)

        # Knapper
        btn_row = QHBoxLayout()

        if self._mode == "load":
            btn_delete = QPushButton("🗑  Slet valgte")
            btn_delete.clicked.connect(self._delete_selected)
            btn_row.addWidget(btn_delete)
            btn_tags = QPushButton("🏷  Rediger tags")
            btn_tags.clicked.connect(self._edit_tags)
            btn_row.addWidget(btn_tags)
            btn_share = QPushButton("↗  Del...")
            btn_share.clicked.connect(self._share_selected)
            btn_row.addWidget(btn_share)
            btn_shared = QPushButton("🌐  Hent delte")
            btn_shared.clicked.connect(self._fetch_shared)
            btn_row.addWidget(btn_shared)

        btn_row.addStretch()
        btn_cancel = QPushButton("Annuller")
        btn_cancel.clicked.connect(self.reject)
        btn_row.addWidget(btn_cancel)

        if self._mode == "save":
            btn_ok = QPushButton("💾  Gem")
            btn_ok.setObjectName("btn_play")
            btn_ok.clicked.connect(self._save)
        else:
            btn_ok = QPushButton("📂  Hent valgte")
            btn_ok.setObjectName("btn_play")
            btn_ok.clicked.connect(self._load_selected)
        btn_row.addWidget(btn_ok)

        layout.addLayout(btn_row)

    def _load_data(self):
        try:
            from local.local_db import get_playlists, get_all_playlist_tags
            self._all_playlists = [dict(r) for r in get_playlists()]

            # Udfyld tag-liste
            self._tag_list.clear()
            all_item = QListWidgetItem("Alle lister")
            all_item.setData(Qt.ItemDataRole.UserRole, None)
            self._tag_list.addItem(all_item)

            for tag in get_all_playlist_tags():
                item = QListWidgetItem(f"# {tag}")
                item.setData(Qt.ItemDataRole.UserRole, tag)
                self._tag_list.addItem(item)

            self._tag_list.setCurrentRow(0)
            self._render(self._all_playlists)
        except Exception as e:
            print(f"Playlist browser load fejl: {e}")

    def _on_tag_selected(self, current, previous):
        if not current:
            return
        self._active_tag = current.data(Qt.ItemDataRole.UserRole)
        self._filter()

    def _suggest_tags(self, text: str):
        """Vis forslag til det sidst indtastede tag."""
        if not hasattr(self, '_tag_suggestions'):
            return
        parts = text.split(",")
        prefix = parts[-1].strip().lower()
        if not prefix:
            self._tag_suggestions.hide()
            return
        try:
            from local.local_db import get_all_playlist_tags
            all_tags = get_all_playlist_tags()
            matches = [t for t in all_tags
                      if t.startswith(prefix) and t not in
                      [p.strip().lower() for p in parts[:-1]]]
            if matches:
                self._tag_suggestions.clear()
                for t in matches[:5]:
                    self._tag_suggestions.addItem(t)
                self._tag_suggestions.show()
            else:
                self._tag_suggestions.hide()
        except Exception:
            self._tag_suggestions.hide()

    def _add_tag_suggestion(self, item):
        """Tilføj et foreslået tag til tekstfeltet."""
        parts = self._tags_input.text().split(",")
        parts[-1] = " " + item.text()
        self._tags_input.setText(",".join(parts) + ", ")
        self._tag_suggestions.hide()
        self._tags_input.setFocus()

    def _edit_tags(self):
        """Rediger tags på den valgte liste."""
        item = self._list.currentItem()
        if not item:
            return
        pl = item.data(Qt.ItemDataRole.UserRole)
        if not pl or not isinstance(pl, dict):
            return
        from PyQt6.QtWidgets import QInputDialog
        current = pl.get("tags", "")
        new_tags, ok = QInputDialog.getText(
            self, "Rediger tags", "Tags (komma-separeret):", text=current
        )
        if ok:
            try:
                from local.local_db import update_playlist_tags
                update_playlist_tags(pl["id"], new_tags.strip())
                self._load_data()
            except Exception as e:
                QMessageBox.warning(self, "Fejl", f"Kunne ikke opdatere tags: {e}")

    def _filter(self):
        query = self._search.text().strip().lower()
        tag = self._active_tag

        filtered = self._all_playlists
        if tag:
            filtered = [
                p for p in filtered
                if tag in [t.strip().lower() for t in p.get("tags", "").split(",")]
            ]
        if query:
            filtered = [p for p in filtered if query in p["name"].lower()]

        self._render(filtered)

    def _render(self, playlists: list):
        self._list.clear()
        self._count_label.setText(f"{len(playlists)} liste{'r' if len(playlists) != 1 else ''}")

        for pl in playlists:
            date = pl.get("created_at", "")[:10]
            count = pl.get("song_count", 0)
            tags = pl.get("tags", "")
            tag_str = f"  [{tags}]" if tags else ""

            item = QListWidgetItem(
                f"{pl['name']}\n"
                f"  {date}  ·  {count} sange{tag_str}"
            )
            item.setData(Qt.ItemDataRole.UserRole, pl)
            self._list.addItem(item)

    def _on_double_click(self, item: QListWidgetItem):
        if self._mode == "load":
            self._load_selected()
        else:
            self._save()

    def _load_selected(self):
        item = self._list.currentItem()
        if not item:
            QMessageBox.information(self, "Vælg", "Vælg en liste først.")
            return
        pl = item.data(Qt.ItemDataRole.UserRole)
        self.playlist_selected.emit(pl["id"], pl["name"])
        self.accept()

    def _save(self):
        name = self._name_input.text().strip()
        if not name:
            QMessageBox.warning(self, "Navn mangler", "Angiv et navn til danselisten.")
            self._name_input.setFocus()
            return
        tags = self._tags_input.text().strip()

        # Tjek om navn allerede eksisterer
        existing = [p for p in self._all_playlists
                   if p["name"].lower() == name.lower()]
        if existing:
            reply = QMessageBox.question(
                self, "Navn eksisterer allerede",
                f"Der findes allerede en liste med navnet '{name}'.\n"
                f"Vil du overskrive den?",
                QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
            )
            if reply == QMessageBox.StandardButton.Yes:
                try:
                    from local.local_db import get_db, add_song_to_playlist
                    pl_id = existing[0]["id"]
                    with get_db() as conn:
                        conn.execute(
                            "DELETE FROM playlist_songs WHERE playlist_id=?", (pl_id,)
                        )
                        if tags:
                            conn.execute(
                                "UPDATE playlists SET tags=? WHERE id=?", (tags, pl_id)
                            )
                    for i, song in enumerate(self._current_songs, start=1):
                        if song.get("id"):
                            add_song_to_playlist(pl_id, song["id"],
                                                  file_id=song.get("file_id"),
                                                  position=i)
                    self.playlist_selected.emit(pl_id, name)
                    self.accept()
                except Exception as e:
                    QMessageBox.warning(self, "Fejl", f"Kunne ikke overskrive: {e}")
            return

        try:
            from local.local_db import create_playlist, add_song_to_playlist
            pl_id = create_playlist(name, tags=tags)
            for i, song in enumerate(self._current_songs, start=1):
                if song.get("id"):
                    add_song_to_playlist(pl_id, song["id"],
                                          file_id=song.get("file_id"),
                                          position=i)
            self.playlist_selected.emit(pl_id, name)
            self.accept()
        except Exception as e:
            QMessageBox.warning(self, "Fejl", f"Kunne ikke gemme: {e}")

    def _delete_selected(self):
        item = self._list.currentItem()
        if not item:
            return
        pl = item.data(Qt.ItemDataRole.UserRole)
        reply = QMessageBox.question(
            self, "Slet danseliste",
            f"Slet '{pl['name']}'?\n\nDette kan ikke fortrydes.",
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
        )
        if reply == QMessageBox.StandardButton.Yes:
            try:
                from local.local_db import delete_playlist
                delete_playlist(pl["id"])
                self._load_data()
                # Signal til main_window om at køre sync
                self.sync_requested.emit()
            except Exception as e:
                QMessageBox.warning(self, "Fejl", f"Kunne ikke slette: {e}")

    def _share_selected(self):
        """Åbn del-dialog for den valgte playliste."""
        item = self._list.currentItem()
        if not item:
            QMessageBox.information(self, "Del", "Vælg en playliste først.")
            return
        pl = item.data(Qt.ItemDataRole.UserRole)
        if not isinstance(pl, dict):
            return

        # Hent server-info fra settings
        try:
            from ui.settings_dialog import load_settings
            s = load_settings()
            server_url = s.get("server_url", "")
            token = self._get_token()
            if not token:
                QMessageBox.warning(self, "Ikke logget ind",
                                    "Du skal være logget ind for at dele.")
                return

            # Find server-ID for playlisten
            server_id = pl.get("api_project_id")
            if not server_id:
                QMessageBox.warning(self, "Ikke synkroniseret",
                                    "Synkroniser playlisten til serveren først\n"
                                    "(Filer → Synkroniser nu).")
                return

            from ui.share_dialog import ShareDialog
            dlg = ShareDialog(server_id, pl["name"], server_url, token,
                              parent=self)
            dlg.exec()
        except Exception as e:
            QMessageBox.warning(self, "Fejl", str(e))

    def _get_token(self) -> str | None:
        """Hent JWT token fra main_window."""
        mw = self.parent()
        while mw and not hasattr(mw, "_api_token"):
            mw = mw.parent()
        return getattr(mw, "_api_token", None) if mw else None

    def _fetch_shared(self):
        """Hent playlister der er delt med mig fra serveren."""
        try:
            from ui.settings_dialog import load_settings
            s = load_settings()
            server_url = s.get("server_url", "").rstrip("/")
            token = self._get_token()
            if not token:
                QMessageBox.warning(self, "Ikke logget ind",
                                    "Du skal være logget ind for at hente delte lister.")
                return

            import urllib.request, json
            req = urllib.request.Request(
                f"{server_url}/sharing/playlists/shared-with-me",
                headers={"Authorization": f"Bearer {token}"}
            )
            with urllib.request.urlopen(req, timeout=10) as resp:
                shared = json.loads(resp.read())

            if not shared:
                QMessageBox.information(self, "Ingen delte lister",
                                        "Ingen playlister er delt med dig.")
                return

            # Vis valgdialog
            from PyQt6.QtWidgets import QInputDialog
            options = [
                f"{p['name']}  (af {p['owner']}, {p['song_count']} sange, {p['permission']})"
                for p in shared
            ]
            choice, ok = QInputDialog.getItem(
                self, "Hent delt playliste",
                "Vælg en playliste at hente:",
                options, 0, False
            )
            if not ok:
                return

            idx = options.index(choice)
            chosen = shared[idx]

            # Hent indholdet
            req2 = urllib.request.Request(
                f"{server_url}/sharing/playlists/{chosen['project_id']}",
                headers={"Authorization": f"Bearer {token}"}
            )
            with urllib.request.urlopen(req2, timeout=10) as resp:
                pl_data = json.loads(resp.read())

            self._import_shared_playlist(pl_data, server_url, token,
                                        permission=chosen.get("permission", "view"))

        except Exception as e:
            QMessageBox.warning(self, "Fejl", f"Kunne ikke hente: {e}")

    def _import_shared_playlist(self, pl_data: dict, server_url: str, token: str,
                                permission: str = "view"):
        """Importer en delt playliste som en linket liste."""
        import sqlite3
        from local.local_db import DB_PATH, get_db, add_song_to_playlist

        name       = pl_data["name"]
        server_id  = pl_data["id"]

        conn = sqlite3.connect(str(DB_PATH))
        conn.row_factory = sqlite3.Row

        # Tjek om listen allerede er linket
        existing = conn.execute(
            "SELECT id FROM playlists WHERE api_project_id=?", (server_id,)
        ).fetchone()
        conn.close()

        if existing:
            # Opdater eksisterende
            pl_id = existing["id"]
            with get_db() as c:
                c.execute("DELETE FROM playlist_songs WHERE playlist_id=?", (pl_id,))
        else:
            # Opret ny linket playliste
            with get_db() as c:
                c.execute(
                    "INSERT INTO playlists (name, api_project_id, is_linked, server_permission) "
                    "VALUES (?, ?, 1, ?)",
                    (name, server_id, permission)
                )
                pl_id = c.execute("SELECT last_insert_rowid()").fetchone()[0]

        # Indsæt sange med sang-matching
        matched = 0
        with get_db() as c:
            for song_data in pl_data.get("songs", []):
                local = c.execute(
                    "SELECT id FROM songs WHERE title=? AND artist=? AND file_missing=0",
                    (song_data["title"], song_data["artist"])
                ).fetchone()
                if local:
                    c.execute(
                        "INSERT INTO playlist_songs "
                        "(playlist_id, song_id, position, status, is_workshop, dance_override) "
                        "VALUES (?,?,?,?,?,?)",
                        (pl_id, local["id"], song_data["position"],
                         song_data.get("status", "pending"),
                         1 if song_data.get("is_workshop") else 0,
                         song_data.get("dance_override") or "")
                    )
                    matched += 1

        self._load_data()
        self.playlist_selected.emit(pl_id, name)
        perm_text = {"view": "se", "copy": "kopiere", "edit": "redigere"}.get(
            permission, permission
        )
        QMessageBox.information(
            self, "Linket",
            f"'{name}' er nu linket til server-listen.\n"
            f"Du har rettighed til at {perm_text} listen.\n\n"
            f"{matched} af {len(pl_data.get('songs', []))} sange fundet lokalt."
        )