<?php
/**
 * /api/dashboard/preview.php?id=123[&version_id=5][&download=1]
 *
 * Streams the on-disk original file for a document, with the correct
 * Content-Type. Used by PDF.js, the <audio> player, image previews, and
 * "Download original" links.
 *
 * ACL: enforces folder read permission on the document.
 */

declare(strict_types=1);

require_once dirname(__DIR__, 2) . '/includes/bootstrap.php';

dbnToolsRequireAuth();

try {
    $tenant = dbnToolsEnsureDashboardTenant();
} catch (DbnToolsHttpException $e) {
    dbnToolsError($e->getMessage(), $e->status, $e->errorCode);
}
$clientId   = (int)$tenant['client_id'];
$userId     = (int)($tenant['client_user_id'] ?? 0);
$tenantRole = (string)($tenant['role'] ?? 'editor');

$id        = (int)($_GET['id'] ?? 0);
$versionId = (int)($_GET['version_id'] ?? 0);
$download  = !empty($_GET['download']);

if ($id <= 0) {
    dbnToolsError('id is required.', 400, 'missing_id');
}

$db = dbnToolsDb();

$stmt = $db->prepare('SELECT id, folder_id, storage_path, original_filename, source_type FROM client_documents WHERE id = ? AND client_id = ?');
$stmt->execute([$id, $clientId]);
$doc = $stmt->fetch();
if (!$doc) {
    dbnToolsError('Document not found.', 404, 'not_found');
}
$fid = $doc['folder_id'] ? (int)$doc['folder_id'] : 0;
if (!dbnDmsUserCanAccessFolder($fid ?: null, 'read', $clientId, $userId, $tenantRole)) {
    dbnToolsError('Forbidden.', 403, 'forbidden');
}

$path = (string)($doc['storage_path'] ?? '');
$filename = (string)($doc['original_filename'] ?? '');

if ($versionId > 0) {
    $vs = $db->prepare('SELECT storage_path, original_filename FROM client_document_versions WHERE id = ? AND document_id = ? AND client_id = ?');
    $vs->execute([$versionId, $id, $clientId]);
    $ver = $vs->fetch();
    if (!$ver) {
        dbnToolsError('Version not found.', 404, 'version_not_found');
    }
    $path     = (string)($ver['storage_path'] ?? '');
    $filename = (string)($ver['original_filename'] ?? $filename);
}

if ($path === '' || !is_file($path) || !is_readable($path)) {
    dbnToolsError('Original file is not available for this document.', 404, 'file_missing',
        ['hint' => 'Document predates disk storage, or file was purged.']);
}

$ext = dbnDmsExtensionFromFilename($filename);
if ($ext === '' && $path !== '') {
    $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
}
$contentType = dbnDmsContentTypeForExt($ext);

dbnDmsLogAudit($clientId, $userId ?: null, $download ? 'download' : 'preview',
    ['version_id' => $versionId ?: null, 'ext' => $ext], $id, $fid ?: null);

// Suppress any earlier output (defensive).
if (ob_get_level() > 0) { @ob_end_clean(); }

$size = filesize($path) ?: 0;
header('Content-Type: ' . $contentType);
header('Content-Length: ' . $size);
header('X-Content-Type-Options: nosniff');
header('Cache-Control: private, max-age=300');
$disposition = $download ? 'attachment' : 'inline';
$safeName = $filename !== '' ? $filename : ('document-' . $id . '.' . ($ext ?: 'bin'));
$safeName = preg_replace('/[\r\n"]/', '_', $safeName) ?? $safeName;
header(sprintf('Content-Disposition: %s; filename="%s"', $disposition, $safeName));

// Range requests (basic) — useful for PDF.js + audio scrubbing.
$range = $_SERVER['HTTP_RANGE'] ?? '';
if ($range && preg_match('/bytes=(\d+)-(\d+)?/', $range, $m)) {
    $start = (int)$m[1];
    $end   = isset($m[2]) && $m[2] !== '' ? (int)$m[2] : ($size - 1);
    if ($end >= $size) $end = $size - 1;
    $length = $end - $start + 1;
    http_response_code(206);
    header('Accept-Ranges: bytes');
    header("Content-Range: bytes {$start}-{$end}/{$size}");
    header('Content-Length: ' . $length);
    $fh = fopen($path, 'rb');
    if ($fh) {
        fseek($fh, $start);
        $remaining = $length;
        while (!feof($fh) && $remaining > 0) {
            $chunk = fread($fh, min(8192, $remaining));
            if ($chunk === false) break;
            echo $chunk;
            $remaining -= strlen($chunk);
            @ob_flush(); @flush();
        }
        fclose($fh);
    }
    exit;
}

header('Accept-Ranges: bytes');
readfile($path);
exit;
