# Standard library imports
import os
import unittest

# PyQt imports

# Third party imports
import pytest
from pytestqt.plugin import QtBot  # type: ignore

# App imports
from app import playlistmodel, utilities
from app.models import (
    db,
    Playlists,
    Tracks,
)
from app import musicmuster


# Custom fixture to adapt qtbot for use with unittest.TestCase
@pytest.fixture(scope="class")
def qtbot_adapter(qapp, request):
    """Adapt qtbot fixture for usefixtures and unittest.TestCase"""
    request.cls.qtbot = QtBot(request)


# Wrapper to handle setup/teardown operations
def with_updown(function):
    def test_wrapper(self, *args, **kwargs):
        if callable(getattr(self, "up", None)):
            self.up()
        try:
            function(self, *args, **kwargs)
        finally:
            if callable(getattr(self, "down", None)):
                self.down()

    test_wrapper.__doc__ = function.__doc__
    return test_wrapper


# Apply the custom fixture to the test class
@pytest.mark.usefixtures("qtbot_adapter")
class MyTestCase(unittest.TestCase):
    def up(self):
        db.create_all()
        self.widget = musicmuster.Window()
        # self.widget.show()

        # Add two tracks to database
        self.tracks = {
            1: {
                "path": "testdata/isa.mp3",
                "title": "I'm so afraid",
                "artist": "Fleetwood Mac",
                "bitrate": 64,
                "duration": 263000,
                "start_gap": 60,
                "fade_at": 236263,
                "silence_at": 260343,
            },
            2: {
                "path": "testdata/mom.mp3",
                "title": "Man of Mystery",
                "artist": "The Shadows",
                "bitrate": 64,
                "duration": 120000,
                "start_gap": 70,
                "fade_at": 115000,
                "silence_at": 118000,
            },
        }

        with db.Session() as session:
            for track in self.tracks.values():
                db_track = Tracks(session=session, **track)
                session.add(db_track)
                track["id"] = db_track.id

            session.commit()

    def down(self):
        db.drop_all()

    @with_updown
    def test_init(self):
        """Just check we can create a playlist_tab"""

        playlist_name = "test_init playlist"

        with db.Session() as session:
            playlist = Playlists(session, playlist_name, template_id=0)
            self.widget._open_playlist(playlist, is_template=False)
            with self.qtbot.waitExposed(self.widget):
                self.widget.show()

    @with_updown
    def test_save_and_restore(self):
        """Playlist with one track, one note, save and restore"""

        note_text = "my note"
        playlist_name = "test_save_and_restore playlist"

        with db.Session() as session:
            playlist = Playlists(session, playlist_name, template_id=0)
            model = playlistmodel.PlaylistModel(playlist.id, is_template=False)

            # Add a track with a note
            model.insert_row(
                proposed_row_number=0, track_id=self.tracks[1]["id"], note=note_text
            )

            # We need to commit the session before re-querying
            session.commit()

            # Retrieve playlist
            all_playlists = Playlists.get_all(session)
            assert len(all_playlists) == 1
            retrieved_playlist = all_playlists[0]
            assert len(retrieved_playlist.rows) == 1
            paths = [a.track.path for a in retrieved_playlist.rows]
            assert self.tracks[1]["path"] in paths
            notes = [a.note for a in retrieved_playlist.rows]
            assert note_text in notes

    @with_updown
    def test_utilities(self):
        """Test check_db utility"""

        from config import Config

        Config.ROOT = os.path.join(os.path.dirname(__file__), "testdata")

        with db.Session() as session:
            utilities.check_db(session)
            utilities.update_bitrates(session)


# def test_meta_all_clear(qtbot, session):
#     # Create playlist
#     playlist = models.Playlists(session, "my playlist", template_id=0)
#     playlist_tab = playlists.PlaylistTab(None, session, playlist.id)

