<?php
// A dynamically generated CSV served as an attachment. Stands in for the SGH
// ED dashboard's results_<timestamp>.csv, and mirrors the response headers
// seen in the surrogate net-log from the field capture:
//
//    HTTP/1.1 200 OK
//    Content-Type: text/csv
//    Content-Length: 94617
//    Content-Disposition: attachment; filename=results_2026-08-24T03-39-11.csv
//    Cache-Control: no-cache
//
// The filename is timestamped on every request, as the dashboard's is, so a
// repeat download cannot be served from cache or collide on disk.
//
// ?size=<bytes>    body size, default 94617 (the size in the capture)
// ?delay_ms=<ms>   spread the body over this many ms, as attachment_pdf_slow
//                  does, to push completion past the activation window
set_time_limit(0);

$target_size = isset($_GET['size']) ? intval($_GET['size']) : 94617;
$delay_ms = isset($_GET['delay_ms']) ? intval($_GET['delay_ms']) : 0;

$body = "attendance_id,arrival_time,triage_category,disposition,ward,los_minutes\n";
$row_no = 0;
while (true) {
   $row_no += 1;
   $row = sprintf("A%06d,2026-06-11T%02d:%02d:%02d,P%d,%s,W%02d,%d\n",
                  $row_no,
                  $row_no % 24, $row_no % 60, ($row_no * 7) % 60,
                  ($row_no % 4) + 1,
                  ($row_no % 2) ? "Admitted" : "Discharged",
                  ($row_no % 12) + 1,
                  ($row_no * 13) % 480);
   if (strlen($body) + strlen($row) > $target_size) {
      break;
   }
   $body .= $row;
}
// Whole rows rarely land on @target_size exactly. Pad the last field with
// spaces rather than truncating, so the body is byte-exact and every row is
// still parseable as CSV.
$pad = $target_size - strlen($body);
if ($pad > 0) {
   $body = substr($body, 0, -1) . str_repeat(' ', $pad) . "\n";
}

$filename = "results_" . gmdate("Y-m-d\TH-i-s") . ".csv";

header("HTTP/1.1 200 OK");
header("Content-Type: text/csv");
header("Content-Disposition: attachment; filename=" . $filename);
header("Content-Length: " . strlen($body));
header("Cache-Control: no-cache");

if ($delay_ms <= 0) {
   echo $body;
} else {
   $chunks = 20;
   $chunk_size = (int)ceil(strlen($body) / $chunks);
   $chunk_delay_us = intval($delay_ms * 1000 / $chunks);
   for ($offset = 0; $offset < strlen($body); $offset += $chunk_size) {
      echo substr($body, $offset, $chunk_size);
      flush();
      usleep($chunk_delay_us);
   }
}
?>
