<?php
// ============================================================
//  admin/email-upload-attachment.php
// ============================================================
//
//  Receives attachment uploads via fetch() from the compose
//  page. Stores them in a per-session temp folder under
//  uploads/email-attach-tmp/. The compose page then references
//  these by token in a hidden field; on Send we read them back,
//  attach to the email, then delete.
//
//  Response:
//   200 OK: { "token": "abc...", "name": "report.pdf", "size": 12345, "mime": "application/pdf" }
//   4xx:    { "error": "..." }
//
//  Lifecycle: temp files are deleted after Send, OR garbage-
//  collected after 24 hours by a periodic check.
// ============================================================

require_once __DIR__ . '/../includes/auth.php';
require_once __DIR__ . '/../includes/config.php';
auth_require_admin();

header('Content-Type: application/json; charset=utf-8');
header('X-Content-Type-Options: nosniff');

function ea_err(int $code, string $msg): void {
    http_response_code($code);
    echo json_encode(['error' => $msg]);
    exit;
}

$me = auth_admin_user();

if ($_SERVER['REQUEST_METHOD'] !== 'POST') ea_err(405, 'POST required');

if (!isset($_FILES['file']) || !is_uploaded_file($_FILES['file']['tmp_name'] ?? '')) {
    ea_err(400, 'No file');
}

$file = $_FILES['file'];
if ($file['error'] !== UPLOAD_ERR_OK) ea_err(400, 'Upload failed (code ' . $file['error'] . ')');

// 25 MB limit per attachment
$max_size = 25 * 1024 * 1024;
if ($file['size'] > $max_size) ea_err(413, 'Attachment too large — 25 MB maximum.');

// Sanity check filename
$original = (string)($file['name'] ?? 'attachment');
$original = preg_replace('/[\r\n"\\\\]/', '_', $original);
$original = mb_substr($original, 0, 200);
if ($original === '') $original = 'attachment';

// MIME via finfo (don't trust client)
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime  = $finfo->file($file['tmp_name']) ?: 'application/octet-stream';

// Refuse a few clearly-dangerous MIME types (the server should never RUN these
// either, but be belt-and-braces: don't even let people send them)
$forbidden = ['application/x-msdownload', 'application/x-msdos-program', 'application/x-executable'];
if (in_array($mime, $forbidden, true)) ea_err(415, 'That file type is not allowed.');

$install_root = realpath(__DIR__ . '/..');
$temp_dir = $install_root . '/uploads/email-attach-tmp/' . (int)$me['id'];
if (!is_dir($temp_dir)) {
    if (!@mkdir($temp_dir, 0755, true) && !is_dir($temp_dir)) ea_err(500, 'Could not create temp dir');
}

// Garbage-collect old uploads (>24h) on each new upload — cheap
$cutoff = time() - 86400;
foreach (glob($temp_dir . '/*.bin') ?: [] as $old) {
    if (@filemtime($old) < $cutoff) @unlink($old);
}
foreach (glob($temp_dir . '/*.meta.json') ?: [] as $old) {
    if (@filemtime($old) < $cutoff) @unlink($old);
}

$token = bin2hex(random_bytes(16));
$dest  = $temp_dir . '/' . $token . '.bin';
$meta  = $temp_dir . '/' . $token . '.meta.json';

if (!@move_uploaded_file($file['tmp_name'], $dest)) ea_err(500, 'Could not save upload');
@chmod($dest, 0600);

file_put_contents($meta, json_encode([
    'name' => $original,
    'mime' => $mime,
    'size' => (int)$file['size'],
    'created' => time(),
]));
@chmod($meta, 0600);

echo json_encode([
    'token' => $token,
    'name'  => $original,
    'size'  => (int)$file['size'],
    'mime'  => $mime,
]);