<?php
require_once __DIR__ . '/common.php';

$input = mobile_input();
mobile_boot_tenant($input);
$surveyor = mobile_authorise();

$items = $input['items'] ?? [];
$reports = $input['reports'] ?? [];
$images = $input['images'] ?? [];
if (!is_array($items)) {
    $items = [];
}
if (!is_array($reports)) {
    $reports = [];
}
if (!is_array($images)) {
    $images = [];
}
if (empty($items) && empty($reports) && empty($images)) {
    mobile_json(['ok' => false, 'error' => 'No items, reports or images supplied'], 400);
}

$tenant = defined('TENANT_URL') ? TENANT_URL : (string)($input['tenant'] ?? '');
$itemResults = [];
$itemErrors = [];
$itemMap = [];
$results = [];
$errors = [];
$imageResults = [];
$imageErrors = [];
$mobileUploadFinished = false;
$mobileUploadInitialObLevel = ob_get_level();
$mobileUploadCurrentReport = null;

register_shutdown_function(function () use (&$mobileUploadFinished, &$itemResults, &$itemErrors, &$results, &$errors, &$imageResults, &$imageErrors, &$mobileUploadCurrentReport, $mobileUploadInitialObLevel): void {
    if ($mobileUploadFinished) {
        return;
    }

    // Let the global mobile shutdown handler report real fatals. This fallback is for legacy include exit/die paths.
    $lastError = error_get_last();
    if ($lastError && in_array((int)$lastError['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR], true)) {
        return;
    }

    while (ob_get_level() > $mobileUploadInitialObLevel) {
        ob_end_clean();
    }

    if ($mobileUploadCurrentReport && empty($errors)) {
        $errors[] = [
            'localId' => (string)($mobileUploadCurrentReport['localId'] ?? ''),
            'error' => 'Report save stopped before completion. The linked item may already have synced.',
        ];
    }

    if (!headers_sent()) {
        http_response_code(207);
        header('Content-Type: application/json; charset=utf-8');
        header('Cache-Control: no-store');
    }

    echo json_encode([
        'ok' => false,
        'items' => $itemResults,
        'uploaded' => $results,
        'images' => $imageResults,
        'item_errors' => $itemErrors,
        'image_errors' => $imageErrors,
        'errors' => $errors,
    ], JSON_UNESCAPED_SLASHES);
});

foreach ($items as $index => $itemPayload) {
    if (!is_array($itemPayload)) {
        $itemErrors[] = ['index' => $index, 'error' => 'Invalid item payload'];
        continue;
    }

    $localId = (string)($itemPayload['localId'] ?? '');
    $clientnumber = (int)($itemPayload['clientnumber'] ?? 0);
    $locnumber = (int)($itemPayload['locnumber'] ?? 0);
    $description = trim((string)($itemPayload['description'] ?? ''));

    if ($localId === '' || $clientnumber <= 0 || $description === '') {
        $itemErrors[] = ['localId' => $localId, 'error' => 'Missing item, client or description'];
        continue;
    }

    $accessError = mobile_assert_client_location_access($surveyor, $clientnumber, $locnumber);
    if ($accessError !== '') {
        $itemErrors[] = ['localId' => $localId, 'error' => $accessError];
        continue;
    }

    $created = mobile_create_item($itemPayload, $clientnumber, $locnumber);
    if (!$created['ok']) {
        $itemErrors[] = ['localId' => $localId, 'error' => $created['error']];
        continue;
    }

    $itemnumber = (int)$created['itemnumber'];
    $itemMap[$localId] = $itemnumber;
    $itemResults[] = [
        'localId' => $localId,
        'itemnumber' => $itemnumber,
        'clientnumber' => $clientnumber,
        'locnumber' => (int)$created['locnumber'],
    ];
}

foreach ($reports as $index => $report) {
    $mobileUploadCurrentReport = is_array($report) ? $report : null;

    if (!is_array($report)) {
        $errors[] = ['index' => $index, 'error' => 'Invalid report payload'];
        $mobileUploadCurrentReport = null;
        continue;
    }

    $localId = (string)($report['localId'] ?? '');
    $itemLocalId = (string)($report['itemLocalId'] ?? '');
    $itemnumber = (int)($report['itemnumber'] ?? 0);
    if ($itemnumber <= 0 && $itemLocalId !== '' && isset($itemMap[$itemLocalId])) {
        $itemnumber = (int)$itemMap[$itemLocalId];
        $report['itemnumber'] = $itemnumber;
    }
    $clientnumber = (int)($report['clientnumber'] ?? 0);
    $locnumber = (int)($report['locnumber'] ?? 0);
    $reptype = (int)($report['formNumber'] ?? 0);
    $answers = isset($report['answers']) && is_array($report['answers']) ? $report['answers'] : [];

    if ($localId === '' || $itemnumber <= 0 || $clientnumber <= 0 || $reptype <= 0) {
        $errors[] = ['localId' => $localId, 'error' => 'Missing report, item, client or form reference'];
        $mobileUploadCurrentReport = null;
        continue;
    }

    $accessError = mobile_assert_item_access($surveyor, $clientnumber, $itemnumber);
    if ($accessError !== '') {
        $errors[] = ['localId' => $localId, 'error' => $accessError];
        $mobileUploadCurrentReport = null;
        continue;
    }

    $item = mobile_item_context($itemnumber);
    if (!$item) {
        $errors[] = ['localId' => $localId, 'error' => 'Item not found'];
        $mobileUploadCurrentReport = null;
        continue;
    }

    if ($locnumber <= 0) {
        $locnumber = (int)($item['locnumber'] ?? 0);
    }

    $saveRequest = mobile_build_report_request($tenant, $surveyor, $report, $answers, $item, $clientnumber, $itemnumber, $locnumber, $reptype);
    try {
        $saveOutput = mobile_run_report_save($saveRequest);
    } catch (Throwable $e) {
        $errors[] = [
            'localId' => $localId,
            'error' => 'Report save failed: ' . $e->getMessage(),
        ];
        $mobileUploadCurrentReport = null;
        continue;
    }

    $parts = explode('|', $saveOutput);
    $requestedRepnumber = (int)($report['repnumber'] ?? 0);
    $isUpdateOutput = trim($saveOutput) === 'update_success';
    if (!$isUpdateOutput && (($parts[0] ?? '') !== 'success' || empty($parts[1]))) {
        $errors[] = [
            'localId' => $localId,
            'error' => $saveOutput !== '' ? $saveOutput : 'Report save failed',
        ];
        $mobileUploadCurrentReport = null;
        continue;
    }

    $repnumber = $isUpdateOutput ? $requestedRepnumber : (int)$parts[1];
    if (!mobile_report_exists($repnumber, $itemnumber, $clientnumber)) {
        $errors[] = [
            'localId' => $localId,
            'error' => 'Report save returned a number but the report was not found afterwards.',
        ];
        $mobileUploadCurrentReport = null;
        continue;
    }

    try {
        $pdfOutput = mobile_generate_report_pdf($tenant, $clientnumber, $itemnumber, $repnumber, $reptype);
    } catch (Throwable $e) {
        $errors[] = [
            'localId' => $localId,
            'error' => 'Report saved but PDF generation failed: ' . $e->getMessage(),
        ];
        $mobileUploadCurrentReport = null;
        continue;
    }

    $results[] = [
        'localId' => $localId,
        'itemnumber' => $itemnumber,
        'repnumber' => $repnumber,
        'pdf' => $pdfOutput,
    ];
    $mobileUploadCurrentReport = null;
}

foreach ($images as $index => $image) {
    if (!is_array($image)) {
        $imageErrors[] = ['index' => $index, 'error' => 'Invalid image payload'];
        continue;
    }

    $localId = (string)($image['localId'] ?? '');
    $itemnumber = (int)($image['itemnumber'] ?? 0);
    $delete = !empty($image['delete']);

    if ($localId === '' || $itemnumber <= 0) {
        $imageErrors[] = ['localId' => $localId, 'error' => 'Missing image or item reference'];
        continue;
    }

    $item = mobile_item_context($itemnumber);
    if (!$item) {
        $imageErrors[] = ['localId' => $localId, 'error' => 'Item not found'];
        continue;
    }

    $clientnumber = (int)($item['clientnumber'] ?? 0);
    $accessError = mobile_assert_item_access($surveyor, $clientnumber, $itemnumber);
    if ($accessError !== '') {
        $imageErrors[] = ['localId' => $localId, 'error' => $accessError];
        continue;
    }

    if ($delete) {
        $removed = mobile_remove_report_image($image, $itemnumber);
        if (!$removed['ok']) {
            $imageErrors[] = ['localId' => $localId, 'error' => $removed['error']];
            continue;
        }
        $imageResults[] = ['localId' => $localId, 'itemnumber' => $itemnumber, 'action' => 'delete'];
        continue;
    }

    $saved = mobile_save_report_image($image, $itemnumber);
    if (!$saved['ok']) {
        $imageErrors[] = ['localId' => $localId, 'error' => $saved['error']];
        continue;
    }
    $imageResults[] = [
        'localId' => $localId,
        'itemnumber' => $itemnumber,
        'filename' => $saved['filename'],
        'action' => 'upload',
    ];
}

$mobileUploadFinished = true;
mobile_json([
    'ok' => empty($errors) && empty($itemErrors) && empty($imageErrors),
    'items' => $itemResults,
    'uploaded' => $results,
    'images' => $imageResults,
    'item_errors' => $itemErrors,
    'image_errors' => $imageErrors,
    'errors' => $errors,
], (empty($errors) && empty($itemErrors) && empty($imageErrors)) ? 200 : 207);

function mobile_report_images_dir(): string
{
    $base = defined('TENANT_DEFER') ? rtrim((string)TENANT_DEFER, '/\\') : dirname(__DIR__, 2);
    $dir = $base . '/images/report_images';
    if (!is_dir($dir)) {
        mkdir($dir, 0775, true);
    }
    return $dir;
}

function mobile_clean_image_description(string $description): string
{
    $description = trim($description) !== '' ? trim($description) : 'Image';
    $description = preg_replace('/[^A-Za-z0-9 _-]/', '', $description);
    $description = preg_replace('/\s+/', '_', (string)$description);
    return substr((string)$description, 0, 80) ?: 'Image';
}

function mobile_save_report_image(array $image, int $itemnumber): array
{
    $raw = base64_decode((string)($image['image'] ?? ''), true);
    if ($raw === false || $raw === '') {
        return ['ok' => false, 'error' => 'Image data missing'];
    }

    $src = imagecreatefromstring($raw);
    if (!$src) {
        return ['ok' => false, 'error' => 'Image data is not a valid image'];
    }

    $rotation = ((int)($image['rotation'] ?? 0)) % 360;
    if ($rotation !== 0) {
        $src = imagerotate($src, 360 - $rotation, 0);
    }

    $desc = mobile_clean_image_description((string)($image['description'] ?? 'Image'));
    $position = mobile_report_image_position($image, $itemnumber);
    $filename = $itemnumber . '_' . $position . '__' . $desc . '.jpg';
    $dir = mobile_report_images_dir();
    mobile_write_resized_jpeg($src, $dir . '/' . $filename, 1024, 1024);
    mobile_write_resized_jpeg($src, $dir . '/' . $itemnumber . '_' . $position . '__' . $desc . '_thumb.jpg', 350, 350);
    imagedestroy($src);
    return ['ok' => true, 'filename' => $filename];
}

function mobile_report_image_position(array $image, int $itemnumber): int
{
    $filename = basename((string)($image['filename'] ?? ''));
    if (preg_match('/^' . preg_quote((string)$itemnumber, '/') . '_(\d+)__[^\/\\\\]+\.jpe?g$/i', $filename, $matches)) {
        $position = (int)$matches[1];
        if ($position >= 1 && $position <= 6) {
            return $position;
        }
    }

    $used = [];
    $dir = mobile_report_images_dir();
    foreach (glob($dir . '/' . $itemnumber . '_*__*.jpg') ?: [] as $path) {
        $base = basename((string)$path);
        if (preg_match('/^' . preg_quote((string)$itemnumber, '/') . '_(\d+)__.*(?<!_thumb)\.jpe?g$/i', $base, $matches)) {
            $used[(int)$matches[1]] = true;
        }
    }

    for ($position = 1; $position <= 6; $position++) {
        if (empty($used[$position])) {
            return $position;
        }
    }

    return 6;
}

function mobile_write_resized_jpeg($src, string $path, int $maxW, int $maxH): void
{
    $width = imagesx($src);
    $height = imagesy($src);
    $ratio = min($maxW / max(1, $width), $maxH / max(1, $height), 1);
    $targetW = max(1, (int)floor($width * $ratio));
    $targetH = max(1, (int)floor($height * $ratio));
    $dst = imagecreatetruecolor($targetW, $targetH);
    imagecopyresampled($dst, $src, 0, 0, 0, 0, $targetW, $targetH, $width, $height);
    imagejpeg($dst, $path, 90);
    imagedestroy($dst);
}

function mobile_remove_report_image(array $image, int $itemnumber): array
{
    $filename = basename((string)($image['filename'] ?? ''));
    if ($filename === '') {
        $desc = mobile_clean_image_description((string)($image['description'] ?? 'Image'));
        $filename = $itemnumber . '_1__' . $desc . '.jpg';
    }

    $newFormat = '/^' . preg_quote((string)$itemnumber, '/') . '_\d+__[^\/\\\\]+\.jpe?g$/i';
    $legacyFormat = '/^_' . preg_quote((string)$itemnumber, '/') . '__[^\/\\\\]+\.jpe?g$/i';
    if (!preg_match($newFormat, $filename) && !preg_match($legacyFormat, $filename)) {
        return ['ok' => false, 'error' => 'Invalid image filename'];
    }

    $dir = mobile_report_images_dir();
    $main = $dir . '/' . $filename;
    $thumb = preg_replace('/\.jpe?g$/i', '_thumb.jpg', $main);
    if (is_file($main)) {
        unlink($main);
    }
    if ($thumb && is_file($thumb)) {
        unlink($thumb);
    }
    return ['ok' => true];
}

function mobile_run_report_save(array $saveRequest): string
{
    $previousRequest = $_REQUEST;
    $previousPost = $_POST;
    $previousObLevel = ob_get_level();
    $_REQUEST = $saveRequest;
    $_POST = $saveRequest;

    ob_start();
    try {
        include dirname(__DIR__, 2) . '/includes/master/form_functions.php';
        $saveOutput = trim((string)ob_get_clean());
        return $saveOutput;
    } finally {
        while (ob_get_level() > $previousObLevel) {
            ob_end_clean();
        }
        $_REQUEST = $previousRequest;
        $_POST = $previousPost;
    }
}

function mobile_assert_client_location_access(array $surveyor, int $clientnumber, int $locnumber): string
{
    $access = (int)($surveyor['access'] ?? 0);
    $surveyorId = (int)($surveyor['id'] ?? 0);

    if ($access === 2) {
        if ($locnumber <= 0) {
            $stmt = $GLOBALS['con']->prepare("SELECT `clientnumber` FROM `clientdetails` WHERE `clientnumber`=? LIMIT 1");
            if (!$stmt) {
                return 'Client access unavailable';
            }
            $stmt->bind_param('i', $clientnumber);
        } else {
            $stmt = $GLOBALS['con']->prepare("SELECT `locnumber` FROM `locations` WHERE `clientnumber`=? AND `locnumber`=? LIMIT 1");
            if (!$stmt) {
                return 'Location access unavailable';
            }
            $stmt->bind_param('ii', $clientnumber, $locnumber);
        }
    } else {
        $stmt = $GLOBALS['con']->prepare("
            SELECT 1
            FROM `surveyor_assignments` sa
            WHERE sa.`surveyor` = ?
              AND sa.`client_id` = ?
              AND sa.`status` = 1
              AND (
                    sa.`asset_id` IS NULL OR sa.`asset_id` = '' OR sa.`asset_id` = 0
                  )
              AND (
                    ? <= 0
                    OR sa.`site_id` IS NULL OR sa.`site_id` = '' OR sa.`site_id` = 0
                    OR sa.`site_id` = ?
                  )
            LIMIT 1
        ");
        if (!$stmt) {
            return 'Client access unavailable';
        }
        $stmt->bind_param('iiii', $surveyorId, $clientnumber, $locnumber, $locnumber);
    }

    $stmt->execute();
    $result = $stmt->get_result();
    $stmt->close();

    return mysqli_num_rows($result) > 0 ? '' : 'Surveyor is not assigned to create items for this client/site';
}

function mobile_create_item(array $payload, int $clientnumber, int $locnumber): array
{
    if ($locnumber <= 0) {
        $locnumber = mobile_first_client_location($clientnumber);
    }

    $payload['locnumber'] = $locnumber;
    $existing = mobile_find_existing_item_for_payload($payload, $clientnumber, $locnumber);
    if ($existing) {
        return [
            'ok' => true,
            'itemnumber' => (int)$existing['itemnumber'],
            'locnumber' => (int)$existing['locnumber'],
        ];
    }

    $previousRequest = $_REQUEST;
    $_REQUEST['FUNCTION'] = '';
    if (session_status() === PHP_SESSION_NONE) {
        session_start();
    }
    $_SESSION['usertype'] = $_SESSION['usertype'] ?? 'surveyors';
    $_SESSION['access'] = max(1, (int)($_SESSION['access'] ?? 1));
    $_SESSION['contractorNumber'] = $_SESSION['contractorNumber'] ?? 0;

    require_once dirname(__DIR__, 2) . '/includes/asset/asset_functions.php';
    $_REQUEST = $previousRequest;

    if (!function_exists('assetMobileInsert')) {
        return ['ok' => false, 'error' => 'Asset insert handler unavailable'];
    }

    $created = assetMobileInsert($clientnumber, $payload);
    if (($created['status'] ?? '') !== 'ok') {
        return ['ok' => false, 'error' => (string)($created['message'] ?? 'Item insert failed')];
    }

    return [
        'ok' => true,
        'itemnumber' => (int)($created['itemnumber'] ?? 0),
        'locnumber' => (int)($created['locnumber'] ?? $locnumber),
    ];
}

function mobile_find_existing_item_for_payload(array $payload, int $clientnumber, int $locnumber): ?array
{
    if ($clientnumber <= 0 || $locnumber <= 0) {
        return null;
    }

    $plantnumber = trim((string)($payload['plantnumber'] ?? ''));
    $serialnumber = trim((string)($payload['serialnumber'] ?? ''));
    $blankMarkers = ['', 'not marked', 'n/a', 'na', '-'];
    $hasPlant = !in_array(strtolower($plantnumber), $blankMarkers, true);
    $hasSerial = !in_array(strtolower($serialnumber), $blankMarkers, true);
    if (!$hasPlant || !$hasSerial) {
        return null;
    }

    $stmt = $GLOBALS['con']->prepare("
        SELECT `itemnumber`, `locnumber`
        FROM `itemdetails`
        WHERE `clientnumber`=?
          AND `locnumber`=?
          AND `statuslive`=1
          AND TRIM(LOWER(`plantnumber`))=TRIM(LOWER(?))
          AND TRIM(LOWER(`serialnumber`))=TRIM(LOWER(?))
        ORDER BY `itemnumber` DESC
        LIMIT 1
    ");
    if (!$stmt) {
        return null;
    }
    $stmt->bind_param('iiss', $clientnumber, $locnumber, $plantnumber, $serialnumber);
    $stmt->execute();
    $result = $stmt->get_result();
    $stmt->close();
    $row = mysqli_fetch_assoc($result);
    return is_array($row) ? $row : null;
}

function mobile_first_client_location(int $clientnumber): int
{
    $stmt = $GLOBALS['con']->prepare("SELECT `locnumber` FROM `locations` WHERE `clientnumber`=? AND `statuslive`=1 ORDER BY `locnumber` ASC LIMIT 1");
    if (!$stmt) {
        return 0;
    }
    $stmt->bind_param('i', $clientnumber);
    $stmt->execute();
    $result = $stmt->get_result();
    $stmt->close();
    $row = mysqli_fetch_assoc($result);
    return (int)($row['locnumber'] ?? 0);
}

function mobile_assert_item_access(array $surveyor, int $clientnumber, int $itemnumber): string
{
    $access = (int)($surveyor['access'] ?? 0);
    $surveyorId = (int)($surveyor['id'] ?? 0);

    if ($access === 2) {
        $stmt = $GLOBALS['con']->prepare("SELECT `itemnumber` FROM `itemdetails` WHERE `itemnumber`=? AND `clientnumber`=? AND `statuslive`=1 LIMIT 1");
        if (!$stmt) {
            return 'Item access unavailable';
        }
        $stmt->bind_param('ii', $itemnumber, $clientnumber);
    } else {
        $stmt = $GLOBALS['con']->prepare("
            SELECT i.`itemnumber`
            FROM `surveyor_assignments` sa
            INNER JOIN `itemdetails` i
                ON i.`statuslive` = 1
               AND i.`clientnumber` = sa.`client_id`
               AND i.`itemnumber` = ?
               AND (
                    (sa.`asset_id` IS NOT NULL AND sa.`asset_id` <> '' AND sa.`asset_id` <> 0 AND i.`itemnumber` = sa.`asset_id`)
                    OR (
                        (sa.`asset_id` IS NULL OR sa.`asset_id` = '' OR sa.`asset_id` = 0)
                        AND (
                            (sa.`site_id` IS NULL OR sa.`site_id` = '' OR sa.`site_id` = 0)
                            OR i.`locnumber` = sa.`site_id`
                        )
                    )
               )
            WHERE sa.`surveyor` = ?
              AND sa.`client_id` = ?
              AND sa.`status` = 1
            LIMIT 1
        ");
        if (!$stmt) {
            return 'Item access unavailable';
        }
        $stmt->bind_param('iii', $itemnumber, $surveyorId, $clientnumber);
    }

    $stmt->execute();
    $result = $stmt->get_result();
    $stmt->close();

    return mysqli_num_rows($result) > 0 ? '' : 'Surveyor is not assigned to this item';
}

function mobile_item_context(int $itemnumber): ?array
{
    $stmt = $GLOBALS['con']->prepare("SELECT `itemnumber`, `clientnumber`, `locnumber`, `lastReport`, `currdate`, `duedate`, `history` FROM `itemdetails` WHERE `itemnumber`=? LIMIT 1");
    if (!$stmt) {
        return null;
    }
    $stmt->bind_param('i', $itemnumber);
    $stmt->execute();
    $result = $stmt->get_result();
    $stmt->close();
    $row = mysqli_fetch_assoc($result);
    return is_array($row) ? $row : null;
}

function mobile_report_exists(int $repnumber, int $itemnumber, int $clientnumber): bool
{
    if ($repnumber <= 0 || $itemnumber <= 0 || $clientnumber <= 0) {
        return false;
    }

    $stmt = $GLOBALS['con']->prepare("
        SELECT `repnumber`
        FROM `reportitems`
        WHERE `repnumber`=?
          AND `itemnumber`=?
          AND `clientnumber`=?
        LIMIT 1
    ");
    if (!$stmt) {
        return false;
    }
    $stmt->bind_param('iii', $repnumber, $itemnumber, $clientnumber);
    $stmt->execute();
    $result = $stmt->get_result();
    $stmt->close();

    return $result && mysqli_num_rows($result) > 0;
}

function mobile_build_report_request(string $tenant, array $surveyor, array $report, array $answers, array $item, int $clientnumber, int $itemnumber, int $locnumber, int $reptype): array
{
    $createdAt = (string)($report['createdAt'] ?? '');
    $inspectionDate = substr($createdAt, 0, 10);
    if ($inspectionDate === '' || strtotime($inspectionDate) === false) {
        $inspectionDate = date('Y-m-d');
    }

    $nextDate = (string)($report['nextExamDate'] ?? '');
    if ($nextDate === '' || strtotime($nextDate) === false) {
        $nextDate = date('Y-m-d', strtotime('+6 months'));
    }

    $result = strtoupper(trim((string)($report['result'] ?? 'PASS')));
    if ($result === 'DEFECT') {
        $result = 'DEFECTS';
    }

    $request = [
        'tenant' => $tenant,
        'FUNCTION' => (int)($report['repnumber'] ?? 0) > 0 ? 'update' : 'create',
        'repnumber' => (string)((int)($report['repnumber'] ?? 0)),
        'clientnumber' => (string)$clientnumber,
        'itemnumber' => (string)$itemnumber,
        'locnumber' => (string)$locnumber,
        'reptype' => (string)$reptype,
        'surveyor' => (string)($surveyor['id'] ?? ''),
        'oldnumber' => '',
        'olddate' => !empty($item['currdate']) ? date('Y-m-d', (int)$item['currdate']) : 'Not Known',
        'insdate' => $inspectionDate,
        'nextDate' => $nextDate,
        'history' => (string)($item['history'] ?? ''),
        'result' => $result,
        'imageMode' => '0',
        'tagMode' => '0',
        'pageMode' => '1',
        'formClass' => '',
    ];

    foreach (mobile_report_default_fields() as $field) {
        if (!isset($request[$field])) {
            $request[$field] = '';
        }
    }

    foreach ($answers as $field => $value) {
        if (is_scalar($value) || $value === null) {
            $request[(string)$field] = (string)$value;
        } else {
            $request[(string)$field] = json_encode($value, JSON_UNESCAPED_SLASHES);
        }
    }

    return $request;
}

function mobile_report_default_fields(): array
{
    return [
        'adefect', 'bdefect', 'obs', 'pnareason', 'partialReason', 'ffcomments', 'code', 'viewed',
        'changeScheme', 'resultOfExam', 'lastReportSeen', 'examType', 'partsCovered', 'lease_or_hire',
        'partsInaccessible', 'conditionInternal', 'conditionExternal', 'conditionFittings',
        'protectiveDevices', '9b1', '9b2', '9b3', 'processConditions', 'class', 'ebond', 'ires',
        'volts', 'nature', 'test_procedure', 'process_conditions', 'effective', 'particulars',
        'other_comments', 'usage_comments', 'noise', 'intended_performance', 'achieving_perfomance',
        'repair_details', 'rack', 'rackRun', 'beam', 'accessories', 'handling', 'stability', 'clutch',
        'safety', 'frequency', 'protectiveDevicesNarrative', 'parts_1', 'parts_2', 'parts_3',
        'parts_2_alt', 'parts_3_alt', 'safety_1', 'safety_2', 'safety_3', 'safety_4', 'safety_5',
        'safety_6', 'safety_7', 'safety_8', 'safety_9', 'safety_10', 'safety_11', 'safety_12',
        'safety_13', 'repair_1', 'repair_2',
    ];
}

function mobile_generate_report_pdf(string $tenant, int $clientnumber, int $itemnumber, int $repnumber, int $reptype): string
{
    $previousRequest = $_REQUEST;
    $previousPost = $_POST;
    $cwd = getcwd();
    $previousObLevel = ob_get_level();

    $_REQUEST = [
        'orientation' => '1',
        'imageMode' => '0',
        'tagMode' => '0',
        'clientnumber' => (string)$clientnumber,
        'repnumber' => (string)$repnumber,
        'items' => (string)$itemnumber,
        'form' => (string)$reptype,
        'tenant' => $tenant,
    ];
    $_POST = $_REQUEST;

    ob_start();
    try {
        chdir(dirname(__DIR__) . '/generators');
        include dirname(__DIR__) . '/generators/genPDF2.php';
        return trim((string)ob_get_clean());
    } finally {
        while (ob_get_level() > $previousObLevel) {
            ob_end_clean();
        }
        if ($cwd !== false) {
            chdir($cwd);
        }
        $_REQUEST = $previousRequest;
        $_POST = $previousPost;
    }
}
