"""Tests for CSV music source."""

import unittest
import os
import csv
from pushtunes.sources.csv import CSVSource
from pushtunes.models.album import Album
from pushtunes.models.track import Track
from pushtunes.utils.csv_utils import import_tracks_from_csv, export_tracks_to_csv


class TestCSVSource(unittest.TestCase):
    def setUp(self):
        # Create a temporary CSV file for testing
        self.csv_file = "test_albums.csv"
        with open(self.csv_file, "w", newline="", encoding="utf-8") as f:
            writer = csv.writer(f)
            writer.writerow(["artist", "artist2", "artist3", "album", "year"])
            writer.writerow(["Artist A", "Artist B", "", "Album 1", "2023"])
            writer.writerow(["Artist C", "", "", "Album 2", "2024"])
            writer.writerow(["Artist D", "Artist E", "Artist F", "Album 3", "2025"])
            writer.writerow(["", "", "", "Album 4", "2026"])  # No artists
            writer.writerow(["Bohren & der Club of Gore", "", "", "Sunset Mission", "2000"])
            writer.writerow(["VV & The Void", "", "", "The Upper Room", "2010"])
            writer.writerow(["Black Hill", "Eensdenkend", "", "Black Turns Grey", "2015"])


    def tearDown(self):
        # Clean up the temporary CSV file
        if os.path.exists(self.csv_file):
            os.remove(self.csv_file)

    def test_import_albums_from_csv_multiple_artists(self):
        """Test importing albums from CSV with multiple artist columns."""
        csv_source = CSVSource(self.csv_file)
        albums = csv_source.get_albums()

        self.assertEqual(len(albums), 7) # Updated count

        # Album 1: Artist A, Artist B
        self.assertEqual(albums[0].artists, ["Artist A", "Artist B"])
        self.assertEqual(albums[0].title, "Album 1")
        self.assertEqual(albums[0].year, 2023)

        # Album 2: Artist C
        self.assertEqual(albums[1].artists, ["Artist C"])
        self.assertEqual(albums[1].title, "Album 2")
        self.assertEqual(albums[1].year, 2024)

        # Album 3: Artist D, Artist E, Artist F
        self.assertEqual(albums[2].artists, ["Artist D", "Artist E", "Artist F"])
        self.assertEqual(albums[2].title, "Album 3")
        self.assertEqual(albums[2].year, 2025)

        # Album 4: No artists
        self.assertEqual(albums[3].artists, [])
        self.assertEqual(albums[3].title, "Album 4")
        self.assertEqual(albums[3].year, 2026)

        # Album 5: Bohren & der Club of Gore
        self.assertEqual(albums[4].artists, ["Bohren", "der Club of Gore"])
        self.assertEqual(albums[4].title, "Sunset Mission")
        self.assertEqual(albums[4].year, 2000)

        # Album 6: VV & The Void
        self.assertEqual(albums[5].artists, ["VV", "The Void"])
        self.assertEqual(albums[5].title, "The Upper Room")
        self.assertEqual(albums[5].year, 2010)

        # Album 7: Black Hill, Eensdenkend
        self.assertEqual(albums[6].artists, ["Black Hill", "Eensdenkend"])
        self.assertEqual(albums[6].title, "Black Turns Grey")
        self.assertEqual(albums[6].year, 2015)


    def test_import_albums_from_csv_no_artists_column(self):
        """Test importing albums from CSV without any artist columns."""
        no_artist_csv_file = "test_no_artist.csv"
        with open(no_artist_csv_file, "w", newline="", encoding="utf-8") as f:
            writer = csv.writer(f)
            writer.writerow(["album", "year"]) # Changed "title" to "album"
            writer.writerow(["Album X", "2020"])

        csv_source = CSVSource(no_artist_csv_file)
        albums = csv_source.get_albums()

        self.assertEqual(len(albums), 1)
        self.assertEqual(albums[0].artists, [])
        self.assertEqual(albums[0].title, "Album X")
        self.assertEqual(albums[0].year, 2020)

        os.remove(no_artist_csv_file)


