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

$input = mobile_input();
mobile_boot_tenant($input);
$surveyor = mobile_authorise();
$surveyorId = (int)$surveyor['id'];
$clientsOnly = !empty($input['clients_only']);
$includeImages = !$clientsOnly && !empty($input['include_images']);
$knownMedia = isset($input['known_media']) && is_array($input['known_media']) ? $input['known_media'] : [];
$requestedClientNumbers = [];
if (isset($input['clientnumbers']) && is_array($input['clientnumbers'])) {
    foreach ($input['clientnumbers'] as $clientnumber) {
        if (filter_var($clientnumber, FILTER_VALIDATE_INT) !== false) {
            $requestedClientNumbers[] = (int)$clientnumber;
        }
    }
    $requestedClientNumbers = array_values(array_unique(array_filter($requestedClientNumbers)));
}

if (!$clientsOnly && empty($requestedClientNumbers)) {
    mobile_json(['ok' => false, 'error' => 'Select at least one client'], 400);
}

$clientFilterSql = '';
if (!empty($requestedClientNumbers)) {
    $clientFilterSql = ' AND c.`clientnumber` IN (' . implode(',', $requestedClientNumbers) . ')';
}
$itemClientFilterSql = '';
if (!empty($requestedClientNumbers)) {
    $itemClientFilterSql = ' AND i.`clientnumber` IN (' . implode(',', $requestedClientNumbers) . ')';
}
$locationClientFilterSql = '';
if (!empty($requestedClientNumbers)) {
    $locationClientFilterSql = ' AND l.`clientnumber` IN (' . implode(',', $requestedClientNumbers) . ')';
}

$clients = [];
$locations = [];
$items = [];
$reportImages = [];
$assetTags = [];
$plantTypes = [];
$access = (int)($surveyor['access'] ?? 0);
$syncDayStart = strtotime('today midnight');
$dueWindowEnd = strtotime('+30 days', $syncDayStart) + 86399;
$dueFilterSql = " AND (i.`duedate` IS NULL OR i.`duedate` = '' OR i.`duedate` = 0 OR i.`duedate` <= " . (int)$dueWindowEnd . ") ";

$plantSql = "SELECT `code`, `description`, `frequency` FROM `dd_plant` ORDER BY `description` ASC, `code` ASC";
if ($plantResult = mysqli_query($GLOBALS['con'], $plantSql)) {
    while ($row = mysqli_fetch_assoc($plantResult)) {
        $description = trim((string)($row['description'] ?? ''));
        if ($description === '') {
            continue;
        }
        $plantTypes[] = [
            'code' => (string)($row['code'] ?? ''),
            'description' => $description,
            'frequency' => (int)($row['frequency'] ?? 0),
        ];
    }
}

$clientSql = $access === 2
    ? "SELECT DISTINCT c.`clientnumber` AS client_id, c.`clientname`, c.`address1`, c.`address2`, c.`town`, c.`county`, c.`postcode`,
            c.`phone1`, c.`mobile`, c.`email`, c.`pri_contact_name`, c.`pri_contact_email`, c.`pri_contact_tel`, c.`pri_contact_mob`
       FROM `clientdetails` c
       INNER JOIN `itemdetails` i ON i.`clientnumber` = c.`clientnumber` AND i.`statuslive` = 1
       WHERE 1=1 $clientFilterSql
       ORDER BY c.`clientname` ASC"
    : "SELECT DISTINCT c.`clientnumber` AS client_id, c.`clientname`, c.`address1`, c.`address2`, c.`town`, c.`county`, c.`postcode`,
            c.`phone1`, c.`mobile`, c.`email`, c.`pri_contact_name`, c.`pri_contact_email`, c.`pri_contact_tel`, c.`pri_contact_mob`
       FROM `surveyor_assignments` sa
       INNER JOIN `clientdetails` c ON c.`clientnumber` = sa.`client_id`
       WHERE sa.`surveyor` = ?
         AND sa.`status` = 1
         $clientFilterSql
       ORDER BY c.`clientname` ASC";

