"""
tag_editor.py — Rediger danse og alternativ-danse.
Dans = navn + niveau kombination. Autoudfyld viser "Navn / Niveau".
"""

from PyQt6.QtWidgets import (
    QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit,
    QPushButton, QComboBox, QWidget, QMessageBox, QGroupBox,
    QScrollArea, QFrame, QListWidget, QListWidgetItem,
)
from PyQt6.QtCore import Qt, QTimer


class DanceLineEdit(QLineEdit):
    """Simpelt tekstfelt til dans-navn i eksisterende rækker."""
    from PyQt6.QtCore import pyqtSignal
    dance_selected = pyqtSignal(dict)

    def __init__(self, placeholder="", parent=None):
        super().__init__(parent)
        self.setPlaceholderText(placeholder)

    def get_dance_info(self) -> dict:
        text = self.text().strip()
        if " / " in text:
            parts = text.split(" / ", 1)
            return {"name": parts[0].strip()}
        return {"name": text}


class TagEditorDialog(QDialog):
    def keyPressEvent(self, event):
        """Forhindre Enter i at lukke dialogen — bruges til at tilføje danse."""
        from PyQt6.QtCore import Qt as _Qt
        if event.key() in (_Qt.Key.Key_Return, _Qt.Key.Key_Enter):
            # Send Enter videre til det fokuserede widget i stedet for at lukke
            focused = self.focusWidget()
            if focused and focused is not self:
                focused.event(event)
            return
        super().keyPressEvent(event)
    def __init__(self, song: dict, parent=None):
        super().__init__(parent)
        self._song    = song
        self._levels  = []
        self._dances  = []   # fra DB: {dance_id, name, level_id, level_name, dance_order}
        self._alts    = []   # fra DB: {dance_id, name, level_id, level_name, note}

        self.setWindowTitle(f"Rediger tags — {song.get('title', '')}")
        self.setMinimumSize(860, 520)
        self.resize(980, 600)

        self._load_levels()
        self._load_existing()
        self._build_ui()

    def _load_levels(self):
        try:
            from local.local_db import get_dance_levels
            self._levels = [dict(r) for r in get_dance_levels()]
        except Exception:
            self._levels = []

    def _load_existing(self):
        try:
            from local.local_db import get_dances_for_song, get_alt_dances_for_song
            self._dances = get_dances_for_song(self._song.get("id"))
            self._alts   = get_alt_dances_for_song(self._song.get("id"))
        except Exception as e:
            print(f"load fejl: {e}")

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

        # Sang-info
        info = QFrame()
        info.setObjectName("track_display")
        il = QHBoxLayout(info)
        il.setContentsMargins(10, 8, 10, 8)
        lbl_t = QLabel(self._song.get("title", "—"))
        lbl_t.setObjectName("track_title")
        il.addWidget(lbl_t, stretch=1)
        fmt = self._song.get("file_format", "").lower()
        can_write = fmt in ("mp3", "flac", "ogg", "opus", "m4a")
        lbl_w = QLabel("✓ Danse skrives til filen" if can_write
                       else "⚠ Dette format understøtter ikke fil-skrivning")
        lbl_w.setObjectName("result_count")
        il.addWidget(lbl_w)
        layout.addWidget(info)

        # Hint om autoudfyld
        hint = QLabel("Skriv dansenavn — forslag vises som 'Navn / Niveau'. "
                      "Vælg fra listen for at få niveau automatisk.")
        hint.setObjectName("result_count")
        hint.setWordWrap(True)
        layout.addWidget(hint)

        # To kolonner — hoveddanse får mere plads
        cols = QHBoxLayout()
        cols.setSpacing(12)
        cols.addWidget(self._build_dances_panel(), stretch=3)
        cols.addWidget(self._build_alts_panel(),   stretch=2)
        layout.addLayout(cols, stretch=1)

        btn_row = QHBoxLayout()
        btn_row.addStretch()
        btn_cancel = QPushButton("Annuller")
        btn_cancel.clicked.connect(self.reject)
        btn_row.addWidget(btn_cancel)
        btn_save = QPushButton("💾  Gem tags")
        btn_save.setObjectName("btn_play")
        btn_save.clicked.connect(self._save)
        btn_row.addWidget(btn_save)
        layout.addLayout(btn_row)

    def _build_dances_panel(self) -> QGroupBox:
        from translations import _
        grp = QGroupBox(_("tags.dances"))
        layout = QVBoxLayout(grp)

        # Kolonneoverskrifter
        hdr = QWidget()
        hdr_layout = QHBoxLayout(hdr)
        hdr_layout.setContentsMargins(0, 0, 0, 0)
        hdr_layout.setSpacing(4)
        lbl_dans = QLabel("Dans")
        lbl_dans.setObjectName("result_count")
        lbl_niveau = QLabel("Niveau")
        lbl_niveau.setObjectName("result_count")
        lbl_niveau.setFixedWidth(130)
        lbl_choreo = QLabel("Koreograf")
        lbl_choreo.setObjectName("result_count")
        lbl_choreo.setFixedWidth(140)
        lbl_btn = QLabel("")   # plads til knapper
        lbl_btn.setFixedWidth(72)
        hdr_layout.addWidget(lbl_dans, stretch=2)
        hdr_layout.addWidget(lbl_niveau)
        hdr_layout.addWidget(lbl_choreo)
        hdr_layout.addWidget(lbl_btn)
        layout.addWidget(hdr)

        # Eksisterende danse
        scroll = QScrollArea()
        scroll.setWidgetResizable(True)
        scroll.setFrameShape(QFrame.Shape.NoFrame)
        container = QWidget()
        self._dance_layout = QVBoxLayout(container)
        self._dance_layout.setSpacing(4)
        self._dance_layout.addStretch()
        scroll.setWidget(container)
        layout.addWidget(scroll, stretch=1)
        self._dance_rows = []
        for d in self._dances:
            self._add_dance_row(d["name"], d["level_id"], d.get("choreographer", ""))

        # Søgefelt
        self._new_dance = QLineEdit()
        self._new_dance.setPlaceholderText("Søg dans eller koreograf...")
        self._new_dance.textChanged.connect(self._on_dance_search)
        self._new_dance.returnPressed.connect(self._on_add_dance)
        layout.addWidget(self._new_dance)

        # Forslags-liste
        self._dance_suggestions = QListWidget()
        self._dance_suggestions.setFixedHeight(150)
        self._dance_suggestions.setFocusPolicy(Qt.FocusPolicy.NoFocus)
        self._dance_suggestions.itemClicked.connect(
            lambda item: self._add_from_suggestion(item, "dance")
        )
        layout.addWidget(self._dance_suggestions)

        # Timer til debounce
        self._dance_search_timer = QTimer(self)
        self._dance_search_timer.setSingleShot(True)
        self._dance_search_timer.setInterval(150)
        self._dance_search_timer.timeout.connect(
            lambda: self._load_dance_suggestions(
                self._new_dance.text().strip(), self._dance_suggestions
            )
        )
        self._load_dance_suggestions("", self._dance_suggestions)
        return grp

    def _add_dance_row(self, name="", level_id=None, choreographer=""):
        try:
            from translations import _, translate_level
        except Exception:
            def _(key, **kw): return key.split(".")[-1]
            def translate_level(n): return n
        row_widget = QWidget()
        row_layout = QHBoxLayout(row_widget)
        row_layout.setContentsMargins(0, 0, 0, 0)
        row_layout.setSpacing(4)

        edit = DanceLineEdit("Dans...", self)
        edit.setText(name)
        edit.setToolTip(name)
        edit.textChanged.connect(lambda txt, e=edit: e.setToolTip(txt))
        row_layout.addWidget(edit, stretch=2)

        # Niveau-dropdown
        level_cb = QComboBox()
        level_cb.addItem(_("tags.no_level"), None)
        for lvl in self._levels:
            level_cb.addItem(translate_level(lvl["name"]), lvl["id"])
        if level_id is not None:
            for i in range(level_cb.count()):
                if level_cb.itemData(i) == level_id:
                    level_cb.setCurrentIndex(i)
                    break
        level_cb.setFixedWidth(130)
        row_layout.addWidget(level_cb)

        # Koreograf-felt med autocomplete
        choreo_edit = QLineEdit()
        choreo_edit.setText(choreographer)
        choreo_edit.setPlaceholderText("Koreograf...")
        choreo_edit.setFixedWidth(140)
        choreo_edit.setToolTip(choreographer)
        choreo_edit.textChanged.connect(
            lambda txt, ce=choreo_edit: (
                ce.setToolTip(txt),
                self._show_choreo_suggestions(txt, ce)
            )
        )
        row_layout.addWidget(choreo_edit)

        # Når autoudfyld vælger — opdater dropdown og koreograf
        def on_dance_selected(dance_info, cb=level_cb, ce=choreo_edit):
            if dance_info.get("level_id") is not None:
                for i in range(cb.count()):
                    if cb.itemData(i) == dance_info["level_id"]:
                        cb.setCurrentIndex(i)
                        break
            if dance_info.get("choreographer") and not ce.text().strip():
                ce.setText(dance_info["choreographer"])
        edit.dance_selected.connect(on_dance_selected)

        btn_info = QPushButton("•••")
        btn_info.setFixedSize(36, 24)
        btn_info.setToolTip("Åbn dans-info (link, video, noter)")
        btn_info.setObjectName("btn_info_row")
        btn_info.style().unpolish(btn_info)
        btn_info.style().polish(btn_info)
        row_layout.addWidget(btn_info)

        btn_rm = QPushButton("✕")
        btn_rm.setFixedSize(32, 24)
        btn_rm.setToolTip("Fjern dans")
        btn_rm.setObjectName("btn_rm_row")
        btn_rm.style().unpolish(btn_rm)
        btn_rm.style().polish(btn_rm)
        row_layout.addWidget(btn_rm)

        idx = self._dance_layout.count() - 1
        self._dance_layout.insertWidget(idx, row_widget)
        entry = {"widget": row_widget, "edit": edit, "level": level_cb, "choreo": choreo_edit}
        self._dance_rows.append(entry)
        btn_rm.clicked.connect(lambda: self._remove_dance_row(entry))
        btn_info.clicked.connect(lambda: self._open_dance_info(entry))

    def _create_dance(self):
        """Opret en ny dans i databasen uden at knytte den til musik."""
        from PyQt6.QtWidgets import QDialog, QFormLayout, QDialogButtonBox
        from PyQt6.QtCore import Qt

        dlg = QDialog(self)
        dlg.setWindowTitle("Opret dans")
        dlg.setFixedWidth(360)
        layout = QVBoxLayout(dlg)
        layout.setSpacing(8)

        form = QFormLayout()
        name_edit = QLineEdit()
        name_edit.setPlaceholderText("f.eks. Cowboy Cha Cha")
        form.addRow("Dans-navn:", name_edit)

        from PyQt6.QtWidgets import QComboBox
        level_cb = QComboBox()
        level_cb.addItem("— intet niveau —", None)
        for lvl in self._levels:
            level_cb.addItem(lvl["name"], lvl["id"])
        form.addRow("Niveau:", level_cb)

        choreo_edit = QLineEdit()
        choreo_edit.setPlaceholderText("Koreografens navn (valgfri)")
        form.addRow("Koreograf:", choreo_edit)

        layout.addLayout(form)

        btns = QDialogButtonBox(
            QDialogButtonBox.StandardButton.Ok |
            QDialogButtonBox.StandardButton.Cancel
        )
        btns.accepted.connect(dlg.accept)
        btns.rejected.connect(dlg.reject)
        layout.addWidget(btns)

        name_edit.setFocus()
        if dlg.exec():
            name   = name_edit.text().strip()
            choreo = choreo_edit.text().strip()
            level  = level_cb.currentData()
            if name:
                try:
                    from local.local_db import get_or_create_dance
                    get_or_create_dance(name, level, choreographer=choreo)
                    # Opdater forslagslisten
                    self._load_dance_suggestions("", self._dance_suggestions)
                    self._load_existing_dance_suggestions("", self._alt_suggestions)
                    self._new_dance.setPlaceholderText(f'"{name}" oprettet ✓')
                except Exception as e:
                    QMessageBox.warning(self, "Fejl", f"Kunne ikke oprette dans:\n{e}")

    def _remove_dance_row(self, entry):
        self._dance_rows.remove(entry)
        entry["widget"].deleteLater()

    def _on_dance_search(self):
        self._dance_search_timer.start()

    def _load_existing_dance_suggestions(self, prefix: str, list_widget):
        """Kun eksisterende danse fra DB — ingen nye kan oprettes herfra."""
        try:
            from local.local_db import get_dance_suggestions
            suggestions = get_dance_suggestions(prefix, limit=20)
            list_widget.clear()
            for s in suggestions:
                s = dict(s)
                parts = [s["name"]]
                if s.get("level_name"):
                    parts.append(s["level_name"])
                if s.get("choreographer"):
                    parts.append(s["choreographer"])
                label = "  /  ".join(parts)
                item = QListWidgetItem(label)
                item.setData(Qt.ItemDataRole.UserRole,     s.get("level_id"))
                item.setData(Qt.ItemDataRole.UserRole + 1, s["name"])
                item.setData(Qt.ItemDataRole.UserRole + 2, s.get("choreographer", ""))
                list_widget.addItem(item)
        except Exception:
            pass

    def _on_alt_search(self):
        self._alt_search_timer.start()

    def _open_dance_info(self, entry: dict):
        """Åbn dans-info dialog for den dans der er i denne række."""
        name = entry["edit"].text().strip()
        if not name:
            entry["edit"].setFocus()
            entry["edit"].setPlaceholderText("Skriv dans-navn først...")
            return
        from ui.dance_info_dialog import DanceInfoDialog
        dlg = DanceInfoDialog(song=self._song, parent=self)
        dlg.exec()
        # Opdater koreograf-feltet fra DB bagefter
        try:
            from local.local_db import get_db
            with get_db() as conn:
                row = conn.execute(
                    "SELECT choreographer FROM dances "
                    "WHERE name=? COLLATE NOCASE LIMIT 1", (name,)
                ).fetchone()
                if row and row["choreographer"]:
                    entry["choreo"].setText(row["choreographer"])
        except Exception:
            pass

    def _show_choreo_suggestions(self, prefix: str, source_edit: 'QLineEdit'):
        """Vis autocomplete popup for koreograf direkte under feltet."""
        pass  # Simpel løsning: autocomplete via QCompleter nedenfor

    def _load_dance_suggestions(self, prefix: str, list_widget):
        try:
            from local.local_db import get_dance_suggestions
            suggestions = get_dance_suggestions(prefix, limit=15)
            list_widget.clear()
            for s in suggestions:
                s = dict(s)
                parts = [s["name"]]
                if s.get("level_name"):
                    parts.append(s["level_name"])
                if s.get("choreographer"):
                    parts.append(s["choreographer"])
                label = "  /  ".join(parts)
                item = QListWidgetItem(label)
                item.setData(Qt.ItemDataRole.UserRole,     s.get("level_id"))
                item.setData(Qt.ItemDataRole.UserRole + 1, s["name"])
                item.setData(Qt.ItemDataRole.UserRole + 2, s.get("choreographer", ""))
                list_widget.addItem(item)
        except Exception as e:
            import logging
            logging.getLogger(__name__).warning(f"Dans-forslag fejl: {e}", exc_info=True)

    def _add_from_suggestion(self, item, panel: str):
        """Tilføj dans fra forslags-listen ved klik."""
        name       = item.data(Qt.ItemDataRole.UserRole + 1) or item.text().split(" / ")[0]
        level_id   = item.data(Qt.ItemDataRole.UserRole)
        choreographer = item.data(Qt.ItemDataRole.UserRole + 2) or ""
        if panel == "dance":
            self._add_dance_row(name, level_id, choreographer)
            self._new_dance.clear()
            self._new_dance.setFocus()
            self._load_dance_suggestions("", self._dance_suggestions)
        else:
            self._add_alt_row(name, level_id)
            self._new_alt.clear()
            self._new_alt.setFocus()
            self._load_dance_suggestions("", self._alt_suggestions)

    def _on_add_dance(self):
        text = self._new_dance.text().strip()
        if text:
            name, level_id = self._parse_name_level(text)
            self._add_dance_row(name, level_id)
            self._new_dance.clear()
            self._load_dance_suggestions("", self._dance_suggestions)

    def _parse_name_level(self, text: str) -> tuple:
        """Parse 'Navn / Niveau' og returnér (name, level_id)."""
        if " / " in text:
            parts = text.split(" / ", 1)
            name = parts[0].strip()
            level_name = parts[1].strip()
            for lvl in self._levels:
                if lvl["name"].lower() == level_name.lower():
                    return name, lvl["id"]
            return name, None
        return text, None

    def _build_alts_panel(self) -> QGroupBox:
        from translations import _
        grp = QGroupBox(_("tags.alts"))
        layout = QVBoxLayout(grp)

        # Eksisterende alternativ-rækker
        scroll = QScrollArea()
        scroll.setWidgetResizable(True)
        scroll.setFrameShape(QFrame.Shape.NoFrame)
        container = QWidget()
        self._alt_layout = QVBoxLayout(container)
        self._alt_layout.setSpacing(4)
        self._alt_layout.addStretch()
        scroll.setWidget(container)
        layout.addWidget(scroll, stretch=1)
        self._alt_rows = []
        for a in self._alts:
            self._add_alt_row(a["name"], a["level_id"], a.get("note", ""))

        # Søgefelt — kun eksisterende danse
        hint = QLabel("Søg blandt eksisterende danse:")
        hint.setObjectName("result_count")
        layout.addWidget(hint)

        self._new_alt = QLineEdit()
        self._new_alt.setPlaceholderText("Søg dans...")
        self._new_alt.textChanged.connect(self._on_alt_search)
        self._new_alt.returnPressed.connect(self._on_add_alt)
        layout.addWidget(self._new_alt)

        self._alt_suggestions = QListWidget()
        self._alt_suggestions.setFixedHeight(150)
        self._alt_suggestions.setFocusPolicy(Qt.FocusPolicy.NoFocus)
        self._alt_suggestions.itemClicked.connect(
            lambda item: self._add_from_suggestion(item, "alt")
        )
        layout.addWidget(self._alt_suggestions)

        self._alt_search_timer = QTimer(self)
        self._alt_search_timer.setSingleShot(True)
        self._alt_search_timer.setInterval(150)
        self._alt_search_timer.timeout.connect(
            lambda: self._load_existing_dance_suggestions(
                self._new_alt.text().strip(), self._alt_suggestions
            )
        )
        self._load_existing_dance_suggestions("", self._alt_suggestions)
        return grp

    def _add_alt_row(self, name="", level_id=None, note=""):
        try:
            from translations import _, translate_level
        except Exception:
            def _(key, **kw): return key.split(".")[-1]
            def translate_level(n): return n
        row_widget = QWidget()
        row_layout = QHBoxLayout(row_widget)
        row_layout.setContentsMargins(0, 0, 0, 0)
        row_layout.setSpacing(4)

        lbl = QLabel("→")
        lbl.setObjectName("track_meta")
        row_layout.addWidget(lbl)

        # Vis dans-navn — ikke redigerbart, kun valgt fra listen
        lbl_name = QLabel(name)
        lbl_name.setObjectName("track_title")
        row_layout.addWidget(lbl_name, stretch=1)

        # Niveau (read-only label)
        level_name = ""
        for lvl in self._levels:
            if lvl["id"] == level_id:
                level_name = lvl["name"]
                break
        if level_name:
            lbl_level = QLabel(level_name)
            lbl_level.setObjectName("result_count")
            lbl_level.setFixedWidth(110)
            row_layout.addWidget(lbl_level)

        btn_rm = QPushButton("✕")
        btn_rm.setFixedSize(32, 24)
        btn_rm.setToolTip("Fjern alternativ-dans")
        btn_rm.setObjectName("btn_rm_row")
        btn_rm.style().unpolish(btn_rm)
        btn_rm.style().polish(btn_rm)
        row_layout.addWidget(btn_rm)

        idx = self._alt_layout.count() - 1
        self._alt_layout.insertWidget(idx, row_widget)
        entry = {"widget": row_widget, "name": name, "level_id": level_id}
        self._alt_rows.append(entry)
        btn_rm.clicked.connect(lambda: self._remove_alt_row(entry))

    def _remove_alt_row(self, entry):
        self._alt_rows.remove(entry)
        entry["widget"].deleteLater()

    def _on_add_alt(self):
        """Alternativ-danse kan kun tilføjes fra forslagslisten, ikke som fri tekst."""
        if self._alt_suggestions.count() > 0:
            self._alt_suggestions.setCurrentRow(0)
            self._add_from_suggestion(self._alt_suggestions.currentItem(), "alt")

    def _save(self):
        song_id    = self._song.get("id")
        local_path = self._song.get("local_path", "")

        try:
            import uuid
            from local.local_db import get_db, get_or_create_dance
            from local.tag_reader import write_dances, can_write_dances

            # Saml data fra UI
            dances = []
            for row in self._dance_rows:
                name = row["edit"].text().strip()
                if name:
                    dances.append({
                        "name":         name,
                        "level_id":     row["level"].currentData(),
                        "choreographer": row["choreo"].text().strip(),
                    })

            alts = []
            for row in self._alt_rows:
                name = row.get("name", "")
                if name:
                    alts.append({
                        "name":     name,
                        "level_id": row.get("level_id"),
                        "note":     "",
                    })

            with get_db() as conn:
                # Slet eksisterende
                conn.execute("DELETE FROM song_dances WHERE song_id=?", (song_id,))
                conn.execute("DELETE FROM song_alt_dances WHERE song_id=?", (song_id,))

                # Indsæt hoveddanse
                for i, d in enumerate(dances, 1):
                    dance_id = get_or_create_dance(d["name"], d["level_id"], conn,
                                                   choreographer=d.get("choreographer", ""))
                    conn.execute(
                        "INSERT OR IGNORE INTO song_dances (id, song_id, dance_id, dance_order) "
                        "VALUES (?,?,?,?)",
                        (str(uuid.uuid4()), song_id, dance_id, i)
                    )

                # Indsæt alternativ-danse
                for a in alts:
                    dance_id = get_or_create_dance(a["name"], a["level_id"], conn)
                    conn.execute(
                        "INSERT OR IGNORE INTO song_alt_dances (id, song_id, dance_id, note) "
                        "VALUES (?,?,?,?)",
                        (str(uuid.uuid4()), song_id, dance_id, a.get("note", ""))
                    )

            # Skriv danse-navne til filen
            import logging as _logging
            _log = _logging.getLogger(__name__)
            dance_names = [d["name"] for d in dances]
            _log.info(f"Gemmer {len(dances)} danse: {dance_names}, local_path={local_path!r}")
            if local_path and can_write_dances(local_path):
                try:
                    result = write_dances(local_path, dance_names)
                    _log.info(f"write_dances resultat: {result}")
                    if not result:
                        QMessageBox.warning(self, "Advarsel",
                            "Gemt i database, men kunne ikke skrive til mp3-filen.\n"
                            "(Filen understøtter ikke dans-tags)")
                except Exception as write_err:
                    _log.warning(f"write_dances fejl: {write_err}")
                    QMessageBox.warning(self, "Advarsel",
                        f"Gemt i database, men fejl ved skrivning til fil:\n{write_err}")
            else:
                _log.info(f"Springer fil-skrivning over: local_path={local_path!r}")

            self.accept()

        except Exception as e:
            import traceback
            traceback.print_exc()
            QMessageBox.warning(self, "Fejl", f"Kunne ikke gemme: {e}")