<?php
/**
 * Alarm-Audio-Player: Spielt TTS + Musik für einen Wecker ab.
 * Wird von timer_pruefung.php als separater Hintergrundprozess gestartet.
 *
 * Aufruf: php alarm_player.php <alarm_id> <state_file>
 *
 * Abspielreihenfolge:
 *   1. Audio mit position='vorher'  (Musik vor TTS)
 *   2. TTS-Sprachausgabe            (aus wecker_tts_cache)
 *   3. Audio mit position='gleichzeitig' und 'danach'
 *
 * Nach jedem Track wird geprüft, ob der Alarm gestoppt/gesnoozed wurde.
 */

$weckerRoot = dirname(__DIR__);
require $weckerRoot . '/config.php';
require FUNCTIONS_ROOT . '/functions_db.php';
require FUNCTIONS_ROOT . '/functions_wecker.php';
require FUNCTIONS_ROOT . '/functions_common.php';

$alarmId   = isset($argv[1]) ? (int) $argv[1] : 0;
$stateFile = isset($argv[2]) ? $argv[2] : (STORAGE_ROOT . '/alarm_ringing.json');

if ($alarmId <= 0) {
    exit(1);
}

// ─── Eigene PID sofort in State-Datei schreiben ───────────────────────────────
(function () use ($stateFile): void {
    $state = [];
    if (is_file($stateFile)) {
        $raw = @file_get_contents($stateFile);
        if ($raw !== false && $raw !== '') {
            $state = @json_decode($raw, true) ?: [];
        }
    }
    $state['player_pid'] = getmypid();
    @file_put_contents($stateFile, json_encode($state));
})();

$storageRoot = defined('STORAGE_ROOT') ? STORAGE_ROOT : ($weckerRoot . '/storage');

// ─── Hilfsfunktionen ─────────────────────────────────────────────────────────

/**
 * Prüft ob der Alarm noch aktiv ist (nicht gestoppt und nicht gesnoozed).
 */
function alarmIsActive(string $stateFile): bool
{
    if (!is_file($stateFile)) {
        return false;
    }
    $raw = @file_get_contents($stateFile);
    if ($raw === false || $raw === '') {
        return false;
    }
    $s = @json_decode($raw, true);
    return !empty($s['ringing']);
}

/**
 * Sucht das erste verfügbare CLI-Programm aus einer Liste.
 */
function findBin(array $candidates): ?string
{
    foreach ($candidates as $bin) {
        $out = [];
        @exec('command -v ' . escapeshellarg($bin) . ' 2>/dev/null', $out);
        if (!empty($out[0]) && trim($out[0]) !== '') {
            return trim($out[0]);
        }
    }
    return null;
}

/**
 * Spielt eine einzelne Audio-Datei ab (blockierend bis fertig).
 * Gibt true zurück wenn erfolgreich, false wenn kein Player gefunden.
 */
function playFile(string $path): bool
{
    if (!is_file($path) || !is_readable($path)) {
        error_log('[alarm_player] Datei nicht lesbar: ' . $path);
        return false;
    }

    $ext = strtolower((string) pathinfo($path, PATHINFO_EXTENSION));

    if ($ext === 'wav') {
        $bin = findBin(['aplay', 'play', 'cvlc']);
        if ($bin === null) {
            error_log('[alarm_player] Kein WAV-Player gefunden (aplay/play/cvlc)');
            return false;
        }
        if (basename($bin) === 'aplay') {
            $cmd = $bin . ' -q ' . escapeshellarg($path);
        } elseif (basename($bin) === 'play') {
            $cmd = $bin . ' -q ' . escapeshellarg($path);
        } else {
            $cmd = $bin . ' --play-and-exit --intf dummy ' . escapeshellarg($path);
        }
    } elseif ($ext === 'mp3') {
        $bin = findBin(['mpg123', 'cvlc', 'play']);
        if ($bin === null) {
            error_log('[alarm_player] Kein MP3-Player gefunden (mpg123/cvlc/play)');
            return false;
        }
        if (basename($bin) === 'mpg123') {
            $cmd = $bin . ' -q ' . escapeshellarg($path);
        } elseif (basename($bin) === 'cvlc') {
            $cmd = $bin . ' --play-and-exit --intf dummy ' . escapeshellarg($path);
        } else {
            $cmd = $bin . ' -q ' . escapeshellarg($path);
        }
    } else {
        // OGG, M4A, AAC, FLAC usw.
        $bin = findBin(['cvlc', 'mpg123', 'play']);
        if ($bin === null) {
            error_log('[alarm_player] Kein Player für .' . $ext . ' gefunden');
            return false;
        }
        if (basename($bin) === 'cvlc') {
            $cmd = $bin . ' --play-and-exit --intf dummy ' . escapeshellarg($path);
        } else {
            $cmd = $bin . ' -q ' . escapeshellarg($path);
        }
    }

    @system($cmd . ' 2>/dev/null');
    return true;
}

