import unittest
from unittest.mock import AsyncMock, patch

from streamrip.rip.parse_url import (
    DeezerDynamicURL,
    GenericURL,
    SoundcloudURL,
    parse_url,
)


class TestParseURL(unittest.TestCase):
    def test_deezer_dynamic_url(self):
        """Test that Deezer dynamic URLs are matched correctly."""
        url = "https://dzr.page.link/SnV6hCyHihkmCCwUA"
        result = parse_url(url)

        self.assertIsNotNone(result)
        self.assertIsInstance(result, DeezerDynamicURL)
        self.assertEqual(result.source, "deezer")

    def test_qobuz_album_url(self):
        """Test that Qobuz album URLs are matched correctly."""
        url = "https://www.qobuz.com/fr-fr/album/bizarre-ride-ii-the-pharcyde-the-pharcyde/0066991040005"
        result = parse_url(url)

        self.assertIsNotNone(result)
        self.assertIsInstance(result, GenericURL)
        self.assertEqual(result.source, "qobuz")

        # Verify the regex match groups
        groups = result.match.groups()
        self.assertEqual(len(groups), 3)
        self.assertEqual(groups[0], "qobuz")  # source
        self.assertEqual(groups[1], "album")  # media_type
        self.assertEqual(groups[2], "0066991040005")  # item_id

    def test_tidal_track_url(self):
        """Test that Tidal track URLs are matched correctly."""
        url = "https://tidal.com/browse/track/3083287"
        result = parse_url(url)

        self.assertIsNotNone(result)
        self.assertIsInstance(result, GenericURL)
        self.assertEqual(result.source, "tidal")

        # Verify the regex match groups
        groups = result.match.groups()
        self.assertEqual(len(groups), 3)
        self.assertEqual(groups[0], "tidal")  # source
        self.assertEqual(groups[1], "track")  # media_type
        self.assertEqual(groups[2], "3083287")  # item_id

    def test_deezer_track_url(self):
        """Test that Deezer track URLs are matched correctly."""
        url = "https://www.deezer.com/track/4195713"
        result = parse_url(url)

        self.assertIsNotNone(result)
        self.assertIsInstance(result, GenericURL)
        self.assertEqual(result.source, "deezer")

        # Verify the regex match groups
        groups = result.match.groups()
        self.assertEqual(len(groups), 3)
        self.assertEqual(groups[0], "deezer")  # source
        self.assertEqual(groups[1], "track")  # media_type
        self.assertEqual(groups[2], "4195713")  # item_id

    def test_invalid_url(self):
        """Test that invalid URLs return None."""
        urls = [
            "https://example.com",
            "not a url",
            "https://spotify.com/track/123456",  # Unsupported source
            "https://tidal.com/invalid/3083287",  # Invalid media type
        ]

        for url in urls:
            result = parse_url(url)
            self.assertIsNone(result, f"URL should not parse: {url}")

    def test_alternate_url_formats(self):
        """Test various URL formats that should be valid."""
        # Test with different domain prefixes
        url1 = "https://open.tidal.com/track/3083287"
        url2 = "https://play.qobuz.com/album/0066991040005"
        url3 = "https://listen.tidal.com/track/3083287"

        for url in [url1, url2, url3]:
            result = parse_url(url)
            self.assertIsNotNone(result, f"Should parse URL: {url}")
            self.assertIsInstance(result, GenericURL)

    def test_url_with_language_code(self):
        """Test URLs with different language codes."""
        urls = [
            "https://www.qobuz.com/us-en/album/name/id123456",
            "https://www.qobuz.com/gb-en/album/name/id123456",
            "https://www.deezer.com/en/track/4195713",
            "https://www.deezer.com/fr/track/4195713",
        ]

        for url in urls:
            result = parse_url(url)
            self.assertIsNotNone(result, f"Should parse URL: {url}")
            self.assertIsInstance(result, GenericURL)

    def test_soundcloud_url(self):
        """Test that Soundcloud URLs are matched correctly."""
        urls = [
            "https://soundcloud.com/artist-name/track-name",
            "https://soundcloud.com/artist-name/sets/playlist-name",
        ]

        for url in urls:
            result = parse_url(url)
            self.assertIsNotNone(result, f"Should parse URL: {url}")
            self.assertIsInstance(result, SoundcloudURL)
            self.assertEqual(result.source, "soundcloud")


class TestDeezerDynamicURL(unittest.TestCase):
    @patch("streamrip.rip.parse_url.DeezerDynamicURL._extract_info_from_dynamic_link")
    def test_into_pending_album(self, mock_extract):
        """Test conversion of Deezer dynamic URL to a PendingAlbum."""
        import asyncio

        async def run_test():
            url = "https://dzr.page.link/SnV6hCyHihkmCCwUA"
            result = parse_url(url)

            # Mock the extract method to return album type and ID
            mock_extract.return_value = ("album", "12345")

            # Mock the client, config, db
            mock_client = AsyncMock()
            mock_client.source = "deezer"
            mock_config = AsyncMock()
            mock_db = AsyncMock()

            # Call into_pending
            pending = await result.into_pending(mock_client, mock_config, mock_db)

            # Verify the correct pending type was created
            self.assertEqual(pending.__class__.__name__, "PendingAlbum")
            self.assertEqual(pending.id, "12345")

        # Run the coroutine
        asyncio.run(run_test())


if __name__ == "__main__":
    unittest.main()