#     # Add some tracks
#     # Need to commit session after each one so that new row is found
#     # for subsequent inserts
#     track1_path = "/a/b/c"
#     track1 = models.Tracks(session, track1_path)
#     playlist_tab.insert_track(session, track1)
#     session.commit()
#     track2_path = "/d/e/f"
#     track2 = models.Tracks(session, track2_path)
#     playlist_tab.insert_track(session, track2)
#     session.commit()
#     track3_path = "/h/i/j"
#     track3 = models.Tracks(session, track3_path)
#     playlist_tab.insert_track(session, track3)
#     session.commit()

#     assert playlist_tab._get_current_track_row() is None
#     assert playlist_tab._get_next_track_row() is None
#     assert playlist_tab._get_notes_rows() == []
#     assert playlist_tab._get_played_track_rows() == []
#     assert len(playlist_tab._get_unreadable_track_rows()) == 3


# def test_meta(qtbot, session):
#     # Create playlist
#     playlist = playlists.Playlists(session, "my playlist",
#     template_id=0)
#     playlist_tab = playlists.PlaylistTab(None, session, playlist.id)

#     # Add some tracks
#     track1_path = "/a/b/c"
#     track1 = models.Tracks(session, track1_path)
#     playlist_tab.insert_track(session, track1)
#     session.commit()
#     track2_path = "/d/e/f"
#     track2 = models.Tracks(session, track2_path)
#     playlist_tab.insert_track(session, track2)
#     session.commit()
#     track3_path = "/h/i/j"
#     track3 = models.Tracks(session, track3_path)
#     playlist_tab.insert_track(session, track3)
#     session.commit()

#     assert len(playlist_tab._get_unreadable_track_rows()) == 3

#     assert playlist_tab._get_played_track_rows() == []
#     assert playlist_tab._get_current_track_row() is None
#     assert playlist_tab._get_next_track_row() is None
#     assert playlist_tab._get_notes_rows() == []

#     playlist_tab._set_played_row(0)
#     assert playlist_tab._get_played_track_rows() == [0]
#     assert playlist_tab._get_current_track_row() is None
#     assert playlist_tab._get_next_track_row() is None
#     assert playlist_tab._get_notes_rows() == []

#     # Add a note
#     note_text = "my note"
#     note_row = 7  # will be added as row 3
#     note = models.Notes(session, playlist.id, note_row, note_text)
#     playlist_tab._insert_note(session, note)

#     assert playlist_tab._get_played_track_rows() == [0]
#     assert playlist_tab._get_current_track_row() is None
#     assert playlist_tab._get_next_track_row() is None
#     assert playlist_tab._get_notes_rows() == [3]

#     playlist_tab._set_next_track_row(1)
#     assert playlist_tab._get_played_track_rows() == [0]
#     assert playlist_tab._get_current_track_row() is None
#     assert playlist_tab._get_next_track_row() == 1
#     assert playlist_tab._get_notes_rows() == [3]

#     playlist_tab._set_current_track_row(2)
#     assert playlist_tab._get_played_track_rows() == [0]
#     assert playlist_tab._get_current_track_row() == 2
#     assert playlist_tab._get_next_track_row() == 1
#     assert playlist_tab._get_notes_rows() == [3]

#     playlist_tab._clear_played_row_status(0)
#     assert playlist_tab._get_played_track_rows() == []
#     assert playlist_tab._get_current_track_row() == 2
#     assert playlist_tab._get_next_track_row() == 1
#     assert playlist_tab._get_notes_rows() == [3]

#     playlist_tab._meta_clear_next()
#     assert playlist_tab._get_played_track_rows() == []
#     assert playlist_tab._get_current_track_row() == 2
#     assert playlist_tab._get_next_track_row() is None
#     assert playlist_tab._get_notes_rows() == [3]

#     playlist_tab._clear_current_track_row()
#     assert playlist_tab._get_played_track_rows() == []
#     assert playlist_tab._get_current_track_row() is None
#     assert playlist_tab._get_next_track_row() is None
#     assert playlist_tab._get_notes_rows() == [3]

#     # Test clearing again has no effect
#     playlist_tab._clear_current_track_row()
#     assert playlist_tab._get_played_track_rows() == []
#     assert playlist_tab._get_current_track_row() is None
#     assert playlist_tab._get_next_track_row() is None
#     assert playlist_tab._get_notes_rows() == [3]


