<?php
declare(strict_types=1);

$uploadDir = '/var/rsv/data/backup/';
$maxSize = 2 * 1024 * 1024 * 1024; // 2GB
$allowedExtensions = ['zip'];
$allowedMimeTypes = [
    'application/zip',
    'application/x-zip-compressed',
    'multipart/x-zip'
];

function respond(int $code, string $message): void {
    http_response_code($code);
    header('Content-Type: text/plain; charset=utf-8');
    echo $message;
    exit;
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    respond(405, 'Method not allowed.');
}

if (!isset($_FILES['file'])) {
    respond(400, 'No file uploaded.');
}

if ($_FILES['file']['error'] !== UPLOAD_ERR_OK) {
    respond(400, 'Upload failed with error code: ' . $_FILES['file']['error']);
}

$tmpPath = $_FILES['file']['tmp_name'];
$originalName = $_FILES['file']['name'] ?? '';
$fileSize = (int)($_FILES['file']['size'] ?? 0);

if ($fileSize <= 0 || $fileSize > $maxSize) {
    respond(413, 'Invalid file size.');
}

$extension = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
if (!in_array($extension, $allowedExtensions, true)) {
    respond(415, 'Only .zip files are allowed.');
}

$finfo = new finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->file($tmpPath);

if (!in_array($mimeType, $allowedMimeTypes, true)) {
    respond(415, 'Invalid MIME type: ' . $mimeType);
}

if (!is_dir($uploadDir)) {
    respond(500, 'Upload directory does not exist.');
}

if (!is_writable($uploadDir)) {
    respond(500, 'Upload directory is not writable.');
}

$baseName = basename($originalName);
$baseName = preg_replace('/[^a-zA-Z0-9._-]/', '_', $baseName);
$baseName = preg_replace('/_+/', '_', $baseName);

$nameWithoutExt = pathinfo($baseName, PATHINFO_FILENAME);
$nameWithoutExt = substr($nameWithoutExt, 0, 120);

$finalName = date('Ymd-His') . '-' . bin2hex(random_bytes(4)) . '-' . $nameWithoutExt . '.zip';
$destPath = $uploadDir . $finalName;

if (!move_uploaded_file($tmpPath, $destPath)) {
    respond(500, 'Failed to move uploaded file.');
}

chmod($destPath, 0640);

$url = 'https://' . $_SERVER['HTTP_HOST'] . '/backup/' . rawurlencode($finalName);
respond(200, $url);
