"""
Song validation utilities for checking if songs should be downloaded.
Centralizes song validation logic to eliminate code duplication.
"""

from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple

from karaoke_downloader.file_utils import check_file_exists_with_patterns
from karaoke_downloader.tracking_manager import TrackingManager


class SongValidator:
    """
    Centralized song validation logic for checking if songs should be downloaded.
    """

    def __init__(self, tracker: TrackingManager, downloads_dir: Path):
        """
        Initialize the song validator.

        Args:
            tracker: Tracking manager instance
            downloads_dir: Base downloads directory
        """
        self.tracker = tracker
        self.downloads_dir = downloads_dir

    def should_skip_song(
        self,
        artist: str,
        title: str,
        channel_name: str,
        video_id: Optional[str] = None,
        video_title: Optional[str] = None,
        server_songs: Optional[Dict[str, Any]] = None,
        server_duplicates_tracking: Optional[Dict[str, Any]] = None,
        force_download: bool = False,
    ) -> Tuple[bool, Optional[str], int]:
        """
        Check if a song should be skipped based on multiple criteria.

        Performs checks in order:
        1. Already downloaded (tracking)
        2. File exists on filesystem
        3. Already on server
        4. Previously failed download (bad file)

        Args:
            artist: Song artist name
            title: Song title
            channel_name: Channel name
            video_id: YouTube video ID (optional)
            video_title: YouTube video title (optional)
            server_songs: Server songs data (optional)
            server_duplicates_tracking: Server duplicates tracking (optional)
            force_download: If True, bypass all validation checks and force download

        Returns:
            Tuple of (should_skip, reason, total_filtered)
        """
        # If force download is enabled, skip all validation checks
        if force_download:
            return False, None, 0

        total_filtered = 0

        # Check 1: Already downloaded by this system
        if self.tracker.is_song_downloaded(artist, title, channel_name, video_id):
            return True, "already downloaded", total_filtered

        # Check 2: File already exists on filesystem
        file_exists, _ = check_file_exists_with_patterns(
            self.downloads_dir, channel_name, artist, title
        )
        if file_exists:
            return True, "file exists", total_filtered

        # Check 3: Already on server (if server data provided)
        if server_songs is not None and server_duplicates_tracking is not None:
            from karaoke_downloader.server_manager import (
                check_and_mark_server_duplicate,
            )

            if check_and_mark_server_duplicate(
                server_songs,
                server_duplicates_tracking,
                artist,
                title,
                video_title,
                channel_name,
            ):
                total_filtered += 1
                return True, "on server", total_filtered

        # Check 4: Previously failed download (bad file)
        if self.tracker.is_song_failed(artist, title, channel_name, video_id):
            return True, "previously failed", total_filtered

        return False, None, total_filtered

    def mark_song_failed(
        self,
        artist: str,
        title: str,
        video_id: Optional[str],
        channel_name: str,
        error_message: str,
    ) -> None:
        """
        Mark a song as failed in tracking.

        Args:
            artist: Song artist name
            title: Song title
            video_id: YouTube video ID (optional)
            channel_name: Channel name
            error_message: Error message to record
        """
        self.tracker.mark_song_failed(
            artist, title, video_id, channel_name, error_message
        )
        print(f"🏷️  Marked song as failed: {artist} - {title}")

    def handle_download_failure(
        self,
        artist: str,
        title: str,
        video_id: Optional[str],
        channel_name: str,
        error_type: str,
        error_details: str = "",
    ) -> None:
        """
        Handle download failures with consistent error formatting.

        Args:
            artist: Song artist name
            title: Song title
            video_id: YouTube video ID (optional)
            channel_name: Channel name
            error_type: Type of error (e.g., "yt-dlp failed", "file verification failed")
            error_details: Additional error details
        """
        error_msg = f"{error_type}"
        if error_details:
            error_msg += f": {error_details}"
        self.mark_song_failed(artist, title, video_id, channel_name, error_msg)


def create_song_validator(
    tracker: TrackingManager, downloads_dir: Path
) -> SongValidator:
    """
    Factory function to create a song validator instance.

    Args:
        tracker: Tracking manager instance
        downloads_dir: Base downloads directory

    Returns:
        SongValidator instance
    """
    return SongValidator(tracker, downloads_dir)
