"""
Cross-platform audio playback for birthday music.
Downloads a birthday song from the internet and plays it.
Works on Windows, macOS, and Linux without requiring extra installs.
"""

import os
import sys
import tempfile
import threading
import urllib.request
import subprocess
import platform


# A short, royalty-free "Happy Birthday" melody MIDI-style URL
# We use a public-domain birthday tune
BIRTHDAY_AUDIO_URLS = [
    "https://www.soundjay.com/birthday/sounds/happy-birthday-song-1.mp3",
    "https://orangefreesounds.com/wp-content/uploads/2022/08/Happy-birthday-to-you.mp3",
]


def _get_cache_dir():
    """Get a cache directory for the audio file."""
    cache = os.path.join(tempfile.gettempdir(), "jyoti_birthday_cache")
    os.makedirs(cache, exist_ok=True)
    return cache


def _download_audio():
    """Download the birthday audio file. Returns path or None."""
    cache_dir = _get_cache_dir()
    audio_path = os.path.join(cache_dir, "birthday.mp3")

    # If already cached, return it
    if os.path.exists(audio_path) and os.path.getsize(audio_path) > 1000:
        return audio_path

    for url in BIRTHDAY_AUDIO_URLS:
        try:
            req = urllib.request.Request(url, headers={
                "User-Agent": "Mozilla/5.0 (compatible; JyotiBirthday/1.0)"
            })
            with urllib.request.urlopen(req, timeout=10) as response:
                data = response.read()
                if len(data) > 1000:
                    with open(audio_path, "wb") as f:
                        f.write(data)
                    return audio_path
        except Exception:
            continue

    return None


def _play_audio_windows(path):
    """Play audio on Windows using built-in PowerShell."""
    try:
        # Use Windows Media Player COM via PowerShell
        ps_cmd = (
            f'$player = New-Object System.Media.SoundPlayer "{path}"; '
            f'$player.PlaySync()'
        )
        # For MP3, use WMPlayer COM
        ps_cmd_mp3 = (
            f'Add-Type -AssemblyName presentationCore; '
            f'$player = New-Object System.Windows.Media.MediaPlayer; '
            f'$player.Open([Uri]"{path}"); '
            f'Start-Sleep -Milliseconds 500; '
            f'$player.Play(); '
            f'Start-Sleep -Seconds 30; '
            f'$player.Stop()'
        )
        subprocess.Popen(
            ["powershell", "-NoProfile", "-Command", ps_cmd_mp3],
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,
            creationflags=subprocess.CREATE_NO_WINDOW if hasattr(subprocess, 'CREATE_NO_WINDOW') else 0,
        )
    except Exception:
        pass


def _play_audio_macos(path):
    """Play audio on macOS using afplay."""
    try:
        subprocess.Popen(
            ["afplay", path],
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,
        )
    except Exception:
        pass


def _play_audio_linux(path):
    """Play audio on Linux using available player."""
    players = [
        ["mpg123", "-q", path],
        ["mpg321", "-q", path],
        ["ffplay", "-nodisp", "-autoexit", "-loglevel", "quiet", path],
        ["aplay", path],
        ["paplay", path],
        ["cvlc", "--play-and-exit", "--no-video", path],
    ]

    for cmd in players:
        try:
            subprocess.Popen(
                cmd,
                stdout=subprocess.DEVNULL,
                stderr=subprocess.DEVNULL,
            )
            return
        except (FileNotFoundError, OSError):
            continue


def play_birthday_audio():
    """Download and play birthday audio in background thread."""
    def _worker():
        audio_path = _download_audio()
        if audio_path is None:
            # Fallback: try system beep pattern for "Happy Birthday"
            _play_beep_fallback()
            return

        system = platform.system().lower()
        if system == "windows":
            _play_audio_windows(audio_path)
        elif system == "darwin":
            _play_audio_macos(audio_path)
        else:
            _play_audio_linux(audio_path)

    thread = threading.Thread(target=_worker, daemon=True)
    thread.start()
    return thread


def _play_beep_fallback():
    """Play a beep pattern resembling Happy Birthday if no audio player available."""
    try:
        if sys.platform == "win32":
            import winsound
            # Happy Birthday melody approximation (frequency, duration)
            notes = [
                (262, 200), (262, 200), (294, 400), (262, 400), (349, 400), (330, 800),
                (262, 200), (262, 200), (294, 400), (262, 400), (392, 400), (349, 800),
                (262, 200), (262, 200), (523, 400), (440, 400), (349, 400), (330, 400), (294, 800),
                (466, 200), (466, 200), (440, 400), (349, 400), (392, 400), (349, 800),
            ]
            for freq, dur in notes:
                winsound.Beep(freq, dur)
        else:
            # On Unix, just print bell character a few times
            for _ in range(3):
                sys.stdout.write("\a")
                sys.stdout.flush()
                import time
                time.sleep(0.5)
    except Exception:
        pass


def stop_all_audio():
    """Best-effort stop any playing audio."""
    system = platform.system().lower()
    try:
        if system == "windows":
            subprocess.run(
                ["taskkill", "/F", "/IM", "powershell.exe"],
                stdout=subprocess.DEVNULL,
                stderr=subprocess.DEVNULL,
            )
        elif system == "darwin":
            subprocess.run(["killall", "afplay"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        else:
            for player in ["mpg123", "mpg321", "ffplay", "cvlc"]:
                subprocess.run(["killall", player], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    except Exception:
        pass