class TestTrackCSVImportExport(unittest.TestCase):
    """Test CSV import/export for tracks."""

    def setUp(self):
        """Create temporary CSV file for testing."""
        self.csv_file = "test_tracks.csv"

    def tearDown(self):
        """Clean up temporary files."""
        if os.path.exists(self.csv_file):
            os.remove(self.csv_file)

    def test_import_tracks_basic(self):
        """Test importing tracks from CSV."""
        with open(self.csv_file, "w", newline="", encoding="utf-8") as f:
            writer = csv.writer(f)
            writer.writerow(["artist", "track", "album", "year"])
            writer.writerow(["Dire Straits", "Sultans of Swing", "Dire Straits", "1978"])
            writer.writerow(["Thy Catafalque", "Molekuláris Gépezetek", "Róka Hasa Rádió", "2009"])

        tracks = import_tracks_from_csv(self.csv_file)

        self.assertEqual(len(tracks), 2)

        # Track 1
        self.assertEqual(tracks[0].artists, ["Dire Straits"])
        self.assertEqual(tracks[0].title, "Sultans of Swing")
        self.assertEqual(tracks[0].album, "Dire Straits")
        self.assertEqual(tracks[0].year, 1978)

        # Track 2
        self.assertEqual(tracks[1].artists, ["Thy Catafalque"])
        self.assertEqual(tracks[1].title, "Molekuláris Gépezetek")
        self.assertEqual(tracks[1].album, "Róka Hasa Rádió")
        self.assertEqual(tracks[1].year, 2009)

    def test_import_tracks_optional_fields(self):
        """Test importing tracks with optional album and year fields."""
        with open(self.csv_file, "w", newline="", encoding="utf-8") as f:
            writer = csv.writer(f)
            writer.writerow(["artist", "track", "album", "year"])
            writer.writerow(["Artist A", "Track 1", "", ""])
            writer.writerow(["Artist B", "Track 2", "Album B", ""])
            writer.writerow(["Artist C", "Track 3", "", "2020"])

        tracks = import_tracks_from_csv(self.csv_file)

        self.assertEqual(len(tracks), 3)

        # Track without album or year
        self.assertIsNone(tracks[0].album)
        self.assertIsNone(tracks[0].year)

        # Track with album but no year
        self.assertEqual(tracks[1].album, "Album B")
        self.assertIsNone(tracks[1].year)

        # Track with year but no album
        self.assertIsNone(tracks[2].album)
        self.assertEqual(tracks[2].year, 2020)

    def test_import_tracks_title_fallback(self):
        """Test that 'title' column works as fallback for 'track'."""
        with open(self.csv_file, "w", newline="", encoding="utf-8") as f:
            writer = csv.writer(f)
            writer.writerow(["artist", "title", "album", "year"])
            writer.writerow(["Artist", "Track Title", "Album", "2020"])

        tracks = import_tracks_from_csv(self.csv_file)

        self.assertEqual(len(tracks), 1)
        self.assertEqual(tracks[0].title, "Track Title")

    def test_export_tracks(self):
        """Test exporting tracks to CSV."""
        tracks = [
            Track(artists=["Artist A"], title="Track 1", album="Album A", year=2020),
            Track(artists=["Artist B"], title="Track 2", album=None, year=2021),
            Track(artists=["Artist C", "Artist D"], title="Track 3", album="Album C", year=None),
        ]

        export_tracks_to_csv(tracks, self.csv_file)

        # Verify the exported CSV
        with open(self.csv_file, "r", newline="", encoding="utf-8") as f:
            reader = csv.DictReader(f)
            rows = list(reader)

        self.assertEqual(len(rows), 3)

        # Check first row
        self.assertEqual(rows[0]["artist"], "Artist A")
        self.assertEqual(rows[0]["track"], "Track 1")
        self.assertEqual(rows[0]["album"], "Album A")
        self.assertEqual(rows[0]["year"], "2020")

        # Check row with no album
        self.assertEqual(rows[1]["album"], "")

        # Check multi-artist (should use & format)
        self.assertEqual(rows[2]["artist"], "Artist C & Artist D")

    def test_csv_source_get_tracks(self):
        """Test CSVSource get_tracks method."""
        with open(self.csv_file, "w", newline="", encoding="utf-8") as f:
            writer = csv.writer(f)
            writer.writerow(["artist", "track", "album", "year"])
            writer.writerow(["Test Artist", "Test Track", "Test Album", "2023"])

        csv_source = CSVSource(self.csv_file)
        tracks = csv_source.get_tracks()

        self.assertEqual(len(tracks), 1)
        self.assertEqual(tracks[0].artists, ["Test Artist"])
        self.assertEqual(tracks[0].title, "Test Track")