# def test_clear_next(qtbot, session):
#     # Create playlist
#     playlist = models.Playlists(session, "my playlist", template_id=0)
#     playlist_tab = playlists.PlaylistTab(None, session, playlist.id)

#     # Add some tracks
#     track1_path = "/a/b/c"
#     track1 = models.Tracks(session, track1_path)
#     playlist_tab.insert_track(session, track1)
#     session.commit()
#     track2_path = "/d/e/f"
#     track2 = models.Tracks(session, track2_path)
#     playlist_tab.insert_track(session, track2)
#     session.commit()

#     playlist_tab._set_next_track_row(1)
#     assert playlist_tab._get_next_track_row() == 1

#     playlist_tab.clear_next(session)
#     assert playlist_tab._get_next_track_row() is None


# def test_get_selected_row(qtbot, monkeypatch, session):
#     monkeypatch.setattr(musicmuster, "Session", session)
#     monkeypatch.setattr(playlists, "Session", session)

#     # Create playlist and playlist_tab
#     window = musicmuster.Window()
#     playlist = models.Playlists(session, "test playlist", template_id=0)
#     playlist_tab = playlists.PlaylistTab(window, session, playlist.id)

#     # Add some tracks
#     track1_path = "/a/b/c"
#     track1 = models.Tracks(session, track1_path)
#     playlist_tab.insert_track(session, track1)
#     session.commit()
#     track2_path = "/d/e/f"
#     track2 = models.Tracks(session, track2_path)
#     playlist_tab.insert_track(session, track2)
#     session.commit()

#     qtbot.addWidget(playlist_tab)
#     with qtbot.waitExposed(window):
#         window.show()
#     row0_item0 = playlist_tab.item(0, 0)
#     assert row0_item0 is not None
#     rect = playlist_tab.visualItemRect(row0_item0)
#     qtbot.mouseClick(playlist_tab.viewport(), Qt.LeftButton, pos=rect.center())
#     row_number = playlist_tab.get_selected_row()
#     assert row_number == 0


# def test_set_next(qtbot, monkeypatch, session):
#     monkeypatch.setattr(musicmuster, "Session", session)
#     monkeypatch.setattr(playlists, "Session", session)
#     seed2tracks(session)

#     playlist_name = "test playlist"
#     # Create testing playlist
#     window = musicmuster.Window()
#     playlist = models.Playlists(session, playlist_name, template_id=0)
#     playlist_tab = playlists.PlaylistTab(window, session, playlist.id)
#     idx = window.tabPlaylist.addTab(playlist_tab, playlist_name)
#     window.tabPlaylist.setCurrentIndex(idx)
#     qtbot.addWidget(playlist_tab)

#     # Add some tracks
#     track1 = models.Tracks.get_by_filename(session, "isa.mp3")
#     track1_title = track1.title
#     assert track1_title

#     playlist_tab.insert_track(session, track1)
#     session.commit()
#     track2 = models.Tracks.get_by_filename(session, "mom.mp3")
#     playlist_tab.insert_track(session, track2)

#     with qtbot.waitExposed(window):
#         window.show()

#     row0_item2 = playlist_tab.item(0, 2)
#     assert row0_item2 is not None
#     rect = playlist_tab.visualItemRect(row0_item2)
#     qtbot.mouseClick(playlist_tab.viewport(), Qt.LeftButton, pos=rect.center())
#     selected_title = playlist_tab.get_selected_title()
#     assert selected_title == track1_title

#     qtbot.keyPress(playlist_tab.viewport(), "N", modifier=Qt.ControlModifier)
#     qtbot.wait(1000)


# def test_kae(monkeypatch, session):
#     # monkeypatch.setattr(dbconfig, "Session", session)
#     monkeypatch.setattr(musicmuster, "Session", session)

#     musicmuster.Window.kae()
#     # monkeypatch.setattr(musicmuster, "Session", session)
#     # monkeypatch.setattr(dbconfig, "Session", session)
#     # monkeypatch.setattr(models, "Session", session)
#     # monkeypatch.setattr(playlists, "Session", session)
