"""CSV utilities for importing and exporting song data."""

import csv

from ..models.album import Album
from ..models.track import Track
from ..models.playlist import Playlist
from .artist_utils import parse_artist_string


def export_albums_to_csv(albums: list[Album], csv_file: str) -> None:
    """Export a list of albums to a CSV file.

    Args:
        albums: list of Album objects to export
        csv_file: Path to the output CSV file
    """
    with open(csv_file, "w", newline="", encoding="utf-8") as f:
        writer = csv.writer(f, quoting=csv.QUOTE_ALL)
        # Write header
        writer.writerow(["artist", "album", "year"])

        # Write album data
        for album in albums:
            writer.writerow([album.artist, album.title, album.year])


def import_albums_from_csv(csv_file: str) -> list[Album]:
    """Import albums from a CSV file with 'artist', 'album' fields.
    Supports multiple artist columns: 'artist', 'artist2', ..., 'artist10'.

    Args:
        csv_file: Path to the input CSV file

    Returns:
        list of Album objects
    """
    albums = []
    with open(csv_file, "r", newline="", encoding="utf-8") as f:
        reader = csv.DictReader(f)
        for row in reader:
            artist_names = []
            # Check for artist2, artist3 etc. first
            for i in range(2, 11):
                additional_artist = row.get(f"artist{i}")
                if additional_artist:
                    artist_names.append(additional_artist)

            primary_artist = row.get("artist")
            if primary_artist:
                # If there were additional artist columns, we assume the user has
                # already split the artists and we just prepend the primary artist.
                # If not, we parse the primary artist string for separators.
                if artist_names:
                    artist_names.insert(0, primary_artist)
                else:
                    artist_names.extend(parse_artist_string(primary_artist))

            year_str = row.get("year")
            year = int(year_str) if year_str else None

            album = Album(
                artists=artist_names,
                title=row.get("album", ""),
                year=year,
            )
            albums.append(album)
    return albums


def export_tracks_to_csv(tracks: list[Track], csv_file: str) -> None:
    """Export a list of tracks to a CSV file.

    Args:
        tracks: list of Track objects to export
        csv_file: Path to the output CSV file
    """
    with open(csv_file, "w", newline="", encoding="utf-8") as f:
        writer = csv.writer(f, quoting=csv.QUOTE_ALL)
        # Write header
        writer.writerow(["artist", "track", "album", "year"])

        # Write track data
        for track in tracks:
            writer.writerow([track.artist, track.title, track.album or "", track.year or ""])


def import_tracks_from_csv(csv_file: str) -> list[Track]:
    """Import tracks from a CSV file with 'artist' and 'track' fields.
    Supports single artist per track (as per requirements).

    Args:
        csv_file: Path to the input CSV file

    Returns:
        list of Track objects
    """
    tracks = []
    with open(csv_file, "r", newline="", encoding="utf-8") as f:
        reader = csv.DictReader(f)
        for row in reader:
            artist = row.get("artist", "")
            artist_list = [artist] if artist else []

            year_str = row.get("year")
            year = int(year_str) if year_str and year_str.isdigit() else None

            track = Track(
                artists=artist_list,
                title=row.get("track", "") or row.get("title", ""),
                album=row.get("album") or None,
                year=year,
            )
            tracks.append(track)
    return tracks


def export_playlist_to_csv(playlist: Playlist, csv_file: str) -> None:
    """Export a playlist to a CSV file.

    Uses the same format as tracks (artist, track, album, year).

    Args:
        playlist: Playlist object to export
        csv_file: Path to the output CSV file
    """
    export_tracks_to_csv(playlist.tracks, csv_file)


def import_playlist_from_csv(csv_file: str, playlist_name: str | None = None) -> Playlist:
    """Import a playlist from a CSV file.

    Uses the same format as tracks (artist, track, album, year).

    Args:
        csv_file: Path to the input CSV file
        playlist_name: Name for the playlist (defaults to filename without extension)

    Returns:
        Playlist object
    """
    tracks = import_tracks_from_csv(csv_file)

    # Use filename (without extension) as playlist name if not provided
    if not playlist_name:
        import os
        playlist_name = os.path.splitext(os.path.basename(csv_file))[0]

    return Playlist(name=playlist_name, tracks=tracks)