$stmt = $GLOBALS['con']->prepare($clientSql);
if (!$stmt) {
    mobile_json(['ok' => false, 'error' => 'Assignments unavailable'], 500);
}
if ($access !== 2) {
    $stmt->bind_param('i', $surveyorId);
}
$stmt->execute();
$result = $stmt->get_result();
$stmt->close();
while ($row = mysqli_fetch_assoc($result)) {
    $clients[(int)$row['client_id']] = [
        'clientnumber' => (int)$row['client_id'],
        'clientname' => (string)$row['clientname'],
        'address1' => (string)($row['address1'] ?? ''),
        'address2' => (string)($row['address2'] ?? ''),
        'town' => (string)($row['town'] ?? ''),
        'county' => (string)($row['county'] ?? ''),
        'postcode' => (string)($row['postcode'] ?? ''),
        'phone1' => (string)($row['phone1'] ?? ''),
        'mobile' => (string)($row['mobile'] ?? ''),
        'email' => (string)($row['email'] ?? ''),
        'primary_contact_name' => (string)($row['pri_contact_name'] ?? ''),
        'primary_contact_email' => (string)($row['pri_contact_email'] ?? ''),
        'primary_contact_phone' => (string)(($row['pri_contact_tel'] ?? '') ?: ($row['pri_contact_mob'] ?? '')),
        'due_count' => 0,
    ];
}

$dueCountSql = $access === 2
    ? "SELECT i.`clientnumber`, COUNT(DISTINCT i.`itemnumber`) AS due_count
       FROM `itemdetails` i
       WHERE i.`statuslive` = 1
       $itemClientFilterSql
       $dueFilterSql
       GROUP BY i.`clientnumber`"
    : "SELECT i.`clientnumber`, COUNT(DISTINCT i.`itemnumber`) AS due_count
       FROM `surveyor_assignments` sa
       INNER JOIN `itemdetails` i
           ON i.`statuslive` = 1
          AND i.`clientnumber` = sa.`client_id`
          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.`status` = 1
         $itemClientFilterSql
         $dueFilterSql
       GROUP BY i.`clientnumber`";

$stmt = $GLOBALS['con']->prepare($dueCountSql);
if ($stmt) {
    if ($access !== 2) {
        $stmt->bind_param('i', $surveyorId);
    }
    $stmt->execute();
    $result = $stmt->get_result();
    $stmt->close();
    while ($row = mysqli_fetch_assoc($result)) {
        $clientnumber = (int)($row['clientnumber'] ?? 0);
        if (isset($clients[$clientnumber])) {
            $clients[$clientnumber]['due_count'] = (int)($row['due_count'] ?? 0);
        }
    }
}

$availableClientNumbers = array_keys($clients);
if (!empty($availableClientNumbers)) {
    $locationClientFilterSql = ' AND l.`clientnumber` IN (' . implode(',', array_map('intval', $availableClientNumbers)) . ')';
}

$locationSql = "SELECT DISTINCT
        l.`locnumber`, l.`clientnumber`, l.`locname`, l.`postcode`,
        l.`locaddress1`, l.`locaddress2`, l.`locaddress3`, l.`locaddress4`,
        '' AS `primary_contact_name`,
        '' AS `primary_contact_email`,
        '' AS `primary_contact_phone`,
        '' AS `location_notes`
   FROM `locations` l
   WHERE 1=1
   $locationClientFilterSql
   ORDER BY l.`clientnumber`, l.`locname` ASC";

