# Standard library imports
from typing import Optional

# PyQt imports
from PyQt6.QtCore import QEvent, Qt
from PyQt6.QtGui import QKeyEvent
from PyQt6.QtWidgets import (
    QDialog,
    QListWidgetItem,
    QMainWindow,
)
from PyQt6.QtWidgets import (
    QDialog,
    QHBoxLayout,
    QLabel,
    QLineEdit,
    QListWidget,
    QListWidgetItem,
    QPushButton,
    QVBoxLayout,
)

# Third party imports
from sqlalchemy.orm.session import Session

# App imports
from classes import ApplicationError, InsertTrack, MusicMusterSignals
from helpers import (
    ask_yes_no,
    get_relative_date,
    ms_to_mmss,
)
from log import log
from models import Settings, Tracks
from playlistmodel import PlaylistModel
import repository
from ui import dlg_TrackSelect_ui


class TrackInsertDialog(QDialog):
    def __init__(
        self,
        parent: QMainWindow,
        playlist_id: int,
        add_to_header: Optional[bool] = False,
    ) -> None:
        """
        Subclassed QDialog to manage track selection
        """

        super().__init__(parent)
        self.playlist_id = playlist_id
        self.add_to_header = add_to_header
        self.setWindowTitle("Insert Track")

        # Title input on one line
        self.title_label = QLabel("Title:")
        self.title_edit = QLineEdit()
        self.title_edit.textChanged.connect(self.update_list)

        title_layout = QHBoxLayout()
        title_layout.addWidget(self.title_label)
        title_layout.addWidget(self.title_edit)

        # Track list
        self.track_list = QListWidget()
        self.track_list.itemDoubleClicked.connect(self.add_clicked)
        self.track_list.itemSelectionChanged.connect(self.selection_changed)

        # Note input on one line
        self.note_label = QLabel("Note:")
        self.note_edit = QLineEdit()

        note_layout = QHBoxLayout()
        note_layout.addWidget(self.note_label)
        note_layout.addWidget(self.note_edit)

        # Track path
        self.path = QLabel()
        path_layout = QHBoxLayout()
        path_layout.addWidget(self.path)

        # Buttons
        self.add_btn = QPushButton("Add")
        self.add_close_btn = QPushButton("Add and close")
        self.close_btn = QPushButton("Close")

        self.add_btn.clicked.connect(self.add_clicked)
        self.add_close_btn.clicked.connect(self.add_and_close_clicked)
        self.close_btn.clicked.connect(self.close)

        btn_layout = QHBoxLayout()
        btn_layout.addWidget(self.add_btn)
        btn_layout.addWidget(self.add_close_btn)
        btn_layout.addWidget(self.close_btn)

        # Main layout
        layout = QVBoxLayout()
        layout.addLayout(title_layout)
        layout.addWidget(self.track_list)
        layout.addLayout(note_layout)
        layout.addLayout(path_layout)
        layout.addLayout(btn_layout)

        self.setLayout(layout)
        self.resize(800, 600)
        # TODO
        # record = Settings.get_setting(self.session, "dbdialog_width")
        # width = record.f_int or 800
        # record = Settings.get_setting(self.session, "dbdialog_height")
        # height = record.f_int or 600
        # self.resize(width, height)

    def update_list(self, text: str) -> None:
        self.track_list.clear()
        if text.strip() == "":
            # Do not search or populate list if input is empty
            return

        if text.startswith("a/") and len(text) > 2:
            self.tracks = repository.tracks_like_artist(text[2:])
        else:
            self.tracks = repository.tracks_like_title(text)

        for track in self.tracks:
            duration_str = ms_to_mmss(track.duration)
            last_played_str = get_relative_date(track.lastplayed)
            item_str = (
                f"{track.title} - {track.artist} [{duration_str}] {last_played_str}"
            )
            item = QListWidgetItem(item_str)
            item.setData(Qt.ItemDataRole.UserRole, track.track_id)
            self.track_list.addItem(item)

    def get_selected_track_id(self) -> int | None:
        selected_items = self.track_list.selectedItems()
        if selected_items:
            return selected_items[0].data(Qt.ItemDataRole.UserRole)
        return None

    def add_clicked(self):
        track_id = self.get_selected_track_id()
        note_text = self.note_edit.text()
        if track_id is None and not note_text:
            return

        insert_track_data = InsertTrack(self.playlist_id, track_id, note_text)
        self.signals.signal_insert_track.emit(insert_track_data)

        self.title_edit.clear()
        self.note_edit.clear()
        self.track_list.clear()
        self.title_edit.setFocus()

        if self.add_to_header:
            self.accept()

    def add_and_close_clicked(self):
        track_id = self.get_selected_track_id()
        if track_id is not None:
            note_text = self.note_edit.text()
            insert_track_data = InsertTrack(
                playlist_id=self.playlist_id, track_id=self.track_id, note=self.note
            )
            insert_track_data = InsertTrack(self.playlist_id, track_id, note_text)
            self.signals.signal_insert_track.emit(insert_track_data)
        self.accept()

    def selection_changed(self) -> None:
        """Display selected track path in dialog box"""

        self.path.setText("")

        track_id = self.get_selected_track_id()
        if track_id is None:
            return

        tracklist = [t for t in self.tracks if t.track_id == track_id]
        if not tracklist:
            return
        if len(tracklist) > 1:
            raise ApplicationError("More than one track returned")
        track = tracklist[0]

        self.path.setText(track.path)
