<?php
declare(strict_types=1);

require __DIR__ . '/src/Meting.php';

header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store');

function respond(int $status, array $payload): void
{
    http_response_code($status);
    echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

if ($_SERVER['REQUEST_METHOD'] === 'GET' && parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) === '/health') {
    respond(200, ['ok' => true]);
}

$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !in_array($path, ['/search', '/url'], true)) {
    respond(404, ['error' => 'Not found']);
}

$configPath = getenv('METING_CONFIG') ?: __DIR__ . '/config.php';
if (!is_file($configPath)) {
    respond(503, ['error' => 'Service is not configured']);
}
$config = require $configPath;
$expectedKey = (string)($config['api_key'] ?? '');
$providedKey = (string)($_SERVER['HTTP_X_API_KEY'] ?? '');
if (strlen($expectedKey) < 32 || !hash_equals($expectedKey, $providedKey)) {
    respond(401, ['error' => 'Unauthorized']);
}

$body = json_decode(file_get_contents('php://input'), true);
if (!is_array($body)) {
    respond(400, ['error' => 'Invalid JSON body']);
}

$keyword = trim((string)($body['keyword'] ?? ''));
$source = (string)($body['source'] ?? 'netease');
$songId = (string)($body['id'] ?? '');
$page = filter_var($body['page'] ?? 1, FILTER_VALIDATE_INT);
$limit = filter_var($body['limit'] ?? 20, FILTER_VALIDATE_INT);
$bitrate = filter_var($body['br'] ?? 320, FILTER_VALIDATE_INT);
$sources = ['netease', 'tencent', 'kugou', 'kuwo'];

if (!in_array($source, $sources, true)) {
    respond(400, ['error' => 'Unsupported music source']);
}

try {
    $client = (new \Metowolf\Meting($source))->format(true);
    if ($path === '/search') {
        if ($keyword === '' || mb_strlen($keyword, 'UTF-8') > 100) {
            respond(400, ['error' => 'keyword must contain 1 to 100 characters']);
        }
        if ($page === false || $page < 1 || $page > 100 || $limit === false || $limit < 1 || $limit > 30) {
            respond(400, ['error' => 'page or limit is out of range']);
        }
        $raw = $client->search($keyword, ['page' => $page, 'limit' => $limit]);
        $songs = json_decode((string)$raw, true, 512, JSON_THROW_ON_ERROR);
        if (!is_array($songs)) {
            respond(502, ['error' => 'Music provider returned an invalid response']);
        }
        respond(200, ['source' => $source, 'keyword' => $keyword, 'songs' => array_slice($songs, 0, $limit)]);
    }

    if ($songId === '' || !preg_match('/^[A-Za-z0-9_-]{1,100}$/', $songId)) {
        respond(400, ['error' => 'A valid song id is required']);
    }
    if ($bitrate === false || !in_array($bitrate, [48, 96, 128, 192, 320, 999], true)) {
        respond(400, ['error' => 'Unsupported bitrate']);
    }

    $result = json_decode((string)$client->url($songId, $bitrate), true, 512, JSON_THROW_ON_ERROR);
    $audioUrl = $result['url'] ?? '';
    if (!is_string($audioUrl) || !filter_var($audioUrl, FILTER_VALIDATE_URL) || !in_array(parse_url($audioUrl, PHP_URL_SCHEME), ['http', 'https'], true)) {
        respond(404, ['error' => 'No playable URL is available for this track']);
    }
    respond(200, [
        'source' => $source,
        'id' => $songId,
        'url' => $audioUrl,
        'bitrate' => (int)($result['br'] ?? $bitrate),
        'size' => (int)($result['size'] ?? 0)
    ]);
} catch (Throwable $error) {
    error_log('Meting request failed: ' . $error->getMessage());
    respond(502, ['error' => 'Music provider request failed']);
}