$stmt = $GLOBALS['con']->prepare($locationSql);
if (!$stmt) {
    mobile_json(['ok' => false, 'error' => 'Locations unavailable'], 500);
}
$stmt->execute();
$result = $stmt->get_result();
$stmt->close();
while ($row = mysqli_fetch_assoc($result)) {
    $locations[(int)$row['locnumber']] = [
        'locnumber' => (int)$row['locnumber'],
        'clientnumber' => (int)$row['clientnumber'],
        'locname' => (string)$row['locname'],
        'postcode' => (string)$row['postcode'],
        'address' => array_values(array_filter([
            (string)$row['locaddress1'],
            (string)$row['locaddress2'],
            (string)$row['locaddress3'],
            (string)$row['locaddress4'],
        ])),
        'primary_contact_name' => (string)($row['primary_contact_name'] ?? ''),
        'primary_contact_email' => (string)($row['primary_contact_email'] ?? ''),
        'primary_contact_phone' => (string)($row['primary_contact_phone'] ?? ''),
        'notes' => (string)($row['location_notes'] ?? ''),
    ];
}

if ($clientsOnly) {
    mobile_json([
        'ok' => true,
        'generated_at' => time(),
        'surveyor' => [
            'id' => $surveyorId,
            'name' => trim((string)($surveyor['forename'] ?? '') . ' ' . (string)($surveyor['surname'] ?? '')),
            'email' => (string)$surveyor['email'],
            'access' => $access,
            'mode' => $access === 2 ? 'elevated' : 'assigned',
        ],
        'clients' => array_values($clients),
        'locations' => array_values($locations),
        'items' => [],
        'report_images' => [],
        'asset_tags' => [],
        'planttypes' => $plantTypes,
        'formtypes' => mobile_formtypes(),
    ]);
}

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

$itemSelect = "
    SELECT DISTINCT
        i.`itemnumber`, i.`clientnumber`, i.`locnumber`, i.`subloc`, i.`desc`, i.`code`, i.`reptype`,
        i.`plantnumber`, i.`serialnumber`, i.`manf`, i.`model`, i.`dateofmanf`, i.`swl`,
        i.`duedate`, i.`lastReport`, i.`linked`, i.`itemnotes`, i.`surveyor`, l.`locname`, l.`postcode`
";

