<?php
declare(strict_types=1);
require __DIR__ . '/../lib/bootstrap.php';
handle_cors_preflight();
require_method(['POST']);
rate_limit('playlist-write', 90, 60);

$input = input_json();
$device = authenticate_device($input);
$action = strtolower(trim((string) ($input['action'] ?? 'save')));

function clean_text($value, int $maxLength): string
{
    return truncate_text(trim((string) $value), $maxLength);
}

function normalized_optional_url($value): ?string
{
    $url = clean_text($value, 2000);
    if ($url === '') {
        return null;
    }
    if (!filter_var($url, FILTER_VALIDATE_URL) || !in_array(strtolower((string) parse_url($url, PHP_URL_SCHEME)), ['http', 'https'], true)) {
        json_response(['ok' => false, 'error' => 'Invalid URL'], 422);
    }
    return $url;
}

function normalize_playlist_input(array $input): array
{
    $type = strtolower(clean_text($input['type'] ?? '', 20));
    $name = clean_text($input['name'] ?? $input['playlist_name'] ?? 'Main IPTV', 255) ?: 'Main IPTV';
    $output = strtolower(clean_text($input['output'] ?? 'm3u8', 20));
    if (!in_array($type, ['m3u', 'xtream'], true) || !in_array($output, ['m3u8', 'ts'], true)) {
        json_response(['ok' => false, 'error' => 'Invalid playlist type or output format'], 422);
    }

    $playlist = [
        'id' => max(0, (int) ($input['id'] ?? $input['playlist_id'] ?? 0)),
        'name' => $name,
        'type' => $type,
        'playlist_url' => null,
        'server_url' => null,
        'username' => null,
        'password' => null,
        'output' => $output,
        'epg_url' => normalized_optional_url($input['epg_url'] ?? ''),
        'catchup_mode' => clean_text($input['catchup_mode'] ?? '', 30) ?: null,
        'enabled' => !array_key_exists('enabled', $input) || (bool) $input['enabled'] ? 1 : 0,
    ];

    if ($type === 'm3u') {
        $playlist['playlist_url'] = normalized_optional_url($input['playlist_url'] ?? $input['url'] ?? '');
        if (!$playlist['playlist_url']) {
            json_response(['ok' => false, 'error' => 'A valid playlist URL is required'], 422);
        }
        return $playlist;
    }

    $serverUrl = rtrim((string) normalized_optional_url($input['server_url'] ?? $input['server'] ?? ''), '/');
    $username = clean_text($input['username'] ?? '', 255);
    $password = clean_text($input['password'] ?? '', 500);
    if ($serverUrl === '' || $username === '' || $password === '') {
        json_response(['ok' => false, 'error' => 'Server URL, username and password are required'], 422);
    }
    $playlist['server_url'] = $serverUrl;
    $playlist['username'] = $username;
    $playlist['password'] = encrypt_secret($password);
    return $playlist;
}

function save_playlist_for_device(int $deviceId, array $playlist): void
{
    $pdo = db();
    $maxPlaylists = max(1, (int) config('app.max_playlists', 10));
    if ($playlist['id'] > 0) {
        $exists = $pdo->prepare('SELECT 1 FROM playlists WHERE id = ? AND device_id = ?');
        $exists->execute([$playlist['id'], $deviceId]);
        if (!$exists->fetchColumn()) {
            json_response(['ok' => false, 'error' => 'Playlist not found'], 404);
        }
    } else {
        $count = $pdo->prepare('SELECT COUNT(*) FROM playlists WHERE device_id = ?');
        $count->execute([$deviceId]);
        if ((int) $count->fetchColumn() >= $maxPlaylists) {
            json_response(['ok' => false, 'error' => 'Playlist limit reached'], 409);
        }
    }

    $ownsTransaction = !$pdo->inTransaction();
    if ($ownsTransaction) {
        $pdo->beginTransaction();
    }
    try {
        if ($playlist['enabled']) {
            $pdo->prepare('UPDATE playlists SET enabled = 0 WHERE device_id = ?')->execute([$deviceId]);
        }
        if ($playlist['id'] > 0) {
            $pdo->prepare(
                'UPDATE playlists SET playlist_name = ?, playlist_type = ?, playlist_url = ?, server_url = ?, username = ?,
                 password = ?, output_format = ?, epg_url = ?, catchup_mode = ?, enabled = ?, updated_at = NOW()
                 WHERE id = ? AND device_id = ?'
            )->execute([$playlist['name'], $playlist['type'], $playlist['playlist_url'], $playlist['server_url'], $playlist['username'],
                $playlist['password'], $playlist['output'], $playlist['epg_url'], $playlist['catchup_mode'], $playlist['enabled'], $playlist['id'], $deviceId]);
        } else {
            $pdo->prepare(
                'INSERT INTO playlists (device_id, playlist_name, playlist_type, playlist_url, server_url, username, password, output_format, epg_url, catchup_mode, enabled)
                 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
            )->execute([$deviceId, $playlist['name'], $playlist['type'], $playlist['playlist_url'], $playlist['server_url'], $playlist['username'],
                $playlist['password'], $playlist['output'], $playlist['epg_url'], $playlist['catchup_mode'], $playlist['enabled']]);
        }
        if ($ownsTransaction) {
            $pdo->commit();
        }
    } catch (Throwable $error) {
        if ($ownsTransaction && $pdo->inTransaction()) {
            $pdo->rollBack();
        }
        throw $error;
    }
}

