<?php
/**
 * Liefert das eingebettete Cover-Bild aus einer Audio-Datei (ID3v2 APIC bei MP3).
 * Aufruf: /audio_cover.php?f=datei.mp3
 * Bei Fehler oder keinem Cover: Platzhalter-SVG (kein 404, damit Konsole sauber bleibt).
 */
require __DIR__ . '/../config.php';

$f = isset($_GET['f']) ? basename($_GET['f']) : '';
if ($f === '' || preg_match('/[^a-zA-Z0-9_.-]/', $f)) {
    http_response_code(400);
    exit;
}

$path = rtrim(STORAGE_ROOT, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'audio' . DIRECTORY_SEPARATOR . $f;
if (!is_file($path) || !is_readable($path)) {
    audio_cover_placeholder();
    exit;
}

$ext = strtolower(pathinfo($f, PATHINFO_EXTENSION));
if ($ext !== 'mp3') {
    audio_cover_placeholder();
    exit;
}

$data = @file_get_contents($path, false, null, 0, 256 * 1024);
if ($data === false || strlen($data) < 10) {
    audio_cover_placeholder();
    exit;
}

if (substr($data, 0, 3) !== 'ID3') {
    audio_cover_placeholder();
    exit;
}

$tagSize = (ord($data[6]) & 0x7f) << 21 | (ord($data[7]) & 0x7f) << 14 | (ord($data[8]) & 0x7f) << 7 | (ord($data[9]) & 0x7f);
$pos = 10;
$end = min(10 + $tagSize, strlen($data));

$v4 = (ord($data[3]) === 4);
while ($pos + 10 <= $end) {
    $frameId = substr($data, $pos, 4);
    $pos += 4;
    if ($v4) {
        $frameSize = (ord($data[$pos]) & 0x7f) << 21 | (ord($data[$pos+1]) & 0x7f) << 14 | (ord($data[$pos+2]) & 0x7f) << 7 | (ord($data[$pos+3]) & 0x7f);
    } else {
        $frameSize = ord($data[$pos]) << 24 | ord($data[$pos+1]) << 16 | ord($data[$pos+2]) << 8 | ord($data[$pos+3]);
    }
    $pos += 6;
    if ($frameId === 'APIC' && $frameSize > 0 && $pos + $frameSize <= strlen($data)) {
        $frameData = substr($data, $pos, $frameSize);
        $enc = ord($frameData[0]);
        $mimeEnd = strpos($frameData, "\0", 1);
        if ($mimeEnd === false) break;
        $mime = trim(substr($frameData, 1, $mimeEnd - 1));
        $picTypePos = $mimeEnd + 1;
        $descStart = $picTypePos + 1;
        if ($enc === 1) {
            $descEnd = strpos($frameData, "\0\0", $descStart);
            $picStart = $descEnd !== false ? $descEnd + 2 : $descStart;
        } else {
            $descEnd = strpos($frameData, "\0", $descStart);
            $picStart = $descEnd !== false ? $descEnd + 1 : $descStart;
        }
        if ($picStart < $frameSize && $picStart > 0) {
            $img = substr($frameData, $picStart);
            $mime = $mime ?: 'image/jpeg';
            if (strpos($mime, 'image/') !== 0) $mime = 'image/jpeg';
            header('Content-Type: ' . $mime);
            header('Cache-Control: public, max-age=86400');
            echo $img;
            exit;
        }
    }
    $pos += $frameSize;
}

function audio_cover_placeholder(): void {
    header('Content-Type: image/svg+xml');
    header('Cache-Control: public, max-age=3600');
    echo '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#888" stroke-width="1.5"><path d="M9 18V5l12-2v13"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="16" r="3"/></svg>';
}
audio_cover_placeholder();
