"""
PlayerManager — Unified media player bridge for Spotify and Apple Music
"""

import subprocess
from dataclasses import dataclass
from typing import Optional


@dataclass
class PlayerState:
    player_name: str  # 'Spotify' or 'Apple Music'
    track_name: str
    artist_name: str
    album_name: str
    player_position: float
    duration: float
    is_playing: bool

    @property
    def track_key(self) -> str:
        return f"{self.track_name.lower()}|{self.artist_name.lower()}"

    @property
    def display_info(self) -> str:
        if self.artist_name:
            return f"{self.track_name} — {self.artist_name}"
        return self.track_name


class PlayerManager:
    """Unified player bridge detecting and controlling Spotify and Apple Music."""

    APPLESCRIPT_QUERY = """
    if application "Spotify" is running then
        tell application "Spotify"
            if player state is playing then
                set tName to name of current track
                set aName to artist of current track
                set alName to album of current track
                set tPos to player position
                set tDur to (duration of current track) / 1000.0
                return tName & "|||" & aName & "|||" & alName & "|||" & (tPos as string) & "|||" & (tDur as string) & "|||playing|||Spotify"
            end if
        end tell
    end if

    if application "Music" is running then
        tell application "Music"
            if player state is playing then
                set tName to name of current track
                set aName to artist of current track
                set alName to album of current track
                set tPos to player position
                set tDur to duration of current track
                return tName & "|||" & aName & "|||" & alName & "|||" & (tPos as string) & "|||" & (tDur as string) & "|||playing|||Apple Music"
            end if
        end tell
    end if

    return "none"
    """

    @classmethod
    def get_current_state(cls) -> Optional[PlayerState]:
        try:
            res = subprocess.run(
                ['osascript', '-e', cls.APPLESCRIPT_QUERY],
                capture_output=True, text=True, timeout=2
            )
            out = res.stdout.strip()
            if not out or out == 'none':
                return None

            parts = out.split('|||')
            if len(parts) >= 7:
                t_name, a_name, al_name, pos_str, dur_str, state_str, player_name = parts[:7]
                pos = float(pos_str) if pos_str else 0.0
                dur = float(dur_str) if dur_str else 0.0
                is_playing = (state_str.strip() == 'playing')

                return PlayerState(
                    player_name=player_name,
                    track_name=t_name.strip(),
                    artist_name=a_name.strip(),
                    album_name=al_name.strip(),
                    player_position=pos,
                    duration=dur,
                    is_playing=is_playing
                )
        except Exception:
            pass

        return None

    @classmethod
    def play_pause(cls, player_name: str = 'Spotify'):
        app = 'Music' if 'Music' in player_name else 'Spotify'
        subprocess.run(['osascript', '-e', f'tell application "{app}" to playpause'], timeout=2)

    @classmethod
    def next_track(cls, player_name: str = 'Spotify'):
        app = 'Music' if 'Music' in player_name else 'Spotify'
        subprocess.run(['osascript', '-e', f'tell application "{app}" to next track'], timeout=2)

    @classmethod
    def previous_track(cls, player_name: str = 'Spotify'):
        app = 'Music' if 'Music' in player_name else 'Spotify'
        subprocess.run(['osascript', '-e', f'tell application "{app}" to previous track'], timeout=2)

    @classmethod
    def seek(cls, position_seconds: float, player_name: str = 'Spotify'):
        app = 'Music' if 'Music' in player_name else 'Spotify'
        subprocess.run(['osascript', '-e', f'tell application "{app}" to set player position to {position_seconds}'], timeout=2)