// ─── Audio-Dateipfade auflösen ────────────────────────────────────────────────

$vorher  = [];
$nachher = [];

$audioEntries = function_wecker_hole_audio($alarmId);

foreach ($audioEntries as $entry) {
    $datei    = trim((string) ($entry['datei']    ?? ''));
    $position = trim((string) ($entry['position'] ?? 'danach'));

    $files = [];

    if ($datei === '') {
        continue;
    }

    if (strpos($datei, 'playlist:') === 0) {
        $pid = (int) substr($datei, 9);
        if ($pid > 0) {
            try {
                $stmt = $GLOBALS['pdo']->prepare(
                    'SELECT m.dateiname
                     FROM musik m
                     INNER JOIN playlist_tracks pt ON pt.musik_id = m.id
                     WHERE pt.playlist_id = ?
                     ORDER BY pt.id'
                );
                $stmt->execute([$pid]);
                while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
                    if (!empty($row['dateiname'])) {
                        $files[] = $storageRoot . '/audio/' . basename($row['dateiname']);
                    }
                }
            } catch (Throwable $e) {
                error_log('[alarm_player] Playlist-Fehler: ' . $e->getMessage());
            }
        }
    } else {
        $files[] = $storageRoot . '/audio/' . basename($datei);
    }

    if ($position === 'vorher') {
        $vorher = array_merge($vorher, $files);
    } else {
        $nachher = array_merge($nachher, $files);
    }
}

// ─── TTS-Datei aus Cache holen ────────────────────────────────────────────────

$ttsFile = null;
try {
    $stmt = $GLOBALS['pdo']->prepare(
        'SELECT audio_dateiname
         FROM wecker_tts_cache
         WHERE wecker_id = ?
         ORDER BY id DESC
         LIMIT 1'
    );
    $stmt->execute([$alarmId]);
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    if ($row && !empty($row['audio_dateiname'])) {
        $candidate = $storageRoot . '/tts/' . basename($row['audio_dateiname']);
        if (is_file($candidate)) {
            $ttsFile = $candidate;
        }
    }
} catch (Throwable $e) {
    error_log('[alarm_player] TTS-Cache-Fehler: ' . $e->getMessage());
}

// ─── Abspielsequenz ───────────────────────────────────────────────────────────

// 1) Musik VOR TTS
foreach ($vorher as $file) {
    if (!alarmIsActive($stateFile)) {
        break;
    }
    playFile($file);
}

// 2) TTS-Sprachausgabe
if ($ttsFile !== null && alarmIsActive($stateFile)) {
    playFile($ttsFile);
}

// 3) Musik NACH TTS
foreach ($nachher as $file) {
    if (!alarmIsActive($stateFile)) {
        break;
    }
    playFile($file);
}

// ─── PID aus State-Datei entfernen ───────────────────────────────────────────
if (is_file($stateFile)) {
    $raw = @file_get_contents($stateFile);
    if ($raw !== false && $raw !== '') {
        $s = @json_decode($raw, true) ?: [];
        unset($s['player_pid']);
        @file_put_contents($stateFile, json_encode($s));
    }
}