if ($action === 'delete') {
    $id = max(0, (int) ($input['id'] ?? $input['playlist_id'] ?? 0));
    $pdo = db();
    $pdo->beginTransaction();
    try {
        $wasEnabled = false;
        if ($id > 0) {
            $lookup = $pdo->prepare('SELECT enabled FROM playlists WHERE device_id = ? AND id = ?');
            $lookup->execute([(int) $device['id'], $id]);
            $existing = $lookup->fetch();
            if (!$existing) {
                $pdo->rollBack();
                json_response(['ok' => false, 'error' => 'Playlist not found'], 404);
            }
            $wasEnabled = (bool) $existing['enabled'];
        }
        $stmt = $pdo->prepare($id > 0 ? 'DELETE FROM playlists WHERE device_id = ? AND id = ?' : 'DELETE FROM playlists WHERE device_id = ?');
        $stmt->execute($id > 0 ? [(int) $device['id'], $id] : [(int) $device['id']]);
        if ($id > 0 && $wasEnabled) {
            $pdo->prepare('UPDATE playlists SET enabled = 1 WHERE device_id = ? ORDER BY id ASC LIMIT 1')->execute([(int) $device['id']]);
        }
        $pdo->commit();
    } catch (Throwable $error) {
        if ($pdo->inTransaction()) {
            $pdo->rollBack();
        }
        throw $error;
    }
    audit_log('playlist.deleted', (int) $device['id'], ['playlist_id' => $id ?: 'all']);
} elseif ($action === 'save_many') {
    $items = $input['playlists'] ?? null;
    $maxPlaylists = max(1, (int) config('app.max_playlists', 10));
    if (!is_array($items) || count($items) > $maxPlaylists) {
        json_response(['ok' => false, 'error' => 'A valid playlists array is required'], 422);
    }
    $normalized = [];
    $enabledFound = false;
    foreach ($items as $item) {
        if (!is_array($item)) {
            continue;
        }
        $playlist = normalize_playlist_input($item);
        $playlist['id'] = 0;
        if ($playlist['enabled'] && !$enabledFound) {
            $enabledFound = true;
        } else {
            $playlist['enabled'] = 0;
        }
        $normalized[] = $playlist;
    }
    if (!$enabledFound && $normalized) {
        $normalized[0]['enabled'] = 1;
    }
    $pdo = db();
    $pdo->beginTransaction();
    try {
        $pdo->prepare('DELETE FROM playlists WHERE device_id = ?')->execute([(int) $device['id']]);
        foreach ($normalized as $playlist) {
            save_playlist_for_device((int) $device['id'], $playlist);
        }
        $pdo->commit();
    } catch (Throwable $error) {
        $pdo->rollBack();
        throw $error;
    }
    audit_log('playlist.replaced', (int) $device['id'], ['count' => count($normalized)]);
} elseif ($action === 'save') {
    save_playlist_for_device((int) $device['id'], normalize_playlist_input($input));
    audit_log('playlist.saved', (int) $device['id']);
} else {
    json_response(['ok' => false, 'error' => 'Unsupported playlist action'], 422);
}

$saved = get_device_playlists((int) $device['id']);
json_response([
    'ok' => true,
    'playlist' => public_playlist_payload(get_device_playlist((int) $device['id'])),
    'playlists' => public_playlists_payload($saved),
]);
