<?php
// =============================================================================
// /api/webview/slideshows.php — Media Slideshow image CRUD + upload.
//
// GET   ?action=list           → { images: [...], slide_interval_ms: N }
// POST  action=create_url      → register an external URL as a slide
// POST  action=upload          → multipart/form-data: file (image) + sort
// POST  action=delete          → id
// POST  action=reorder         → ids[] in desired order
// POST  action=set_interval    → ms
// =============================================================================
require_once __DIR__ . '/../_common.php';
require_csrf_unless_get();

$UPLOAD_DIR = __DIR__ . '/../../uploads/slideshows';
$UPLOAD_URL = 'uploads/slideshows';                 // relative to panel base
$MAX_BYTES  = 8 * 1024 * 1024;                      // 8 MiB
$ALLOWED    = ['jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg',
               'png' => 'image/png',  'gif' => 'image/gif',
               'webp'=> 'image/webp'];

if (!is_dir($UPLOAD_DIR)) @mkdir($UPLOAD_DIR, 0775, true);

list($action, $body) = read_action();

if ($action === 'list' || ($_SERVER['REQUEST_METHOD'] === 'GET' && $action === '')) {
    $rows = db_all('SELECT id, image_url, duration_ms, sort, enabled
                    FROM webview_slideshows ORDER BY sort ASC, id ASC');
    $row  = db_one('SELECT value FROM webview_settings WHERE key=?', ['slide_interval_ms']);
    $ms   = $row ? max(1000, (int)$row['value']) : 5000;
    $fitRow = db_one('SELECT value FROM webview_settings WHERE key=?', ['slide_fit_mode']);
    $fit    = in_array($fitRow['value'] ?? '', ['cover','contain'], true) ? $fitRow['value'] : 'contain';
    json_response(['images' => $rows, 'slide_interval_ms' => $ms, 'slide_fit_mode' => $fit]);
}

require_method('POST');

if ($action === 'create_url') {
    $url = trim((string)($body['url'] ?? ''));
    if ($url === '' || !preg_match('#^https?://#i', $url)) json_error('valid url required', 400);
    $id = db_insert(
        'INSERT INTO webview_slideshows (image_url, duration_ms, sort, enabled, created_at)
         VALUES (?, ?, ?, 1, ?)',
        [$url, (int)($body['duration_ms'] ?? 0) ?: 0, (int)($body['sort'] ?? 0), time()]);
    json_response(['ok' => true, 'id' => $id]);
}

if ($action === 'upload') {
    if (empty($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
        json_error('no file (' . ($_FILES['file']['error'] ?? 'missing') . ')', 400);
    }
    $f = $_FILES['file'];
    if ((int)$f['size'] > $MAX_BYTES) json_error('file too large (max 8 MiB)', 400);
    $ext = strtolower(pathinfo($f['name'], PATHINFO_EXTENSION));
    if (!isset($ALLOWED[$ext])) json_error('unsupported extension', 400);

    // Validate the actual mime-type so a renamed PHP/HTML doesn't slip through.
    // Prefer fileinfo when available; fall back to getimagesize() (always
    // present with GD, standard on cPanel/aaPanel) so hosts without the
    // fileinfo extension still get a real check.
    $mime = null;
    if (function_exists('finfo_open')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mime  = $finfo ? finfo_file($finfo, $f['tmp_name']) : null;
        if ($finfo) finfo_close($finfo);
    }
    if ($mime === null || $mime === false) {
        $info = @getimagesize($f['tmp_name']);
        $mime = is_array($info) && !empty($info['mime']) ? $info['mime'] : null;
    }
    if ($mime === null || $mime !== $ALLOWED[$ext]) {
        json_error('mime mismatch (' . ($mime ?: 'unknown') . ')', 400);
    }

    $name  = bin2hex(random_bytes(6)) . '_' . preg_replace('/[^a-z0-9._-]/i', '_', basename($f['name']));
    $dest  = $UPLOAD_DIR . '/' . $name;
    if (!move_uploaded_file($f['tmp_name'], $dest)) json_error('move failed', 500);
    @chmod($dest, 0644);

    $url = $UPLOAD_URL . '/' . $name;
    $id  = db_insert(
        'INSERT INTO webview_slideshows (image_url, duration_ms, sort, enabled, created_at)
         VALUES (?, 0, ?, 1, ?)',
        [$url, (int)($body['sort'] ?? 0), time()]
    );
    json_response(['ok' => true, 'id' => $id, 'image_url' => $url]);
}

if ($action === 'delete') {
    $id = (int)($body['id'] ?? 0);
    if ($id <= 0) json_error('id required', 400);
    $row = db_one('SELECT image_url FROM webview_slideshows WHERE id=?', [$id]);
    db_exec('DELETE FROM webview_slideshows WHERE id=?', [$id]);
    // If the URL points at our uploads dir, remove the file too.
    if ($row && strpos($row['image_url'], $UPLOAD_URL . '/') === 0) {
        $fp = __DIR__ . '/../../' . $row['image_url'];
        if (is_file($fp)) @unlink($fp);
    }
    json_response(['ok' => true]);
}

if ($action === 'reorder') {
    $ids = $body['ids'] ?? [];
    if (!is_array($ids)) json_error('ids[] required', 400);
    $sort = 0;
    foreach ($ids as $id) {
        $id = (int)$id;
        if ($id > 0) db_exec('UPDATE webview_slideshows SET sort=? WHERE id=?', [$sort++, $id]);
    }
    json_response(['ok' => true, 'reordered' => $sort]);
}

if ($action === 'set_interval') {
    $ms = max(1000, (int)($body['ms'] ?? 5000));
    db_exec('INSERT INTO webview_settings (key, value, updated_at) VALUES (?, ?, ?)
             ON CONFLICT(key) DO UPDATE SET value=excluded.value, updated_at=excluded.updated_at',
            ['slide_interval_ms', (string)$ms, time()]);
    json_response(['ok' => true, 'ms' => $ms]);
}

if ($action === 'set_fit_mode') {
    $fit = in_array($body['fit'] ?? '', ['cover','contain'], true) ? $body['fit'] : 'contain';
    db_exec('INSERT INTO webview_settings (key, value, updated_at) VALUES (?, ?, ?)
             ON CONFLICT(key) DO UPDATE SET value=excluded.value, updated_at=excluded.updated_at',
            ['slide_fit_mode', $fit, time()]);
    json_response(['ok' => true, 'fit' => $fit]);
}

json_error('unknown action', 400);
