# pylint: disable=broad-exception-caught

"""
Shazam music detection processor.

Detects background music in videos using Shazam audio fingerprinting API.
"""

import logging
import os
import tempfile
from typing import Optional
from mini_videorag.core.processor import ProcessorResult, TimeSegment
from mini_videorag.processors.music_detection.base import BaseMusicDetectionProcessor
from mini_videorag.utils.audio_utils import video_to_audio
from mini_videorag.processors.music_detection.shazam_utils import audio_recognize
from mini_videorag.core.exceptions import ProcessingError, AudioExtractionError


class ShazamMusicDetectionProcessor(BaseMusicDetectionProcessor):
    """
    Shazam-based music detection processor.

    Uses Shazam's audio fingerprinting to identify music tracks in video files.

    Example:
        processor = ShazamMusicDetectionProcessor()
        result = processor.process(
            video_path="/path/to/video.mp4",
            video_id="video_123"
        )

        if result.success and result.data.get("has_music"):
            print(f"Music detected: {result.data['track_title']}")

    Attributes:
        logger: Logger instance for this processor
    """

    def __init__(self):
        """Initialize the Shazam music detection processor."""
        self.logger = logging.getLogger(__name__)

    @property
    def provider(self) -> str:
        """Provider name for this implementation."""
        return "shazam"

    def process(self, video_path: str, video_id: str, **kwargs) -> ProcessorResult:
        """
        Detect music in the video.

        Args:
            video_path: Path to video file
            video_id: Unique identifier for the video
            **kwargs: Additional options (currently unused)

        Returns:
            ProcessorResult with music detection data:
            - data["has_music"]: bool - Whether music was detected
            - data["track_title"]: str - Title of detected track (if found)
            - data["confidence"]: float - Confidence score (1.0 if detected, 0.0 otherwise)

        Raises:
            Exception: If processing fails completely
        """
        try:
            self.validate_input(video_path)

            self.logger.info(f"Starting music detection for video: {video_id}")

            with tempfile.TemporaryDirectory() as temp_dir:
                audio_path = os.path.join(temp_dir, "audio.mp3")

                self.logger.debug(f"Extracting audio from video: {video_path}")
                try:
                    video_to_audio(video_path, audio_path)
                except Exception as e:
                    self.logger.error(f"Failed to extract audio: {e}")
                    return ProcessorResult(
                        processor_name=self.name,
                        video_id=video_id,
                        success=False,
                        error=f"Audio extraction failed: {str(e)}",
                    )

                self.logger.debug("Analyzing audio for music...")
                track_title: Optional[str] = None

                try:
                    track_title = audio_recognize(audio_path)
                except Exception as e:
                    self.logger.warning(f"Music recognition failed: {e}")
                    track_title = None

                has_music = track_title is not None

                result_data = {
                    "has_music": has_music,
                    "confidence": 1.0 if has_music else 0.0,
                }

                if has_music:
                    result_data["track_title"] = track_title
                    self.logger.info(f"Music detected: {track_title}")
                else:
                    self.logger.info("No music detected in video")

                segments = []
                if has_music:
                    segments.append(
                        TimeSegment(
                            start=0.0,
                            end=0.0,
                            metadata={"track_title": track_title, "confidence": 1.0},
                        )
                    )

                return ProcessorResult(
                    processor_name=self.name,
                    video_id=video_id,
                    success=True,
                    data=result_data,
                    segments=segments,
                    metadata={"audio_path": audio_path, "recognition_method": "shazam"},
                )

        except FileNotFoundError as e:
            self.logger.error(f"Video file not found: {e}")
            return ProcessorResult(
                processor_name=self.name, video_id=video_id, success=False, error=str(e)
            )

        except AudioExtractionError as e:
            self.logger.error(f"Audio extraction failed: {e}")
            return ProcessorResult(
                processor_name=self.name,
                video_id=video_id,
                success=False,
                error=f"Audio extraction failed: {str(e)}",
            )

        except ProcessingError as e:
            self.logger.error(f"Unexpected error with processor {self.name}: {e}")
            return ProcessorResult(
                processor_name=self.name,
                video_id=video_id,
                success=False,
                error=f"Unexpected error: {str(e)}",
            )