def export_album_results_to_csv(results: list, status_filter: list[str], csv_file: str) -> int:
    """Export album results matching specified statuses to a CSV file.

    Args:
        results: List of AlbumResult objects
        status_filter: List of status names to include (e.g., ['not_found', 'similarity_too_low'])
        csv_file: Path to the output CSV file

    Returns:
        Number of albums exported
    """
    # Filter results by status
    filtered = [r for r in results if r.status.name in status_filter]

    if not filtered:
        return 0

    # Extract albums from results
    albums = [r.album for r in filtered]

    # Export using existing function
    export_albums_to_csv(albums, csv_file)

    return len(albums)


def export_track_results_to_csv(results: list, status_filter: list[str], csv_file: str) -> int:
    """Export track results matching specified statuses to a CSV file.

    Args:
        results: List of TrackResult objects
        status_filter: List of status names to include (e.g., ['not_found', 'similarity_too_low'])
        csv_file: Path to the output CSV file

    Returns:
        Number of tracks exported
    """
    # Filter results by status
    filtered = [r for r in results if r.status.name in status_filter]

    if not filtered:
        return 0

    # Extract tracks from results
    tracks = [r.track for r in filtered]

    # Export using existing function
    export_tracks_to_csv(tracks, csv_file)

    return len(tracks)


def export_album_results_to_mappings_csv(results: list, status_filter: list[str], csv_file: str) -> int:
    """Export album results matching specified statuses to a mappings CSV file.

    Creates a CSV file in the mappings format with empty target fields that the user can fill in.

    Args:
        results: List of AlbumResult objects
        status_filter: List of status names to include (e.g., ['not_found'])
        csv_file: Path to the output CSV file

    Returns:
        Number of albums exported
    """
    # Filter results by status
    filtered = [r for r in results if r.status.name in status_filter]

    if not filtered:
        return 0

    with open(csv_file, "w", newline="", encoding="utf-8") as f:
        writer = csv.writer(f, quoting=csv.QUOTE_ALL)
        # Write header
        writer.writerow([
            "type", "artist", "title",
            "spotify_id", "ytm_id",
            "spotify_artist", "spotify_title",
            "ytm_artist", "ytm_title"
        ])

        # Write album data with empty target fields
        for result in filtered:
            writer.writerow([
                "album",
                result.album.artist,
                result.album.title,
                "",  # spotify_id
                "",  # ytm_id
                "",  # spotify_artist
                "",  # spotify_title
                "",  # ytm_artist
                ""   # ytm_title
            ])

    return len(filtered)


def export_track_results_to_mappings_csv(results: list, status_filter: list[str], csv_file: str) -> int:
    """Export track results matching specified statuses to a mappings CSV file.

    Creates a CSV file in the mappings format with empty target fields that the user can fill in.

    Args:
        results: List of TrackResult objects
        status_filter: List of status names to include (e.g., ['not_found'])
        csv_file: Path to the output CSV file

    Returns:
        Number of tracks exported
    """
    # Filter results by status
    filtered = [r for r in results if r.status.name in status_filter]

    if not filtered:
        return 0

    with open(csv_file, "w", newline="", encoding="utf-8") as f:
        writer = csv.writer(f, quoting=csv.QUOTE_ALL)
        # Write header
        writer.writerow([
            "type", "artist", "title",
            "spotify_id", "ytm_id",
            "spotify_artist", "spotify_title",
            "ytm_artist", "ytm_title"
        ])

        # Write track data with empty target fields
        for result in filtered:
            writer.writerow([
                "track",
                result.track.artist,
                result.track.title,
                "",  # spotify_id
                "",  # ytm_id
                "",  # spotify_artist
                "",  # spotify_title
                "",  # ytm_artist
                ""   # ytm_title
            ])

    return len(filtered)