$itemSql = $access === 2
    ? $itemSelect . "
       FROM `itemdetails` i
       LEFT JOIN `locations` l ON l.`locnumber` = i.`locnumber`
       WHERE i.`statuslive` = 1
       $itemClientFilterSql
       $dueFilterSql
       ORDER BY i.`clientnumber`, l.`locname`, i.`subloc`, i.`desc`"
    : $itemSelect . "
       FROM `surveyor_assignments` sa
       INNER JOIN `itemdetails` i
           ON i.`statuslive` = 1
          AND i.`clientnumber` = sa.`client_id`
          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`
                    )
                )
          )
       LEFT JOIN `locations` l ON l.`locnumber` = i.`locnumber`
       WHERE sa.`surveyor` = ?
         AND sa.`status` = 1
         $itemClientFilterSql
         $dueFilterSql
       ORDER BY i.`clientnumber`, l.`locname`, i.`subloc`, i.`desc`";

$stmt = $GLOBALS['con']->prepare($itemSql);
if (!$stmt) {
    mobile_json(['ok' => false, 'error' => 'Items unavailable'], 500);
}
if ($access !== 2) {
    $stmt->bind_param('i', $surveyorId);
}
$stmt->execute();
$result = $stmt->get_result();
$stmt->close();
while ($row = mysqli_fetch_assoc($result)) {
    $dueDate = (int)($row['duedate'] ?? 0);
    $items[(int)$row['itemnumber']] = [
        'itemnumber' => (int)$row['itemnumber'],
        'clientnumber' => (int)$row['clientnumber'],
        'locnumber' => (int)$row['locnumber'],
        'location_name' => (string)($row['locname'] ?? ''),
        'postcode' => (string)($row['postcode'] ?? ''),
        'subloc' => (string)$row['subloc'],
        'description' => (string)$row['desc'],
        'code' => (string)$row['code'],
        'plantnumber' => (string)$row['plantnumber'],
        'serialnumber' => (string)$row['serialnumber'],
        'manufacturer' => (string)$row['manf'],
        'model' => (string)$row['model'],
        'year' => (string)$row['dateofmanf'],
        'swl' => (string)$row['swl'],
        'duedate' => $dueDate,
        'due_status' => $dueDate <= 0 ? 'NDS' : ($dueDate < $syncDayStart ? 'OVERDUE' : 'DUE'),
        'last_result' => (string)($row['lastReport'] ?? ''),
        'report_set' => (int)($row['reptype'] ?? 0),
        'linked' => (string)$row['linked'],
        'itemnotes' => (string)$row['itemnotes'],
    ];
}

if (!empty($items)) {
    $itemNumbers = implode(',', array_map('intval', array_keys($items)));
    $historySql = "
        SELECT `repnumber`, `reptype`, `result`, `insdate`, `nextDate`, `itemnumber`, `reportdata`
        FROM `reportitems`
        WHERE `itemnumber` IN ($itemNumbers)
        ORDER BY `itemnumber` ASC, `insdate` DESC, `repitem` DESC
    ";
    $historyResult = mysqli_query($GLOBALS['con'], $historySql);
    $historyCounts = [];
    if ($historyResult) {
        while ($row = mysqli_fetch_assoc($historyResult)) {
            $itemnumber = (int)($row['itemnumber'] ?? 0);
            if ($itemnumber <= 0 || !isset($items[$itemnumber])) {
                continue;
            }
            $historyCounts[$itemnumber] = (int)($historyCounts[$itemnumber] ?? 0);
            if ($historyCounts[$itemnumber] >= 4) {
                continue;
            }
            $historyCounts[$itemnumber]++;
            if (!isset($items[$itemnumber]['report_history'])) {
                $items[$itemnumber]['report_history'] = [];
            }
            $rd = enrepReportDataFromRow($row);
            $items[$itemnumber]['report_history'][] = [
                'repnumber' => (int)($row['repnumber'] ?? 0),
                'formnumber' => (int)($row['reptype'] ?? 0),
                'result' => (string)($row['result'] ?? ''),
                'insdate' => (int)($row['insdate'] ?? 0),
                'nextDate' => (int)($row['nextDate'] ?? 0),
                'answers' => mobile_report_history_answers($rd),
            ];
        }
    }
}

if ($includeImages && !empty($items)) {
    foreach (array_keys($items) as $itemnumber) {
        foreach (mobile_download_report_images((int)$itemnumber, $knownMedia) as $image) {
            $reportImages[] = $image;
        }
        $tag = mobile_download_asset_tag((int)$itemnumber, $knownMedia);
        if ($tag !== null) {
            $assetTags[] = $tag;
        }
    }
}

mobile_json([
    'ok' => true,
    'generated_at' => time(),
    'sync_day_start' => $syncDayStart,
    'due_window_end' => $dueWindowEnd,
    'surveyor' => [
        'id' => $surveyorId,
        'name' => trim((string)($surveyor['forename'] ?? '') . ' ' . (string)($surveyor['surname'] ?? '')),
        'email' => (string)$surveyor['email'],
        'access' => $access,
        'mode' => $access === 2 ? 'elevated' : 'assigned',
    ],
    'clients' => array_values($clients),
    'locations' => array_values($locations),
    'items' => array_values($items),
    'report_images' => $reportImages,
    'asset_tags' => $assetTags,
    'planttypes' => $plantTypes,
    'formtypes' => mobile_formtypes(),
]);

function mobile_report_history_answers(array $reportData): array
{
    $answers = [];
    foreach ($reportData as $key => $value) {
        $field = (string)$key;
        if ($field === '') {
            continue;
        }
        if ($value === null || is_scalar($value)) {
            $answers[$field] = (string)$value;
            continue;
        }
        if (is_array($value)) {
            $encoded = json_encode($value, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
            $answers[$field] = $encoded === false ? '' : $encoded;
        }
    }

    if (isset($reportData['pressure']) && is_array($reportData['pressure'])) {
        foreach ($reportData['pressure'] as $key => $value) {
            if ($key === '' || (!is_scalar($value) && $value !== null)) {
                continue;
            }
            $answers['pressure[' . (string)$key . ']'] = (string)$value;
        }
    }
    foreach (['lease_or_hire', 'scheme_number_alt'] as $pressureKey) {
        if (array_key_exists($pressureKey, $reportData) && !array_key_exists('pressure[' . $pressureKey . ']', $answers)) {
            $answers['pressure[' . $pressureKey . ']'] = (string)$reportData[$pressureKey];
        }
    }
    if (!empty($answers['protectiveDevices']) && strpos($answers['protectiveDevices'], '|') !== false) {
        $parts = explode('|', $answers['protectiveDevices'], 2);
        $answers['protectiveDevices'] = $parts[0] ?? '';
        if (!array_key_exists('protectiveDevicesNarrative', $answers)) {
            $answers['protectiveDevicesNarrative'] = $parts[1] ?? '';
        }
    }
    return $answers;
}

function mobile_download_tenant_dir(string $relative): string
{
    $base = defined('TENANT_DEFER') ? rtrim((string)TENANT_DEFER, '/\\') : dirname(__DIR__, 2);
    return $base . '/' . trim($relative, '/\\');
}

function mobile_download_known_updated(array $knownMedia, string $type, string $filename): int
{
    $rows = isset($knownMedia[$type]) && is_array($knownMedia[$type]) ? $knownMedia[$type] : [];
    return (int)($rows[$filename] ?? 0);
}

function mobile_download_file_payload(string $path, string $filename, string $type, array $knownMedia): ?array
{
    if (!is_file($path)) {
        return null;
    }
    $updatedAt = (int)filemtime($path);
    if (mobile_download_known_updated($knownMedia, $type, $filename) >= $updatedAt) {
        return null;
    }
    return [
        'filename' => $filename,
        'updated_at' => $updatedAt,
        'image' => base64_encode((string)file_get_contents($path)),
    ];
}

function mobile_download_report_images(int $itemnumber, array $knownMedia): array
{
    $dir = mobile_download_tenant_dir('images/report_images');
    $images = [];
    foreach (glob($dir . '/' . $itemnumber . '_*__*.jpg') ?: [] as $path) {
        $filename = basename((string)$path);
        if (preg_match('/_thumb\.jpe?g$/i', $filename)) {
            continue;
        }
        if (!preg_match('/^' . preg_quote((string)$itemnumber, '/') . '_(\d+)__(.*?)\.jpe?g$/i', $filename, $matches)) {
            continue;
        }
        $thumbFilename = preg_replace('/\.jpe?g$/i', '_thumb.jpg', $filename);
        $thumbPath = $dir . '/' . $thumbFilename;
        $payload = mobile_download_file_payload(is_file($thumbPath) ? $thumbPath : $path, $thumbFilename, 'report_images', $knownMedia);
        if ($payload === null) {
            continue;
        }
        $images[] = $payload + [
            'itemnumber' => $itemnumber,
            'slot' => (int)$matches[1],
            'description' => str_replace('_', ' ', (string)$matches[2]),
            'main_filename' => $filename,
        ];
    }
    return $images;
}

function mobile_download_asset_tag(int $itemnumber, array $knownMedia): ?array
{
    $dir = mobile_download_tenant_dir('images/tags');
    $filename = $itemnumber . '_thumb.jpg';
    $path = $dir . '/' . $filename;
    if (!is_file($path)) {
        $filename = $itemnumber . '.jpg';
        $path = $dir . '/' . $filename;
    }
    $payload = mobile_download_file_payload($path, $filename, 'asset_tags', $knownMedia);
    if ($payload === null) {
        return null;
    }
    return $payload + [
        'itemnumber' => $itemnumber,
        'main_filename' => $itemnumber . '.jpg',
    ];
}
