<?php 
require_once __DIR__ . '/../../functions/security.php';
require_once __DIR__ . '/../../functions/logging.php';
require_once __DIR__ . '/../../functions/itemdetails_json.php';

$tenant = enrep_tenant_segment();
if ($tenant !== '' && file_exists('../../../' . $tenant . '/config.php')) {
    require_once('../../../' . $tenant . '/config.php');
}
if (file_exists('/config.php')) {
    require_once('/config.php');
}
require_once __DIR__ . '/../plant_changes/plant_change_helpers.php';

if (!isset($GLOBALS['con']) || !($GLOBALS['con'] instanceof mysqli)) {
    enrep_fail(400, 'Tenant config not found');
}

enrep_require_user();

$FUNCTION = enrep_request_string('FUNCTION', '', 80);
enrep_log_request_completion('assets', 'FUNCTION', [
    'assetUploadCSV' => ['action' => 'csv_uploaded', 'message' => 'Uploaded asset CSV import file', 'entity_type' => 'itemdetails'],
    'assetCommitImport' => ['action' => 'csv_imported', 'message' => 'Committed asset CSV import', 'entity_type' => 'itemdetails'],
    'insert' => ['action' => 'created', 'message' => 'Created asset', 'entity_type' => 'itemdetails'],
    'update' => ['action' => 'updated', 'message' => 'Updated asset', 'entity_type' => 'itemdetails'],
]);

function assetAttachWrittenScheme(int $wsnumber, int $itemnumber): bool
{
    if ($wsnumber <= 0 || $itemnumber <= 0 || empty($GLOBALS['con']) || !($GLOBALS['con'] instanceof mysqli)) {
        return false;
    }

    $stmt = $GLOBALS['con']->prepare("DELETE FROM `wsitems` WHERE `itemnumber`=? AND `wsnumber`<>?") or die(mysqli_error($GLOBALS['con']));
    $stmt->bind_param('ii', $itemnumber, $wsnumber);
    $stmt->execute();
    $stmt->close();

    $stmt = $GLOBALS['con']->prepare("SELECT `id` FROM `wsitems` WHERE `wsnumber`=? AND `itemnumber`=? LIMIT 1") or die(mysqli_error($GLOBALS['con']));
    $stmt->bind_param('ii', $wsnumber, $itemnumber);
    $stmt->execute();
    $existing = $stmt->get_result();
    $stmt->close();
    if ($existing && mysqli_fetch_array($existing)) {
        return true;
    }

    $created = time();
    $type = 1;
    $desc = '';
    $swl = '';
    $stmt = $GLOBALS['con']->prepare("INSERT INTO `wsitems` (`wsnumber`,`itemnumber`,`date`,`type`,`desc`,`swl`) VALUES(?,?,?,?,?,?)") or die(mysqli_error($GLOBALS['con']));
    $stmt->bind_param('iiiiss', $wsnumber, $itemnumber, $created, $type, $desc, $swl);
    $ok = $stmt->execute();
    $stmt->close();

    return $ok;
}

switch ($FUNCTION) {
    default:
        break;
    case 'assetUploadCSV':
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode(
            assetUploadCSV((int)($_REQUEST['clientnumber'] ?? 0)),
            JSON_UNESCAPED_UNICODE
        );
        exit;

    case 'assetCommitImport':
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode(
            assetCommitImport(
                enrep_request_int('clientnumber'),
                enrep_request_string('rows', '', 1000000)
            ),
            JSON_UNESCAPED_UNICODE
        );
        exit;

    case 'assetDownloadTemplate':
        header_remove('Content-Type');
        header('Content-Type: text/csv; charset=utf-8');
        header('Content-Disposition: attachment; filename="asset_import_template.csv"');

        $out = fopen('php://output', 'w');

        fputcsv($out, [
            'Description',
            'Safe working load',
            'Plant Number',
            'Serial Number',
            'Model',
            'Date of manufacture',
            'Manufacturer',
            'Due Date',
            'Frequency',
            'Last Date',
            'Sub Location'
        ]);

        fputcsv($out, [
            '4 Leg Chain Sling',
            '3.1t',
            '4194',
            'RSS020037/A6',
            'CM4',
            '2016',
            'Crosby',
            '15-10-2025',
            '12',
            '05-06-2025',
            'Main Workshop'
        ]);

        fclose($out);
        exit;
    case "insert":
        enrep_itemdetails_apply_nested_formdata($_REQUEST);
        $_REQUEST['statuslive'] = in_array(strtolower((string)($_REQUEST['statuslive'] ?? '')), ['on', '1', 'true', 'yes'], true) ? "1" : "0";
        foreach (['agent'] as $assetOptionalField) {
            $_REQUEST[$assetOptionalField] = $_REQUEST[$assetOptionalField] ?? '';
        }
        if ($_REQUEST['agent'] == "") {
            $_REQUEST['agent'] = "0";
        }

        $itemdetailsJson = enrep_itemdetails_json_from_request($_REQUEST);
        $multi_flag = (($_POST['multi_flag'] ?? '') === '') ? null : (int)$_POST['multi_flag'];
        $cont_freq  = (($_POST['cont_freq']  ?? '') === '') ? null : $_POST['cont_freq'];
        $currdateTs = (isset($_REQUEST['currdate']) && $_REQUEST['currdate'] !== '') ? strtotime($_REQUEST['currdate']) : null;
        $duedateTs = (isset($_REQUEST['duedate']) && $_REQUEST['duedate'] !== '') ? strtotime($_REQUEST['duedate']) : null;
        $assetCondition = $_REQUEST['condition'] ?? '';
        $contractorNumber = $_SESSION['contractorNumber'] ?? 0;
        $createdTs = strtotime('now');
        $linkedValue = '';
        $archived = null;
        $nfc = null;

        $insertFields = [
            'locnumber',
            'clientnumber',
            'code',
            'desc',
            'swl',
            'plantnumber',
            'serialnumber',
            'ancillarynumber',
            'model',
            'dateofmanf',
            'manf',
            'subloc',
            'detailedloc',
            'currdate',
            'duedate',
            'statuslive',
            'itemnotes',
            'history',
            'lastReport',
            'multi_flag',
            'cont_freq',
            'condition',
            'surveyor',
            'agent',
            'broker',
            'reptype',
            'linked',
            'contractor',
            'created',
            'archived',
            'nfc',
            'pressure_data',
            'lev_data',
        ];
        $insertTypes = 'iisssssssssssssisssiissiisiiiisss';
        $insertValues = [
            $_REQUEST['locnumber'],
            $_REQUEST['clientnumber'],
            $_REQUEST['code'],
            $_REQUEST['desc'],
            $_REQUEST['swl'],
            $_REQUEST['plantnumber'],
            $_REQUEST['serialnumber'],
            $_REQUEST['ancillarynumber'],
            $_REQUEST['model'],
            $_REQUEST['dateofmanf'],
            $_REQUEST['manf'],
            $_REQUEST['subloc'],
            $_REQUEST['detailedloc'],
            $currdateTs,
            $duedateTs,
            $_REQUEST['statuslive'],
            $_REQUEST['itemnotes'],
            $_REQUEST['history'],
            $_REQUEST['lastReport'],
            $multi_flag,
            $cont_freq,
            $assetCondition,
            $_REQUEST['surveyor'],
            $_REQUEST['agent'],
            $_REQUEST['broker'],
            $_REQUEST['reptype'],
            $linkedValue,
            $contractorNumber,
            $createdTs,
            $archived,
            $nfc,
            $itemdetailsJson['pressure_data'],
            $itemdetailsJson['lev_data'],
        ];
        $placeholders = implode(',', array_fill(0, count($insertFields), '?'));
        $fieldSql = '`' . implode('`,`', $insertFields) . '`';
        $stmt = $GLOBALS['con']->prepare("INSERT INTO `itemdetails` ({$fieldSql}) VALUES ({$placeholders})") or die(mysqli_error($GLOBALS['con']));
        $stmt->bind_param($insertTypes, ...$insertValues);
        $stmt->execute();
        $id = mysqli_insert_id($GLOBALS['con']);
        echo "insert" . $_REQUEST['locnumber'] . $stmt->error;
        $stmt->close();
        if ((int)$id > 0) {
            plantChangeLogAdd((int)$id, 'asset_insert');
        }

        $selectedWsnumber = (int)($_REQUEST['wsSelect'] ?? ($_REQUEST['pending_wsnumber'] ?? 0));
        assetAttachWrittenScheme($selectedWsnumber, (int)$id);

        $tagTemp = trim((string)($_REQUEST['tagTemp'] ?? ''));

        if ($tagTemp !== '') {
            $tagTemp = enrep_safe_filename($tagTemp);
            $tenantDir = defined('TENANT_URL') ? trim((string)TENANT_URL, "/\\") : $tenant;
            $tagDir = '../../../' . $tenantDir . '/images/tags/';

            // Build file paths
            $tempMain  = $tagDir . $tagTemp . '.jpg';
            $tempThumb = $tagDir . $tagTemp . '_thumb.jpg';

            $finalMain  = $tagDir . $id . '.jpg';
            $finalThumb = $tagDir . $id . '_thumb.jpg';

            // If file exists, rename
            if (file_exists($tempMain)) {
                @rename($tempMain, $finalMain);
            }
            if (file_exists($tempThumb)) {
                @rename($tempThumb, $finalThumb);
            }
        }
        break;


    case "update":
        enrep_itemdetails_apply_nested_formdata($_REQUEST);
        $_REQUEST['statuslive'] = in_array(strtolower((string)($_REQUEST['statuslive'] ?? '')), ['on', '1', 'true', 'yes'], true) ? "1" : "0";
        foreach (['agent'] as $assetOptionalField) {
            $_REQUEST[$assetOptionalField] = $_REQUEST[$assetOptionalField] ?? '';
        }
        if ($_REQUEST['agent'] == "") {
            $_REQUEST['agent'] = "0";
        }

        $existingItemdetails = [];
        $stmt = $GLOBALS['con']->prepare("SELECT * FROM `itemdetails` WHERE `itemnumber`=? LIMIT 1");
        if ($stmt) {
            $existingItemnumber = (int)($_REQUEST['itemnumber'] ?? 0);
            $stmt->bind_param('i', $existingItemnumber);
            $stmt->execute();
            $res = $stmt->get_result();
            $stmt->close();
            $row = mysqli_fetch_array($res);
            if (is_array($row)) {
                $existingItemdetails = $row;
            }
        }
        $itemdetailsJson = enrep_itemdetails_json_from_request($_REQUEST, $existingItemdetails);
        $pressureJsonSql = mysqli_real_escape_string($GLOBALS['con'], $itemdetailsJson['pressure_data']);
        $levJsonSql = mysqli_real_escape_string($GLOBALS['con'], $itemdetailsJson['lev_data']);

        //$_REQUEST['plantnumber']=str_replace("'","",$_REQUEST['plantnumber']);
        $_REQUEST['model'] = str_replace("'", "&#39;", $_REQUEST['model']);

        $plantChangeOldSnapshot = plantChangeSnapshot((int)($_REQUEST['itemnumber'] ?? 0));

        $curr_ts = (isset($_REQUEST['currdate']) && $_REQUEST['currdate'] !== '') ? strtotime($_REQUEST['currdate']) : '';
        $due_ts  = (isset($_REQUEST['duedate'])  && $_REQUEST['duedate']  !== '') ? strtotime($_REQUEST['duedate'])  : '';
        $q = mysqli_query($GLOBALS['con'], "
UPDATE `itemdetails` SET
`locnumber`=CAST(NULLIF('" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['locnumber'] ?? '') . "','') AS SIGNED),
`code`=NULLIF('" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['code'] ?? '') . "',''),
`desc`=NULLIF('" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['desc'] ?? '') . "',''),
`swl`=NULLIF('" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['swl'] ?? '') . "',''),
`plantnumber`='" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['plantnumber'] ?? '') . "',
`serialnumber`='" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['serialnumber'] ?? '') . "',
`ancillarynumber`='" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['ancillarynumber'] ?? '') . "', /* NOT NULL */
`model`='" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['model'] ?? '') . "',
`dateofmanf`='" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['dateofmanf'] ?? '') . "',
`manf`='" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['manf'] ?? '') . "',
`subloc`='" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['subloc'] ?? '') . "',
`detailedloc`='" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['detailedloc'] ?? '') . "',
`currdate`=NULLIF('" . $curr_ts . "',''),
`duedate`=NULLIF('" . $due_ts . "',''),
`statuslive`=CAST(NULLIF('" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['statuslive'] ?? '') . "','') AS SIGNED),
`itemnotes`=NULLIF('" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['itemnotes'] ?? '') . "',''),
`history`=NULLIF('" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['history'] ?? '') . "',''),
`multi_flag`=CAST(NULLIF('" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['multi_flag'] ?? '') . "','') AS SIGNED),
`cont_freq`=CAST(NULLIF('" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['cont_freq'] ?? '') . "','') AS SIGNED),
`condition`=NULLIF('" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['condition'] ?? '') . "',''),
`pressure_data`='" . $pressureJsonSql . "',
`lev_data`='" . $levJsonSql . "',
`surveyor`=NULLIF('" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['surveyor'] ?? '') . "',''),
`agent`=CAST(NULLIF('" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['agent'] ?? '') . "','') AS SIGNED),
`broker`=CAST(NULLIF('" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['broker'] ?? '') . "','') AS SIGNED),
`reptype`='" . mysqli_real_escape_string($GLOBALS['con'], $_REQUEST['reptype']) . "'
WHERE `itemnumber`=" . (int)$_REQUEST['itemnumber'] . "
");
        plantChangeLogUpdate($plantChangeOldSnapshot, (int)($_REQUEST['itemnumber'] ?? 0), 'asset_update');


        $selectedWsnumber = (int)($_REQUEST['wsSelect'] ?? ($_REQUEST['pending_wsnumber'] ?? 0));
        assetAttachWrittenScheme($selectedWsnumber, (int)($_REQUEST['itemnumber'] ?? 0));

        if (($_REQUEST['isWS'] ?? '') == "1") {
            $pressureRequest = is_array($_REQUEST['pressure'] ?? null) ? $_REQUEST['pressure'] : [];
            $schemeNumberAlt = (string)($pressureRequest['scheme_number_alt'] ?? '');
            $stmt = $GLOBALS['con']->prepare("UPDATE `writtenscheme` SET `wSol`=?,`scheme_number_alt`=?,`wCat`=? WHERE `id`=?") or die(mysqli_error($GLOBALS['con']));
            $stmt->bind_param('sssi', $_REQUEST['wSol'], $schemeNumberAlt, $_REQUEST['wCat'], $_REQUEST['wsnumber']);
            $stmt->execute();
            $stmt->close();
        }

        $linkedValue = (string)($_REQUEST['linked'] ?? 'NULL');
        if ($linkedValue !== "NULL") {
            $linkedItems = enrep_int_list_from_mixed(str_replace('|', ',', $linkedValue));
            $stmt = $GLOBALS['con']->prepare("UPDATE `itemdetails` SET `linked`=? WHERE `itemnumber`=?") or die(mysqli_error($GLOBALS['con']));
            foreach ($linkedItems as $linkedItemnumber) {
                $stmt->bind_param('si', $linkedValue, $linkedItemnumber);
                $stmt->execute();
            }
            $stmt->close();
        }

        if (($_REQUEST['isLWS'] ?? '') == "1") {
            $stmt = $GLOBALS['con']->prepare("UPDATE `lwrittenscheme` SET `wSol`=?,`wCat`=? WHERE `id`=?") or die(mysqli_error($GLOBALS['con']));
            $stmt->bind_param('ssi', $_REQUEST['wSol'], $_REQUEST['wCat'], $_REQUEST['lwsnumber']);
            $stmt->execute();
            $stmt->close();
            echo "lws";
            echo $_REQUEST['lwsnumber'];
            $e;
        }

        echo "COmplete";
        break;


    case "getSite":
        $stmt = $GLOBALS['con']->prepare("SELECT `locnumber`,`locname` FROM `locations` WHERE `clientnumber`=?") or die(mysqli_error($GLOBALS['con']));
        $client = enrep_request_int('client');
        $stmt->bind_param('i', $client);
        $stmt->execute();
        $cc = $stmt->get_result();
        $stmt->close();
        $co = 0;
        //$ret='[';
        $return_arr = array();
        while ($pd = mysqli_fetch_array($cc)) {
            $row_array = array("value" => $pd['locname'], "name" => $pd['locnumber']);
            array_push($return_arr, $row_array);
        }
        //$ret.='['; 
        echo json_encode($return_arr);
        break;

    case "getAsset":
        $stmt = $GLOBALS['con']->prepare("SELECT `itemnumber`,`desc` FROM `itemdetails` WHERE `locnumber`=?") or die(mysqli_error($GLOBALS['con']));
        $loc = enrep_request_int('loc');
        $stmt->bind_param('i', $loc);
        $stmt->execute();
        $cc = $stmt->get_result();
        $stmt->close();
        $co = 0;
        //$ret='[';
        $return_arr = array();
        while ($pd = mysqli_fetch_array($cc)) {
            $row_array = array("value" => $pd['desc'], "name" => $pd['itemnumber']);
            array_push($return_arr, $row_array);
        }
        //$ret.='['; 
        echo json_encode($return_arr);
        break;
}

function genContractNo()
{
    $stmt = $GLOBALS['con']->prepare("SELECT `clientnumber` FROM `clientdetails` ORDER BY abs(clientnumber) DESC LIMIT 1") or die(mysqli_error($GLOBALS['con']));
    $stmt->execute();
    $s = $stmt->get_result();
    $stmt->close();
    $d = mysqli_fetch_array($s);
    $n = strtoupper($_SESSION['client']) . "-" . ($d['clientnumber'] + 1) . "-" . date('m') . date('y');
    return $n;
}

function listPlant($c, $n, $t)
{
    switch ($t) {
        default:
            break;

        case "select":
            $stmt = $GLOBALS['con']->prepare("SELECT * FROM `dd_plant` ORDER BY `code` ASC") or die(mysqli_error($GLOBALS['con']));
            $stmt->execute();
            $cc = $stmt->get_result();
            $stmt->close();
            while ($pd = mysqli_fetch_array($cc)) {
                $ca[] = $pd;
            }

            $ret = '<select class="form-select form-select-sm  w-100" id="' . $n . '" name="' . $n . '">';
            foreach ($ca as $px) {
                if ($c == $px['code']) {
                    $s = "SELECTED";
                } else {
                    $s = "";
                }
                $ret .= '<option value="' . $px['code'] . '" title="' . $px['description'] . '" ' . $s . '>' . $px['code'] . '</option>'; //.PHP_EOL;
            }
            $ret .= '</select>';
            return ($ret);
            break;

        case "name":
            $stmt = $GLOBALS['con']->prepare("SELECT * FROM `dd_plant` ORDER BY `description` ASC") or die(mysqli_error($GLOBALS['con']));
            $stmt->execute();
            $cc = $stmt->get_result();
            $stmt->close();
            while ($pd = mysqli_fetch_array($cc)) {
                $ca[] = $pd;
            }

            $ret = '<select class="form-select form-select-sm w-100" id="' . $n . '" name="' . $n . '">';
            foreach ($ca as $px) {
                if ($c == $px['code']) {
                    $s = "SELECTED";
                } else {
                    $s = "";
                }
                $ret .= '<option value="' . $px['description'] . '"  title="' . $px['code'] . '" ' . $s . ' >' . $px['description'] . '&nbsp;&nbsp;&nbsp;&nbsp;(' . $px['frequency'] . ' months)</option>'; //.PHP_EOL;
            }
            $ret .= '</select>';
            return ($ret);
            break;

        case "ajax":
            $stmt = $GLOBALS['con']->prepare("SELECT * FROM UNION SELECT * FROM  `dd_plant` ORDER BY `code` ASC") or die(mysqli_error($GLOBALS['con']));
            $stmt->execute();
            $cc = $stmt->get_result();
            $stmt->close();
            $cnt = mysqli_num_rows($cc);
            while ($pd = mysqli_fetch_array($cc)) {
                $ca[] = $pd;
            }
            $co = 0;
            $ret = 'var plantList = [';
            foreach ($ca as $px) {
                $co++;
                if ($co == $cnt) {
                    $s = "";
                } else {
                    $s = ",";
                }
                $ret .= '{"value":"' . $px['description'] . '","name":"' . $px['code'] . '"}' . $s . PHP_EOL;
            }
            $ret .= '];';
            return ($ret);
            break;
    }
}

function listClient($c, $n, $t, $p)
{
    switch ($t) {
        default:
            break;

        case "code":
            $stmt = $GLOBALS['con']->prepare("SELECT `clientnumber`,`clientname` FROM `clientdetails` WHERE `statuslive`='1' ORDER BY `clientname` ASC") or die(mysqli_error($GLOBALS['con']));
            $stmt->execute();
            $cc = $stmt->get_result();
            $stmt->close();
            while ($pd = mysqli_fetch_array($cc)) {
                $ca[] = $pd;
            }

            $ret = '<select class="form-control form-control-sm" id="' . $n . '" name="' . $n . '">';
            foreach ($ca as $px) {
                if ($c == $px['code']) {
                    $s = "SELECTED";
                } else {
                    $s = "";
                }
                $ret .= '<option value="' . $px['clientnumber'] . '" ' . $s . '>' . $px['clientname'] . '</option>'; //.PHP_EOL;
            }
            $ret .= '</select>';
            return ($ret);
            break;

        case "name":
            $stmt = $GLOBALS['con']->prepare("SELECT `clientnumber`,`clientname` FROM `clientdetails` WHERE `statuslive`='1'  ORDER BY `clientname` ASC") or die(mysqli_error($GLOBALS['con']));
            $stmt->execute();
            $cc = $stmt->get_result();
            $stmt->close();
            while ($pd = mysqli_fetch_array($cc)) {
                $ca[] = $pd;
            }

            $ret = '<select class="form-control form-control-sm" data-mdb-select-init data-mdb-filter="true"  id="' . $n . '" name="' . $n . '">';
            foreach ($ca as $px) {
                if ($c == $px['code']) {
                    $s = "SELECTED";
                } else {
                    $s = "";
                }
                $ret .= '<option value="' . $px['clientname'] . '" ' . $s . '>' . $px['clientname'] . '</option>'; //.PHP_EOL;
            }
            $ret .= '</select>';
            return ($ret);
            break;

        case "select":
            $stmt = $GLOBALS['con']->prepare("SELECT `clientnumber`,`clientname` FROM `clientdetails` WHERE `statuslive`='1'  ORDER BY `clientname` ASC") or die(mysqli_error($GLOBALS['con']));
            $stmt->execute();
            $cc = $stmt->get_result();
            $stmt->close();

            $ret = '<select class="form-control form-control-sm" data-mdb-select-init data-mdb-filter="true"  id="' . $n . '" name="' . $n . '" data-placeholder="' . $p . '">';
            $ret .= '<option value=""></option>';
            while ($pd = mysqli_fetch_array($cc)) {
                $ret .= '<option value="' . $pd['clientnumber'] . '" >' . $pd['clientname'] . '</option>'; //.PHP_EOL;
            }
            $ret .= '</select>';
            return ($ret);
            break;

        case "ajax":
            $stmt = $GLOBALS['con']->prepare("SELECT `clientnumber`,`clientname` FROM `clientdetails` WHERE `statuslive`='1'  ORDER BY `clientname` ASC") or die(mysqli_error($GLOBALS['con']));
            $stmt->execute();
            $cc = $stmt->get_result();
            $stmt->close();
            $cnt = mysqli_num_rows($cc);
            while ($pd = mysqli_fetch_array($cc)) {
                $ca[] = $pd;
            }
            $co = 0;
            $ret = 'var clientList = [';
            foreach ($ca as $px) {
                $px['clientname'] = str_replace('"', '', $px['clientname']);
                $px['clientname'] = str_replace('\&', 'and', $px['clientname']);
                $co++;
                if ($co == $cnt) {
                    $s = "";
                } else {
                    $s = ",";
                }
                $ret .= '{"value":"' . $px['clientname'] . '","name":"' . $px['clientnumber'] . '"}' . $s . PHP_EOL;
            }
            $ret .= '];';
            return ($ret);
            break;
    }
}

function listAgent($c, $n, $t, $cnt)
{
    switch ($t) {
        default:
            break;

        case "select":
            if ($cnt != "") {
                $stmt = $GLOBALS['con']->prepare("SELECT `agent_number` FROM `clientdetails` WHERE `clientnumber`='" . $cnt . "'") or die(mysqli_error($GLOBALS['con']));
                $stmt->execute();
                $cd = $stmt->get_result();
                $stmt->close();
                $cxa = mysqli_fetch_array($cd);
            }

            $stmt = $GLOBALS['con']->prepare("SELECT `agent_number`,`agent_name` FROM `agents` WHERE `statuslive`='1' ORDER BY `agent_name` ASC") or die(mysqli_error($GLOBALS['con']));
            $stmt->execute();
            $cc = $stmt->get_result();
            $stmt->close();
            while ($pd = mysqli_fetch_array($cc)) {
                $ca[] = $pd;
            }

            $ret = '<select class="form-control form-control-sm" data-mdb-select-init data-mdb-filter="true"  id="' . $n . '" name="' . $n . '">';
            $ret .= '<option value="0">None</option>'; //.PHP_EOL;	
            foreach ($ca as $px) {
                // Check if both 'agent_number' and 'agent_name' exist in the current array element
                if (isset($px['agent_number']) && isset($px['agent_name'])) {
                    // Determine if this option should be selected
                    $s = ($c == $px['agent_number'] || (isset($ca['agent_number']) && $ca['agent_number'] == $px['agent_number'])) ? "SELECTED" : "";

                    // Append the option to the return string
                    $ret .= '<option value="' . htmlspecialchars($px['agent_number'], ENT_QUOTES) . '" ' . $s . '>'
                        . htmlspecialchars($px['agent_name'], ENT_QUOTES) . '</option>';
                }
            }

            // Close the select element
            $ret .= '</select>';
            return ($ret);
            break;

        case "name":
            $stmt = $GLOBALS['con']->prepare("SELECT `agent_number`,`agent_name` FROM `agents` WHERE `statuslive`='1'  ORDER BY `agent_name` ASC") or die(mysqli_error($GLOBALS['con']));
            $stmt->execute();
            $cc = $stmt->get_result();
            $stmt->close();
            while ($pd = mysqli_fetch_array($cc)) {
                $ca[] = $pd;
            }

            $ret = '<select class="form-control form-control-sm" id="' . $n . '" name="' . $n . '">';
            foreach ($ca as $px) {
                // Check if 'agent_name' exists in the current array element
                if (isset($px['agent_name'])) {
                    // Set the selected attribute if the current agent_name matches $c
                    $s = ($c === $px['agent_name']) ? "SELECTED" : "";

                    // Append the option to the return string
                    $ret .= '<option value="' . htmlspecialchars($px['agent_name'], ENT_QUOTES) . '" ' . $s . '>'
                        . htmlspecialchars($px['agent_name'], ENT_QUOTES) . '</option>';
                }
            }

            // Close the select element
            $ret .= '</select>';
            return ($ret);
            break;

        case "ajax":
            $stmt = $GLOBALS['con']->prepare("SELECT `agent_number`,`agent_name` FROM `agents` WHERE `statuslive`='1'  ORDER BY `agent_name` ASC") or die(mysqli_error($GLOBALS['con']));
            $stmt->execute();
            $cc = $stmt->get_result();
            $stmt->close();
            $cnt = mysqli_num_rows($cc);
            while ($pd = mysqli_fetch_array($cc)) {
                $ca[] = $pd;
            }
            $co = 0;
            $ret = 'var clientList = [';
            foreach ($ca as $px) {
                $px['agent_name'] = str_replace('"', '', $px['agent_name']);
                $px['agent_name'] = str_replace('\&', 'and', $px['agent_name']);
                $co++;
                if ($co == $cnt) {
                    $s = "";
                } else {
                    $s = ",";
                }
                $ret .= '{"value":"' . $px['agent_name'] . '","name":"' . $px['agent_number'] . '"}' . $s . PHP_EOL;
            }
            $ret .= '];';
            return ($ret);
            break;
    }
}

function listBroker($c, $n, $t, $cnt)
{
    switch ($t) {
        default:
            break;

        case "select":
            if ($cnt != "") {
                $stmt = $GLOBALS['con']->prepare("SELECT `broker_number` FROM `clientdetails` WHERE `clientnumber`='" . $cnt . "'") or die(mysqli_error($GLOBALS['con']));
                $stmt->execute();
                $cd = $stmt->get_result();
                $stmt->close();
                $cxa = mysqli_fetch_array($cd);
            }

            $stmt = $GLOBALS['con']->prepare("SELECT `broker_number`,`broker_name` FROM `brokers` WHERE `statuslive`='1' ORDER BY `broker_name` ASC") or die(mysqli_error($GLOBALS['con']));
            $stmt->execute();
            $cc = $stmt->get_result();
            $stmt->close();
            while ($pd = mysqli_fetch_array($cc)) {
                $ca[] = $pd;
            }

            $ret = '<select class="form-control form-control-sm" data-mdb-select-init data-mdb-filter="true"  id="' . $n . '" name="' . $n . '">';
            $ret .= '<option value="0">None</option>'; //.PHP_EOL;	
            foreach ($ca as $px) {
                // Check if both 'broker_number' and 'broker_name' exist in the current array element
                if (isset($px['broker_number'], $px['broker_name'])) {
                    // Set the selected attribute if conditions are met
                    $s = ($c === $px['broker_number'] || (isset($ca['broker_number']) && $ca['broker_number'] === $px['broker_number'])) ? "SELECTED" : "";

                    // Append option to return string
                    $ret .= '<option value="' . htmlspecialchars($px['broker_number'], ENT_QUOTES) . '" ' . $s . '>'
                        . htmlspecialchars($px['broker_name'], ENT_QUOTES) . '</option>';
                }
            }
            $ret .= '</select>';
            return ($ret);
            break;

        case "name":
            $stmt = $GLOBALS['con']->prepare("SELECT `broker_number`,`broker_name` FROM `brokers` WHERE `statuslive`='1'  ORDER BY `broker_name` ASC") or die(mysqli_error($GLOBALS['con']));
            $stmt->execute();
            $cc = $stmt->get_result();
            $stmt->close();
            while ($pd = mysqli_fetch_array($cc)) {
                $ca[] = $pd;
            }

            $ret = '<select class="form-control form-control-sm" id="' . $n . '" name="' . $n . '">';
            foreach ($ca as $px) {
                if ($c == $px['agent_name']) {
                    $s = "SELECTED";
                } else {
                    $s = "";
                }
                $ret .= '<option value="' . $px['broker_name'] . '" ' . $s . '>' . $px['broker_name'] . '</option>'; //.PHP_EOL;
            }
            $ret .= '</select>';
            return ($ret);
            break;

        case "ajax":
            $stmt = $GLOBALS['con']->prepare("SELECT `broker_number`,`broker_name` FROM `brokers` WHERE `statuslive`='1'  ORDER BY `broker_name` ASC") or die(mysqli_error($GLOBALS['con']));
            $stmt->execute();
            $cc = $stmt->get_result();
            $stmt->close();
            $cnt = mysqli_num_rows($cc);
            while ($pd = mysqli_fetch_array($cc)) {
                $ca[] = $pd;
            }
            $co = 0;
            $ret = 'var clientList = [';
            foreach ($ca as $px) {
                $px['broker_name'] = str_replace('"', '', $px['broker_name']);
                $px['broker_name'] = str_replace('\&', 'and', $px['broker_name']);
                $co++;
                if ($co == $cnt) {
                    $s = "";
                } else {
                    $s = ",";
                }
                $ret .= '{"value":"' . $px['broker_name'] . '","name":"' . $px['broker_number'] . '"}' . $s . PHP_EOL;
            }
            $ret .= '];';
            return ($ret);
            break;
    }
}



function listSurveyor($c, $n, $t)
{
    if (!empty($_SESSION['contractorNumber'])) {
        $filter = "AND `contractor`='" . $_SESSION['contractorNumber'] . "'";
    }
    switch ($t) {
        default:
            break;

        case "select":
            $ca = array();
            $stmt = $GLOBALS['con']->prepare("SELECT `id`,`forename`,`surname` FROM `surveyor` WHERE `statuslive`='1' $filter ORDER BY `forename` ASC") or die(mysqli_error($GLOBALS['con']));
            $stmt->execute();
            $cc = $stmt->get_result();
            $stmt->close();
            while ($pd = mysqli_fetch_array($cc)) {
                $ca[] = $pd;
            }
            $ret = '<select class="form-control form-control-sm filterSelect form-select" id="' . $n . '" name="' . $n . '">';
            $ret .= '<option value="NULL">Select primary Surveyor</option>'; //.PHP_EOL;	
            foreach ($ca as $px) {
                $name = $px['forename'] . ' ' . $px['surname'];
                if ($c == $px['id']) {
                    $s = "SELECTED";
                } else {
                    $s = "";
                }
                $ret .= '<option value="' . $px['id'] . '" ' . $s . '>' . $name . '</option>'; //.PHP_EOL;
            }
            $ret .= '</select>';
            return ($ret);
            break;

        case "name":
            $stmt = $GLOBALS['con']->prepare("SELECT `esname`,`forename`,`surname` FROM `surveyor` WHERE `statuslive`='1'  ORDER BY `forename` ASC") or die(mysqli_error($GLOBALS['con']));
            $stmt->execute();
            $cc = $stmt->get_result();
            $stmt->close();
            while ($pd = mysqli_fetch_array($cc)) {
                $ca[] = $pd;
            }
            $ret = '<select class="form-control form-control-sm" id="' . $n . '" name="' . $n . '">';
            $ret .= '<option value="NULL">Select Surveyor</option>'; //.PHP_EOL;	
            foreach ($ca as $px) {
                $name = $px['forename'] . ' ' . $px['surname'];
                if ($c == $name) {
                    $s = "SELECTED";
                } else {
                    $s = "";
                }
                $ret .= '<option value="' . $name . '" ' . $s . '>' . $name . '</option>'; //.PHP_EOL;
            }
            $ret .= '</select>';
            return ($ret);
            break;

        case "ajax":
            $stmt = $GLOBALS['con']->prepare("SELECT `esname`,`forename`,`surname` FROM `surveyor` WHERE `statuslive`='1'  ORDER BY `forename` ASC") or die(mysqli_error($GLOBALS['con']));
            $stmt->execute();
            $cc = $stmt->get_result();
            $stmt->close();
            $cnt = mysqli_num_rows($cc);
            while ($pd = mysqli_fetch_array($cc)) {
                $ca[] = $pd;
            }

            $co = 0;
            $ret = 'var clientList = [';
            foreach ($ca as $px) {
                $name = $px['forename'] . ' ' . $px['surname'];
                $name = str_replace('"', '', $name);
                $name = str_replace('\&', 'and', $name);
                $co++;
                if ($co == $cnt) {
                    $s = "";
                } else {
                    $s = ",";
                }
                $ret .= '{"value":"' . $name . '","name":"' . $px['esname'] . '"}' . $s . PHP_EOL;
            }
            $ret .= '];';
            return ($ret);
            break;
    }
}


function listReptype($c, $n, $t)
{

    $ret = '<select class="form-control form-control-sm" data-mdb-select-init data-mdb-size="sm" data-mdb-filter="true" id="' . $n . '" name="' . $n . '">';
    $ret .= '<option value="NULL"';
    if ($c == "") {
        $ret .= 'SELECTED';
    }
    $ret .= '>Select Report type</option>'; //.PHP_EOL;	
    // Get selected form numbers from master_formtypes
    $selectedQuery = "SELECT formnumber FROM master_formtypes WHERE toggle = 1";
    $selectedResult = mysqli_query($GLOBALS['con'], $selectedQuery) or die(mysqli_error($GLOBALS['con']));

    // Create an array to store selected form numbers
    $selectedFormNumbers = [];
    while ($row = mysqli_fetch_assoc($selectedResult)) {
        $selectedFormNumbers[] = $row['formnumber'];
    }

    // Query form types from ".$GLOBALS['path'].".dd_formtypes
    $queryPath = "SELECT * FROM " . $GLOBALS['path'] . ".dd_formtypes ORDER BY formnumber ASC";
    $stmtPath = $GLOBALS['master']->prepare($queryPath) or die(mysqli_error($GLOBALS['master']));
    $stmtPath->execute();
    $recallPath = $stmtPath->get_result();
    $stmtPath->close();

    // Query form types from dd_formtypes 
    $queryLocal = "SELECT * FROM dd_formtypes ORDER BY formnumber ASC";
    $stmtLocal = $GLOBALS['con']->prepare($queryLocal) or die(mysqli_error($GLOBALS['con']));
    $stmtLocal->execute();
    $recallLocal = $stmtLocal->get_result();
    $stmtLocal->close();

    // Filter results from ".$GLOBALS['path'].".dd_formtypes and store them in $reps
    $reps = [];  // Array to store the final results

    // Filter the form types from ".$GLOBALS['path'].".dd_formtypes using selected form numbers
    while ($dtaPath = mysqli_fetch_array($recallPath)) {
        if (in_array($dtaPath['formnumber'], $selectedFormNumbers)) {
            $reps[] = $dtaPath;  // Only include those selected in master_formtypes
        }
    }

    // Add all form types from dd_formtypes (without filtering)
    while ($dtaLocal = mysqli_fetch_array($recallLocal)) {
        $reps[] = $dtaLocal;  // Add unconditionally
    }


    foreach ($reps as $px) {
        if ($c == $px['formnumber']) {
            $s = "SELECTED";
        } else {
            $s = "";
        }
        $ret .= '<option value="' . $px['formnumber'] . '" ' . $s . '>' . $px['formnumber'] . ": " . $px['formtype'] . '</option>'; //.PHP_EOL;	
    }
    $ret .= '</select>';
    return ($ret);
}


function getSites($s, $c)
{
    $stmt = $GLOBALS['con']->prepare("SELECT `locnumber`,`locname`,`postcode`,`locaddress1`,`locaddress2`,`locaddress3`,`locaddress4` FROM `locations` WHERE `clientnumber`=?  AND statuslive=1") or die($error = mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $s);
    $stmt->execute();
    $res = $stmt->get_result();
    $stmt->close();
    $ret = '<select class="form-control form-control-sm" data-mdb-select-init data-mdb-size="sm" data-mdb-filter="true" id="locnumber" name="locnumber" data-placeholder="Select Location">';
    $ret .= '<option value="">Select Location</option>';
    $count = mysqli_num_rows($res);
    while ($d = mysqli_fetch_array($res)) {
        if ($c == $d['locnumber']) {
            $s = 'SELECTED';
        } else {
            $s = '';
        }
        $ret .= '<option value="' . $d['locnumber'] . '" ' . $s . '>' . $d['locaddress1'] . ',' . $d['locaddress2'] . ',' . $d['locaddress3'] . ',' . $d['locaddress4'] . ', ' . $d['postcode'] . '</option>';
    }

    $ret .= '</select>';
    return $ret;
}

function getSitesSmall($s, $c)
{
    $stmt = $GLOBALS['con']->prepare("SELECT `locnumber`,`locname`,`postcode`,`locaddress1`,`locaddress2`,`locaddress3`,`locaddress4` FROM `locations` WHERE `clientnumber`=? AND statuslive=1") or die($error = mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $s);
    $stmt->execute();
    $res = $stmt->get_result();
    $stmt->close();
    $ret = '<select class="form-control form-control-sm" data-mdb-select-init data-mdb-size="sm" data-mdb-filter="true" id="locnumber" name="locnumber" data-placeholder="Select Location">';
    $ret .= '<option value="">Select Location</option>';
    $count = mysqli_num_rows($res);
    while ($d = mysqli_fetch_array($res)) {
        if ($c == $d['locnumber']) {
            $s = 'SELECTED';
        } else {
            $s = '';
        }
        $ret .= '<option value="' . $d['locnumber'] . '" ' . $s . '>' . $d['locname'] . ' - ' . $d['postcode'] . '</option>';
    }

    $ret .= '</select>';
    return $ret;
}


function getSites2($s, $c)
{
    $stmt = $GLOBALS['con']->prepare("SELECT `locnumber`,`locname`,`postcode` FROM `locations` WHERE `clientnumber`=?  AND statuslive=1") or die($error = mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $s);
    $stmt->execute();
    $res = $stmt->get_result();
    $stmt->close();
    $ret = '<select class="form-control form-control-sm" data-mdb-select-init data-mdb-size="sm" data-mdb-filter="true" id="locnumber' . rand() . '" name="locnumber" data-placeholder="Select Location">';
    $ret .= '<option value="">Select Location</option>';
    $count = mysqli_num_rows($res);
    while ($d = mysqli_fetch_array($res)) {
        if ($c == $d['locnumber']) {
            $s = 'SELECTED';
        } else {
            $s = '';
        }
        $ret .= '<option value="' . $d['locnumber'] . '" ' . $s . '>' . $d['postcode'] . ' - ' . $d['locname'] . '</option>';
    }

    $ret .= '</select>';
    return $ret;
}

function getSites3($s, $c)
{
    $stmt = $GLOBALS['con']->prepare("SELECT `locnumber`,`locname`,`postcode` FROM `locations` WHERE `clientnumber`=?  AND statuslive=1") or die($error = mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $s);
    $stmt->execute();
    $res = $stmt->get_result();
    $stmt->close();
    $ret = '<select class="form-control form-control-sm" data-mdb-select-init data-mdb-size="sm" data-mdb-filter="true" id="WSlocnumber" name="locnumber" data-placeholder="Select Location">';
    $ret .= '<option value="">Select Location</option>';
    $count = mysqli_num_rows($res);
    while ($d = mysqli_fetch_array($res)) {
        if ($c == $d['locnumber']) {
            $s = 'SELECTED';
        } else {
            $s = '';
        }
        $ret .= '<option value="' . $d['locnumber'] . '" ' . $s . '>' . $d['postcode'] . ' - ' . $d['locname'] . '</option>';
    }

    $ret .= '</select>';
    return $ret;
}

function getSites4($s, $c)
{
    $stmt = $GLOBALS['con']->prepare("SELECT `locnumber`,`locname`,`postcode` FROM `locations` WHERE `clientnumber`=?  AND statuslive=1") or die($error = mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $s);
    $stmt->execute();
    $res = $stmt->get_result();
    $stmt->close();
    $ret = '<select class="form-control form-control-sm" data-mdb-select-init data-mdb-size="sm" data-mdb-filter="true" id="WSElocnumber" name="locnumber" data-placeholder="Select Location">';
    $ret .= '<option value="">Select Location</option>';
    $count = mysqli_num_rows($res);
    while ($d = mysqli_fetch_array($res)) {
        if ($c == $d['locnumber']) {
            $s = 'SELECTED';
        } else {
            $s = '';
        }
        $ret .= '<option value="' . $d['locnumber'] . '" ' . $s . '>' . $d['postcode'] . ' - ' . $d['locname'] . '</option>';
    }

    $ret .= '</select>';
    return $ret;
}



function getItemName($itemnumber)
{
    $stmt = $GLOBALS['con']->prepare("SELECT `desc` FROM `itemdetails` WHERE `itemnumber`=?") or die(mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $itemnumber);
    $stmt->execute();
    $rc = $stmt->get_result();
    $stmt->close();
    $cd = mysqli_fetch_array($rc);
    return $cd['desc'];
}

function getLEVData($itemnumber)
{
    $stmt = $GLOBALS['con']->prepare("SELECT * FROM `itemdetails` WHERE `itemnumber`=?") or die(mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $itemnumber);
    $stmt->execute();
    $rc = $stmt->get_result();
    $stmt->close();
    $cd = mysqli_fetch_array($rc);
    if (is_array($cd)) {
        $cd = array_replace($cd, enrep_itemdetails_lev_from_record($cd));
    }
    if (empty($cd['process'])) {
        return 'None found';
    }
    return $cd['process'];
}

function getPSSRData($itemnumber)
{
    $stmt = $GLOBALS['con']->prepare("SELECT `id` FROM `wsitems` WHERE `itemnumber`=? LIMIT 1") or die(mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $itemnumber);
    $stmt->execute();
    $wsResult = $stmt->get_result();
    $stmt->close();
    if ($wsResult && mysqli_fetch_array($wsResult)) {
        return;
    }

    $stmt = $GLOBALS['con']->prepare("SELECT * FROM `itemdetails` WHERE `itemnumber`=?") or die(mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $itemnumber);
    $stmt->execute();
    $rc = $stmt->get_result();
    $stmt->close();
    $cd = mysqli_fetch_array($rc);
    if (is_array($cd)) {
        $cd = array_replace($cd, enrep_itemdetails_pressure_from_record($cd));
    }
    if (empty($cd['system_type'])) {
        return 'None found';
    }
}

function isWSItem($itemnumber)
{
    $stmt = $GLOBALS['con']->prepare("SELECT `id` FROM `wsitems` WHERE `itemnumber`=? LIMIT 1") or die($error = mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $itemnumber);
    $stmt->execute();
    $wsResult = $stmt->get_result();
    $stmt->close();
    if ($wsResult && mysqli_fetch_array($wsResult)) {
        return "checked";
    }

    $stmt = $GLOBALS['con']->prepare("SELECT * FROM `itemdetails` WHERE `itemnumber`=?") or die($error = mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $itemnumber);
    $stmt->execute();
    $res = $stmt->get_result();
    $stmt->close();
    $d = mysqli_fetch_array($res);
    if (is_array($d)) {
        $d = array_replace($d, enrep_itemdetails_pressure_from_record($d));
    }
    if (empty($d['system_type'])) {
        return "";
    } else {
        return "checked";
    }
}

function getWSData($itemnumber)
{
    //check for instance
    $stmt = $GLOBALS['con']->prepare("SELECT `id`,`wsnumber` FROM `wsitems` WHERE `itemnumber`=?") or die($error = mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $itemnumber);
    $stmt->execute();
    $res = $stmt->get_result();
    $stmt->close();
    $c = mysqli_num_rows($res);
    $d = mysqli_fetch_array($res);
    if ($c > 0) {
        $stmt = $GLOBALS['con']->prepare("SELECT `description`,`no` FROM `writtenscheme` WHERE `id`=?") or die($error = mysqli_error($GLOBALS['con']));
        $stmt->bind_param('i', $d['wsnumber']);
        $stmt->execute();
        $res2 = $stmt->get_result();
        $stmt->close();
        $e = mysqli_fetch_array($res2);
        return '<div class="row">
<div class="col-md-7">Item attached to Written Scheme <strong>' . $e['no'] . '</strong></div>
<div class="col-md-4"><a href="javascript:void(0)" class="btn btn-secondary btn-sm" onClick="editWSC(\'' . $d['wsnumber'] . '\')" data-toggle="tooltip" data-placement="left" title="View ' . $e['description'] . ' details"><i class="fad fa-search"></i></a>&nbsp;&nbsp;&nbsp;
<a href="javascript:void(0)" class="btn btn-secondary btn-sm" onClick="printWSC(\'' . $d['wsnumber'] . '\')" data-toggle="tooltip" data-placement="left" title="Print ' . $e['description'] . '"><i class="fad fa-print"></i></a>&nbsp;&nbsp;&nbsp;
<a href="javascript:void(0)" class="btn btn-secondary btn-sm" onClick="emailWSC(\'' . $d['wsnumber'] . '\')" data-toggle="tooltip" data-placement="left" title="Email ' . $e['description'] . '"><i class="fad fa-envelope"></i></a>
</div><input type="hidden" name="isWS" id="isWS" value="1" /><input type="hidden" name="wsnumber" id="wsnumber" value="' . $d['wsnumber'] . '" /></div>';
    } else {
        return 'None found';
    }
}

function getPssrNumber($itemnumber)
{
    //check for instance
    $stmt = $GLOBALS['con']->prepare("SELECT `wsnumber` FROM `wsitems` WHERE `itemnumber`=?") or die($error = mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $itemnumber);
    $stmt->execute();
    $res = $stmt->get_result();
    $stmt->close();
    $d = mysqli_fetch_array($res);
    return $d['wsnumber'] ?? '';
}

function getPssrEno($itemnumber)
{
    //check for instance
    $stmt = $GLOBALS['con']->prepare("SELECT `wsnumber` FROM `wsitems` WHERE `itemnumber`=?") or die($error = mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $itemnumber);
    $stmt->execute();
    $res = $stmt->get_result();
    $stmt->close();
    $d = mysqli_fetch_array($res);
    if (empty($d['wsnumber'])) {
        return '';
    }

    $stmt2 = $GLOBALS['con']->prepare("SELECT `no` FROM `writtenscheme` WHERE `id`=?") or die($error = mysqli_error($GLOBALS['con']));
    $stmt2->bind_param('i', $d['wsnumber']);
    $stmt2->execute();
    $resx = $stmt2->get_result();
    $stmt2->close();
    $e = mysqli_fetch_array($resx);

    return $e['no'] ?? '';
}

function listWSE($client)
{
    $stmt = $GLOBALS['con']->prepare("SELECT * FROM `writtenscheme` WHERE `clientnumber`=? ORDER BY abs(no) ASC ") or die(mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $client);
    $stmt->execute();
    $cc = $stmt->get_result();
    $stmt->close();
    $ret = '<div class="col-4"><select id="wsSelect" name="wsSelect" class="form-control" data-mdb-select-init data-mdb-filter="true" >';
    $ret .= '<option value="">SELECT SCHEME</option>';
    while ($cd = mysqli_fetch_array($cc)) {
        $ret .= '<option value="' . $cd['id'] . '"><small>' . $cd['no'] . '</small>:' . $cd['title'] . '</option>';
    }
    $ret .= '</select></div>';
    return $ret;
}

function getPssrNo($itemnumber, $clientnumber)
{
    //check for instance
    $stmt = $GLOBALS['con']->prepare("SELECT `wsnumber` FROM `wsitems` WHERE `itemnumber`=?") or die($error = mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $itemnumber);
    $stmt->execute();
    $res = $stmt->get_result();
    $stmt->close();
    $d = mysqli_fetch_array($res);

    if (empty($d['wsnumber'])) {
        return '<div class="row"><div class="col-8 alert alert-warning p-1 ps-2">Not attached to WS yet, please complete the item registration first.</div>' . listWSE($clientnumber) . '</div>';
    } else {
        $stmt2 = $GLOBALS['con']->prepare("SELECT `no` FROM `writtenscheme` WHERE `id`=?") or die($error = mysqli_error($GLOBALS['con']));
        $stmt2->bind_param('i', $d['wsnumber']);
        $stmt2->execute();
        $resx = $stmt2->get_result();
        $stmt2->close();
        $e = mysqli_fetch_array($resx);
        return '<div class="alert alert-success p-1 ps-2">Item is attached to the Written Scheme <strong>' . ($e['no'] ?? '') . '</strong></div>';
    }
}

function getPssrReviews($wsnumber)
{
    $ret = '';
    $stmt = $GLOBALS['con']->prepare("SELECT * FROM `wsrevisions` WHERE `wsnumber`=? ORDER BY abs(date) DESC") or die($error = mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $wsnumber);
    $stmt->execute();
    $res = $stmt->get_result();
    $stmt->close();
    while ($d = mysqli_fetch_array($res)) {
        $stmt = $GLOBALS['con']->prepare("SELECT `forename`,`surname` FROM `surveyor` WHERE `id`=?") or die($error = mysqli_error($GLOBALS['con']));
        $stmt->bind_param('i', $d['surveyor']);
        $stmt->execute();
        $res2 = $stmt->get_result();
        $stmt->close();
        $e = mysqli_fetch_array($res2);
        if ($_SESSION['usertype'] == "admins") {
            $del = '<a href="javascript:void(0)" class="btn btn-danger btn-sm" onClick="remrevConfirm(\'' . $d['id'] . '\')" data-toggle="tooltip" data-placement="left" title="Remove this revision entry"><i class="fad fa-times"></i></a>';
        }
        $ret .= '<tr id="Rr' . $d['id'] . '"><td>' . date("d-m-Y", $d['date']) . ' <small>' . date("H:m:i", $d['date']) . '</small></td><td>' . $d['description'] . '</td><td>' . $e['forename'] . ' ' . $e['surname'] . '</td><td>' . $del . '</td></tr>';
    }
    return $ret;
}

function isLWSItem($itemnumber)
{
    $stmt = $GLOBALS['con']->prepare("SELECT * FROM `itemdetails` WHERE `itemnumber`=?") or die($error = mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $itemnumber);
    $stmt->execute();
    $res = $stmt->get_result();
    $stmt->close();
    $d = mysqli_fetch_array($res);
    if (is_array($d)) {
        $d = array_replace($d, enrep_itemdetails_lev_from_record($d));
    }
    if (empty($d['process'])) {
        return "";
    } else {
        return "checked";
    }
}


function getLWSData($itemnumber)
{
    //check for instance
    $stmt = $GLOBALS['con']->prepare("SELECT `id`,`lwsnumber` FROM `lwsitems` WHERE `itemnumber`=?") or die($error = mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $itemnumber);
    $stmt->execute();
    $res = $stmt->get_result();
    $stmt->close();
    $c = mysqli_num_rows($res);
    $d = mysqli_fetch_array($res);
    if ($c > 0) {
        $stmt = $GLOBALS['con']->prepare("SELECT `description`,`no` FROM `lwrittenscheme` WHERE `id`=?") or die($error = mysqli_error($GLOBALS['con']));
        $stmt->bind_param('i', $d['lwsnumber']);
        $stmt->execute();
        $res2 = $stmt->get_result();
        $stmt->close();
        $e = mysqli_fetch_array($res2);
        return '<div class="row">
<div class="col-md-7">Item attached to LOLER Written Scheme <strong>' . $e['no'] . '</strong></div>
<div class="col-md-4"><a href="javascript:void(0)" class="btn btn-secondary btn-sm" onClick="editLWSC(\'' . $d['lwsnumber'] . '\')" data-toggle="tooltip" data-placement="left" title="View ' . $e['description'] . ' details"><i class="fad fa-search"></i></a>&nbsp;&nbsp;&nbsp;
<a href="javascript:void(0)" class="btn btn-secondary btn-sm" onClick="printLWSC(\'' . $d['lwsnumber'] . '\')" data-toggle="tooltip" data-placement="left" title="Print ' . $e['description'] . '"><i class="fad fa-print"></i></a>&nbsp;&nbsp;&nbsp;
<a href="javascript:void(0)" class="btn btn-secondary btn-sm" onClick="emailLWSC(\'' . $d['lwsnumber'] . '\')" data-toggle="tooltip" data-placement="left" title="Email ' . $e['description'] . '"><i class="fad fa-envelope"></i></a>
</div><input type="hidden" name="isLWS" id="isLWS" value="1" /><input type="hidden" name="lwsnumber" id="lwsnumber" value="' . $d['lwsnumber'] . '" /></div>';
    } else {
        return 'None found';
    }
}

function getLWSNumber($itemnumber)
{
    //check for instance
    $stmt = $GLOBALS['con']->prepare("SELECT `lwsnumber` FROM `lwsitems` WHERE `itemnumber`=?") or die($error = mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $itemnumber);
    $stmt->execute();
    $res = $stmt->get_result();
    $stmt->close();
    $d = mysqli_fetch_array($res);
    return ($d['lwsnumber']);
}

function getLWSReviews($wsnumber)
{
    $ret = '';
    $stmt = $GLOBALS['con']->prepare("SELECT * FROM `lwsrevisions` WHERE `lwsnumber`=? ORDER BY abs(date) DESC") or die($error = mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $wsnumber);
    $stmt->execute();
    $res = $stmt->get_result();
    $stmt->close();
    while ($d = mysqli_fetch_array($res)) {
        $stmt = $GLOBALS['con']->prepare("SELECT `forename`,`surname` FROM `surveyor` WHERE `id`=?") or die($error = mysqli_error($GLOBALS['con']));
        $stmt->bind_param('i', $d['surveyor']);
        $stmt->execute();
        $res2 = $stmt->get_result();
        $stmt->close();
        $e = mysqli_fetch_array($res2);
        if ($_SESSION['usertype'] == "admins") {
            $del = '<a href="javascript:void(0)" class="btn btn-danger btn-sm" onClick="remrevConfirm(\'' . $d['id'] . '\')" data-toggle="tooltip" data-placement="left" title="Remove this revision entry"><i class="fad fa-times"></i></a>';
        }
        $ret .= '<tr><td>' . date("d-m-Y", $d['date']) . ' <small>' . date("H:m:i", $d['date']) . '</small></td><td>' . $d['description'] . '</td><td>' . $e['forename'] . ' ' . $e['surname'] . '</td><td>' . $del . '</td></tr>';
    }
    return $ret;
}

function getItemList($clientnumber, $current)
{
    $ret = '';
    //check for instance
    $stmt = $GLOBALS['con']->prepare("SELECT `itemnumber`,`desc`,`serialnumber` FROM `itemdetails` WHERE `clientnumber`=? AND `statuslive`='1'") or die($error = mysqli_error($GLOBALS['con']));
    $stmt->bind_param('i', $clientnumber);
    $stmt->execute();
    $res = $stmt->get_result();
    $stmt->close();
    while ($d = mysqli_fetch_array($res)) {
        if ($current == $d['itemnumber']) {
            $s = "SELECTED";
        } else {
            $s = "";
        }
        $ret .= '<option value="' . $d['itemnumber'] . '" ' . $s . '>' . $d['desc'] . ' - ' . $d['serialnumber'] . '</option>';
    }
    return $ret;
}



/* =======================
 * ASSET IMPORT: UPLOAD CSV
 * ======================= */
function assetUploadCSV(int $clientnumber): array
{
    if ($clientnumber <= 0) return ['status' => 'error', 'message' => 'Invalid clientnumber'];
    if (!isset($GLOBALS['con']) || !($GLOBALS['con'] instanceof mysqli))
        return ['status' => 'error', 'message' => 'DB connection unavailable'];
    $GLOBALS['con']->set_charset('utf8mb4');

    if (!isset($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK)
        return ['status' => 'error', 'message' => 'CSV upload failed'];

    $tmp = $_FILES['file']['tmp_name'];

    // --- UTF-8 validation ---
    $raw = file_get_contents($tmp);

    if ($raw === false) {
        return ['status' => 'error', 'message' => 'Unable to read uploaded file'];
    }

    // Strip UTF-8 BOM if present
    if (substr($raw, 0, 3) === "\xEF\xBB\xBF") {
        $raw = substr($raw, 3);
    }

    // Detect encoding
    $encoding = mb_detect_encoding($raw, ['UTF-8', 'ISO-8859-1', 'Windows-1252'], true);

    // If not UTF-8, reject
    if ($encoding !== 'UTF-8') {
        return [
            'status' => 'error',
            'message' => 'CSV must be UTF-8 encoded. Please re-save the file as UTF-8 and try again.',
            'detected_encoding' => $encoding
        ];
    }

    $fh  = @fopen($tmp, 'r');
    if (!$fh) return ['status' => 'error', 'message' => 'Unable to read CSV'];

    // expected headers
    $expected = [
        'Description',
        'Safe working load',
        'Plant Number',
        'Serial Number',
        'Model',
        'Date of manufacture',
        'Manufacturer',
        'Due Date',
        'Frequency',
        'Last Date',
        'Sub Location',
    ];

    $header = fgetcsv($fh);
    if ($header && isset($header[0])) {
        // strip UTF-8 BOM
        $header[0] = preg_replace('/^\xEF\xBB\xBF/', '', (string)$header[0]);
    }
    if ($header) {
        $header = _asset_trim_trailing_empty_csv_cells($header);
    }
    if (!$header) {
        fclose($fh);
        return ['status' => 'error', 'message' => 'Missing CSV header row'];
    }
    if (count($header) !== count($expected)) {
        fclose($fh);
        return ['status' => 'error', 'message' => 'Invalid CSV header count'];
    }
    for ($i = 0; $i < count($expected); $i++) {
        if (trim((string)$header[$i]) !== $expected[$i]) {
            fclose($fh);
            return ['status' => 'error', 'message' => 'CSV headers do not match expected format'];
        }
    }

    // Locations for this client
    $locations = [];
    if ($st = $GLOBALS['con']->prepare("SELECT locnumber, locname, postcode FROM locations WHERE clientnumber=? AND statuslive=1 ORDER BY locname")) {
        $st->bind_param('i', $clientnumber);
        $st->execute();
        $rs = $st->get_result();
        while ($r = $rs->fetch_assoc()) $locations[] = $r;
        $st->close();
    }

    // Existing sub-locations for this client (active items only)
    $sublocs = [];
    if ($st = $GLOBALS['con']->prepare("SELECT DISTINCT TRIM(subloc) AS subloc FROM itemdetails WHERE clientnumber=? AND statuslive=1 AND TRIM(subloc) <> ''")) {
        $st->bind_param('i', $clientnumber);
        $st->execute();
        $rs = $st->get_result();
        while ($r = $rs->fetch_assoc()) {
            $sl = (string)$r['subloc'];
            if ($sl !== '') $sublocs[$sl] = true;
        }
        $st->close();
    }

    // Codes from tenant dd_plant
    $codes = [];
    if ($qr = $GLOBALS['con']->query("SELECT code, description, frequency FROM dd_plant ORDER BY code")) {
        while ($r = $qr->fetch_assoc()) {
            $r['description_key'] = _asset_normalise_plant_description((string)($r['description'] ?? ''));
            $codes[] = $r;
        }
    }

    // Existing duplicate index for this client – keyed by desc+pn/sn
    $existing = [];
    if ($qe = $GLOBALS['con']->prepare("SELECT `desc`, plantnumber, serialnumber FROM itemdetails WHERE clientnumber=?")) {
        $qe->bind_param('i', $clientnumber);
        $qe->execute();
        $er = $qe->get_result();
        while ($r = $er->fetch_assoc()) {
            $d  = _asset_normalise_plant_description((string)($r['desc'] ?? ''));
            $pn = strtolower(trim((string)($r['plantnumber'] ?? '')));
            $sn = strtolower(trim((string)($r['serialnumber'] ?? '')));

            if ($d === '') continue;

            if ($pn !== '') {
                $existing[$d . '|pn|' . $pn] = true;
            }
            if ($sn !== '') {
                $existing[$d . '|sn|' . $sn] = true;
            }
            if ($pn !== '' && $sn !== '') {
                $existing[$d . '|both|' . $pn . '|' . $sn] = true;
            }
        }
        $qe->close();
    }

    $rows        = [];
    $uploadIndex = []; // also keyed by desc+pn/sn to catch duplicates within the CSV

    while (($row = fgetcsv($fh)) !== false) {
        $row = _asset_trim_trailing_empty_csv_cells($row);
        if (count($row) === 0 || (count($row) === 1 && trim((string)$row[0]) === '')) continue;

        for ($i = 0; $i < count($row); $i++) $row[$i] = trim((string)$row[$i]);

        $rec = [
            'desc'          => $row[0] ?? '',
            'swl'           => $row[1] ?? '',
            'plantnumber'   => $row[2] ?? '',
            'serialnumber'  => $row[3] ?? '',
            'model'         => $row[4] ?? '',
            'dateofmanf'    => $row[5] ?? '',
            'manf'          => $row[6] ?? '',
            'duedate_raw'   => $row[7] ?? '',
            'frequency_raw' => $row[8] ?? '',
            'lastdate_raw'  => $row[9] ?? '',
            'subloc_raw'    => $row[10] ?? '',
        ];
        $rec['desc_key'] = _asset_normalise_plant_description((string)$rec['desc']);

        $err = null;
        if ($rec['desc'] === '') {
            $err = 'Description is required';
        }
        // You said items will always have either a plant or a serial.
        if (!$err && $rec['plantnumber'] === '' && $rec['serialnumber'] === '') {
            $err = 'At least Plant Number or Serial Number is required';
        }

        // Due Date
        $duedate_unix = null;
        if ($rec['duedate_raw'] !== '') {
            $parsed = _asset_parse_date_to_unix($rec['duedate_raw']);
            if ($parsed === null) $err = 'Unrecognised Due Date format';
            else $duedate_unix = $parsed;
        }

        // Last Date (currdate) – parse but we don’t hard-fail if it’s wrong
        $lastdate_unix = null;
        if ($rec['lastdate_raw'] !== '') {
            $parsedLD = _asset_parse_date_to_unix($rec['lastdate_raw']);
            if ($parsedLD !== null) $lastdate_unix = $parsedLD;
        }

        // Frequency
        // If CSV frequency is blank, leave it blank here so the frontend can honour
        // any existing dd_plant frequency for the matching description.
        // Only normalise when an actual override has been supplied.
        $freqRaw = trim((string)($rec['frequency_raw'] ?? ''));

        if ($freqRaw === '') {
            $rec['frequency'] = null;
        } else {
            $freq = (int)$freqRaw;
            if (!in_array($freq, [4, 6, 12, 18, 21], true)) {
                $freq = 12;
            }
            $rec['frequency'] = $freq;
        }

        // Duplicate detection: desc + plant OR desc + serial
        $dup = false;
        if (!$err) {
            $d  = $rec['desc_key'];
            $pn = strtolower($rec['plantnumber']);
            $sn = strtolower($rec['serialnumber']);

            $keys = [];
            if ($pn !== '') $keys[] = $d . '|pn|' . $pn;
            if ($sn !== '') $keys[] = $d . '|sn|' . $sn;
            if ($pn !== '' && $sn !== '') $keys[] = $d . '|both|' . $pn . '|' . $sn;

            foreach ($keys as $k) {
                if (isset($existing[$k]) || isset($uploadIndex[$k])) {
                    $dup = true;
                    break;
                }
            }
            // mark keys for intra-CSV dupes
            foreach ($keys as $k) {
                $uploadIndex[$k] = true;
            }
        }

        $rec['duedate']         = $duedate_unix;
        $rec['duedate_display'] = $rec['duedate_raw'];
        $rec['lastdate_unix']   = $lastdate_unix;
        $rec['lastdate_display'] = $rec['lastdate_raw'];

        if ($err) $rec['_error'] = $err;
        if ($dup) $rec['_duplicate'] = true;

        // Ensure subloc list grows from CSV content too
        $sl = $rec['subloc_raw'];
        if ($sl !== '') $sublocs[$sl] = true;

        $rows[] = $rec;
    }
    fclose($fh);

    // normalise sublocs array into a simple list
    $sublocList = array_keys($sublocs);
    sort($sublocList, SORT_NATURAL | SORT_FLAG_CASE);

    return [
        'status'    => 'ok',
        'rows'      => $rows,
        'locations' => $locations,
        'codes'     => $codes,
        'sublocs'   => $sublocList,
    ];
}


/* remove spreadsheet-exported blank columns beyond the real CSV content */
function _asset_trim_trailing_empty_csv_cells(array $row): array
{
    while (!empty($row) && trim((string)end($row)) === '') {
        array_pop($row);
    }

    return $row;
}

function _asset_normalise_plant_description(string $value): string
{
    $value = html_entity_decode($value, ENT_QUOTES | ENT_HTML5, 'UTF-8');
    $value = str_replace("\xC2\xA0", ' ', $value);
    $value = trim($value);
    $normalised = preg_replace('/\s+/u', ' ', $value);
    if ($normalised === null) {
        $normalised = preg_replace('/\s+/', ' ', $value);
    }

    return strtolower(trim((string)$normalised));
}


/* date parser used by assetUploadCSV */
function _asset_parse_date_to_unix(string $s): ?int
{
    $s = trim($s);
    if ($s === '') return null;

    if (preg_match('~^(\d{1,2})[-/](\d{1,2})[-/](\d{4})$~', $s, $m)) {
        $d  = (int)$m[1];
        $mo = (int)$m[2];
        $y  = (int)$m[3];
        return checkdate($mo, $d, $y) ? strtotime(sprintf('%04d-%02d-%02d', $y, $mo, $d)) : null;
    }
    if (preg_match('~^(\d{4})-(\d{1,2})-(\d{1,2})$~', $s, $m)) {
        $y  = (int)$m[1];
        $mo = (int)$m[2];
        $d  = (int)$m[3];
        return checkdate($mo, $d, $y) ? strtotime(sprintf('%04d-%02d-%02d', $y, $mo, $d)) : null;
    }
    $t = strtotime($s);
    return $t !== false ? $t : null;
}

/**
 * Generate a dd_plant.code based on description:
 * first 2 letters (A–Z) + 3-digit incremental number, e.g. RU001, RU002.
 */
function _asset_generate_dd_plant_code(string $description): string
{
    $db = $GLOBALS['con'];

    $letters = preg_replace('/[^A-Z]/i', '', strtoupper($description));
    if ($letters === '') {
        $letters = 'AA';
    }

    $prefix = substr($letters, 0, 2);
    if ($prefix === '') {
        $prefix = 'AA';
    }

    $like = $prefix . '%';
    $stmt = $db->prepare("SELECT code FROM dd_plant WHERE code LIKE ?");
    $stmt->bind_param('s', $like);
    $stmt->execute();
    $res = $stmt->get_result();

    $maxNum = 0;

    while ($row = $res->fetch_assoc()) {
        $code = (string)($row['code'] ?? '');

        if (preg_match('/^' . preg_quote($prefix, '/') . '(\d+)/', $code, $m)) {
            $num = (int)$m[1];
            if ($num > $maxNum) {
                $maxNum = $num;
            }
        }
    }

    $stmt->close();

    $next = $maxNum + 1;
    return $prefix . str_pad((string)$next, 3, '0', STR_PAD_LEFT);
}

function _asset_find_dd_plant_match(string $description, ?int $frequency = null): ?array
{
    $db = $GLOBALS['con'];
    $descriptionKey = _asset_normalise_plant_description($description);
    if ($descriptionKey === '') {
        return null;
    }

    $stmt = $db->prepare("SELECT code, description, frequency FROM dd_plant");
    if (!$stmt) {
        return null;
    }

    $stmt->execute();
    $res = $stmt->get_result();

    while ($row = $res->fetch_assoc()) {
        if (_asset_normalise_plant_description((string)($row['description'] ?? '')) !== $descriptionKey) {
            continue;
        }

        if ($frequency === null || (int)($row['frequency'] ?? 0) === (int)$frequency) {
            $stmt->close();
            return [
                'code' => (string)($row['code'] ?? ''),
                'description' => (string)($row['description'] ?? ''),
                'frequency' => (int)($row['frequency'] ?? 0),
            ];
        }
    }

    $stmt->close();
    return null;
}


function _asset_resolve_or_create_dd_plant_code(string $description, int $frequency): array
{
    $db = $GLOBALS['con'];

    $description = trim($description);
    $frequency   = (int)$frequency;

    if ($description === '') {
        return ['status' => 'error', 'message' => 'Blank description'];
    }

    if ($frequency <= 0) {
        $frequency = 12;
    }

    // Exact match first: same normalised description + same frequency
    $matchedPlant = _asset_find_dd_plant_match($description, $frequency);
    if ($matchedPlant) {
        return ['status' => 'ok', 'code' => (string)$matchedPlant['code'], 'created' => false];
    }

    // Does this description already exist at another frequency?
    $sameDescriptionExists = _asset_find_dd_plant_match($description, null) !== null;

    // Generate base code using existing style
    $baseCode = _asset_generate_dd_plant_code($description);
    $newCode  = $baseCode;

    // Only add frequency suffix if same description already exists at another frequency
    if ($sameDescriptionExists) {
        $newCode = $baseCode . '-' . $frequency;

        // Ensure even the suffixed code is unique
        $counter = 1;
        while (true) {
            $stmt = $db->prepare("SELECT COUNT(*) AS total FROM dd_plant WHERE code = ?");
            $stmt->bind_param('s', $newCode);
            $stmt->execute();
            $res = $stmt->get_result();
            $row = $res->fetch_assoc();
            $stmt->close();

            if ((int)($row['total'] ?? 0) === 0) {
                break;
            }

            $baseCode = _asset_generate_dd_plant_code($description);
            $newCode  = $baseCode . '-' . $frequency;
            $counter++;

            if ($counter > 1000) {
                return ['status' => 'error', 'message' => 'Unable to generate unique dd_plant code'];
            }
        }
    } else {
        // Ensure plain generated code is unique
        $stmt = $db->prepare("SELECT COUNT(*) AS total FROM dd_plant WHERE code = ?");
        $stmt->bind_param('s', $newCode);
        $stmt->execute();
        $res = $stmt->get_result();
        $row = $res->fetch_assoc();
        $stmt->close();

        if ((int)($row['total'] ?? 0) > 0) {
            return ['status' => 'error', 'message' => 'Generated dd_plant code already exists'];
        }
    }

    $stmt = $db->prepare("INSERT INTO dd_plant (code, description, frequency) VALUES (?, ?, ?)");
    if (!$stmt) {
        return ['status' => 'error', 'message' => 'Failed preparing dd_plant insert'];
    }

    $stmt->bind_param('ssi', $newCode, $description, $frequency);

    if (!$stmt->execute()) {
        $err = $stmt->error;
        $stmt->close();
        return ['status' => 'error', 'message' => 'Failed creating dd_plant row: ' . $err];
    }

    $stmt->close();

    return ['status' => 'ok', 'code' => $newCode, 'created' => true];
}

function assetCommitImport(int $clientnumber, string $rowsJson): array
{
    if ($clientnumber <= 0) return ['status' => 'error', 'message' => 'Invalid clientnumber'];
    if (!isset($GLOBALS['con']) || !($GLOBALS['con'] instanceof mysqli))
        return ['status' => 'error', 'message' => 'DB connection unavailable'];

    $rows = json_decode($rowsJson, true);
    if (!is_array($rows)) return ['status' => 'error', 'message' => 'Invalid payload'];

    $now      = time();
    $inserted = 0;
    $skipped  = 0;
    $errors   = [];

    // Preload existing desc+plant/serial pairs for this client
    $existing = [];
    if ($st = $GLOBALS['con']->prepare("SELECT `desc`, plantnumber, serialnumber FROM itemdetails WHERE clientnumber=?")) {
        $st->bind_param('i', $clientnumber);
        $st->execute();
        $rs = $st->get_result();
        while ($r = $rs->fetch_assoc()) {
            $d  = _asset_normalise_plant_description((string)($r['desc'] ?? ''));
            $pn = strtolower(trim((string)($r['plantnumber'] ?? '')));
            $sn = strtolower(trim((string)($r['serialnumber'] ?? '')));

            if ($d === '') continue;

            if ($pn !== '') {
                $existing[$d . '|pn|' . $pn] = true;
            }
            if ($sn !== '') {
                $existing[$d . '|sn|' . $sn] = true;
            }
            if ($pn !== '' && $sn !== '') {
                $existing[$d . '|both|' . $pn . '|' . $sn] = true;
            }
        }
        $st->close();
    }

    // insert statement – includes currdate, cont_freq, subloc
    $sql = "INSERT INTO itemdetails
        (locnumber, clientnumber, code, `desc`, swl, plantnumber, serialnumber, model,
         dateofmanf, manf, duedate, currdate, cont_freq, subloc, statuslive,
         ancillarynumber, reptype, linked, created, archived)
        VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?, NULL)";

    $stmt = $GLOBALS['con']->prepare($sql);
    if (!$stmt) return ['status' => 'error', 'message' => 'DB prepare failed'];

    foreach ($rows as $i => $r) {
        $locnumber    = (int)($r['locnumber'] ?? 0);
        $code         = trim((string)($r['code'] ?? ''));
        $desc         = trim((string)($r['desc'] ?? ''));
        $swl          = (string)($r['swl'] ?? '');
        $plantnumber  = trim((string)($r['plantnumber'] ?? ''));
        $serialnumber = trim((string)($r['serialnumber'] ?? ''));
        $model        = (string)($r['model'] ?? '');
        $dateofmanf   = (string)($r['dateofmanf'] ?? '');
        $manf         = (string)($r['manf'] ?? '');
        $duedate      = isset($r['duedate']) && $r['duedate'] !== '' ? (int)$r['duedate'] : null;
        $currdate     = isset($r['currdate']) && $r['currdate'] !== '' ? (int)$r['currdate'] : null;
        $freq         = (int)($r['frequency'] ?? 12);
        $subloc       = trim((string)($r['subloc'] ?? ''));
        $statuslive   = 1;
        $ancillary    = '';
        $reptype      = '500';
        $linked       = '';
        $created      = $now;

        if (!$locnumber || $desc === '') {
            $errors[] = "Row " . ($i + 1) . ": missing required fields";
            continue;
        }

        // Hard idempotency using desc+plant OR desc+serial
        $dKey = _asset_normalise_plant_description($desc);
        $pn   = strtolower($plantnumber);
        $sn   = strtolower($serialnumber);

        $dupKeys = [];
        if ($pn !== '') $dupKeys[] = $dKey . '|pn|' . $pn;
        if ($sn !== '') $dupKeys[] = $dKey . '|sn|' . $sn;
        if ($pn !== '' && $sn !== '') $dupKeys[] = $dKey . '|both|' . $pn . '|' . $sn;

        $isDup = false;
        foreach ($dupKeys as $k) {
            if (isset($existing[$k])) {
                $isDup = true;
                break;
            }
        }
        if ($isDup) {
            $skipped++;
            continue;
        }

        // Resolve/create dd_plant code for this description + frequency
        if ($code === '') {
            $codeResult = _asset_resolve_or_create_dd_plant_code($desc, $freq);

            if (($codeResult['status'] ?? 'error') !== 'ok') {
                $errors[] = "Row " . ($i + 1) . ": " . ($codeResult['message'] ?? 'Unable to resolve plant code');
                continue;
            }

            $code = (string)$codeResult['code'];
        } else {
            // Even if a code was posted, make sure the matching dd_plant row exists
            $stmtCheck = $GLOBALS['con']->prepare("SELECT COUNT(*) AS total FROM dd_plant WHERE code = ?");
            $stmtCheck->bind_param('s', $code);
            $stmtCheck->execute();
            $rsCheck = $stmtCheck->get_result();
            $rowCheck = $rsCheck->fetch_assoc();
            $stmtCheck->close();

            if ((int)($rowCheck['total'] ?? 0) === 0) {
                $stmtPlant = $GLOBALS['con']->prepare("INSERT INTO dd_plant (code, description, frequency) VALUES (?, ?, ?)");
                if (!$stmtPlant) {
                    $errors[] = "Row " . ($i + 1) . ": failed preparing dd_plant insert";
                    continue;
                }

                $stmtPlant->bind_param('ssi', $code, $desc, $freq);

                if (!$stmtPlant->execute()) {
                    $errors[] = "Row " . ($i + 1) . ": failed creating dd_plant row - " . $stmtPlant->error;
                    $stmtPlant->close();
                    continue;
                }

                $stmtPlant->close();
            }
        }

        // 19 params → 19 type chars
        // i: locnumber
        // i: clientnumber
        // s: code
        // s: desc
        // s: swl
        // s: plantnumber
        // s: serialnumber
        // s: model
        // s: dateofmanf
        // s: manf
        // s: duedateStr
        // s: currdateStr
        // i: freq (cont_freq)
        // s: subloc
        // i: statuslive
        // s: ancillary
        // s: reptype
        // s: linked
        // i: created
        $types  = 'iissssssssiiisisssi';
        $params = [
            $locnumber,
            $clientnumber,
            $code,
            $desc,
            $swl,
            $plantnumber,
            $serialnumber,
            $model,
            $dateofmanf,
            $manf,
            $duedate,
            $currdate,
            $freq,
            $subloc,
            $statuslive,
            $ancillary,
            $reptype,
            $linked,
            $created
        ];

        $refs   = [];
        $refs[] = &$types;
        foreach ($params as $k => $v) {
            $refs[] = &$params[$k];
        }

        if (!call_user_func_array([$stmt, 'bind_param'], $refs) || !$stmt->execute()) {
            $errors[] = "Row " . ($i + 1) . ": " . $stmt->error;
        } else {
            plantChangeLogAdd((int)$GLOBALS['con']->insert_id, 'asset_csv_import');
            $inserted++;
            // add to existing set so subsequent rows in same request also skip
            foreach ($dupKeys as $k) {
                $existing[$k] = true;
            }
        }
    }
    $stmt->close();

    if ($inserted > 0 && empty($errors)) {
        return ['status' => 'ok', 'inserted' => $inserted, 'skipped' => $skipped];
    }
    if ($inserted > 0) {
        return ['status' => 'ok', 'inserted' => $inserted, 'skipped' => $skipped, 'errors' => $errors];
    }
    return ['status' => 'error', 'message' => 'No rows imported', 'skipped' => $skipped, 'errors' => $errors];
}

function assetMobileInsert(int $clientnumber, array $payload): array
{
    if ($clientnumber <= 0) {
        return ['status' => 'error', 'message' => 'Invalid clientnumber'];
    }
    if (!isset($GLOBALS['con']) || !($GLOBALS['con'] instanceof mysqli)) {
        return ['status' => 'error', 'message' => 'DB connection unavailable'];
    }

    $locnumber = (int)($payload['locnumber'] ?? 0);
    $desc = trim((string)($payload['description'] ?? $payload['desc'] ?? ''));
    if ($locnumber <= 0 || $desc === '') {
        return ['status' => 'error', 'message' => 'Missing site or description'];
    }

    $freq = (int)($payload['frequency'] ?? $payload['cont_freq'] ?? 12);
    if ($freq <= 0) {
        $freq = 12;
    }

    $code = trim((string)($payload['code'] ?? ''));
    if ($code === '') {
        $codeResult = _asset_resolve_or_create_dd_plant_code($desc, $freq);
        if (($codeResult['status'] ?? 'error') !== 'ok') {
            return ['status' => 'error', 'message' => ($codeResult['message'] ?? 'Unable to resolve plant code')];
        }
        $code = (string)$codeResult['code'];
    } else {
        $stmtCheck = $GLOBALS['con']->prepare("SELECT COUNT(*) AS total FROM dd_plant WHERE code = ?");
        if ($stmtCheck) {
            $stmtCheck->bind_param('s', $code);
            $stmtCheck->execute();
            $rsCheck = $stmtCheck->get_result();
            $rowCheck = $rsCheck->fetch_assoc();
            $stmtCheck->close();

            if ((int)($rowCheck['total'] ?? 0) === 0) {
                $stmtPlant = $GLOBALS['con']->prepare("INSERT INTO dd_plant (code, description, frequency) VALUES (?, ?, ?)");
                if ($stmtPlant) {
                    $stmtPlant->bind_param('ssi', $code, $desc, $freq);
                    $stmtPlant->execute();
                    $stmtPlant->close();
                }
            }
        }
    }

    $sql = "INSERT INTO itemdetails
        (locnumber, clientnumber, code, `desc`, swl, plantnumber, serialnumber, model,
         dateofmanf, manf, duedate, currdate, cont_freq, subloc, statuslive,
         ancillarynumber, reptype, linked, created, archived)
        VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?, NULL)";

    $stmt = $GLOBALS['con']->prepare($sql);
    if (!$stmt) {
        return ['status' => 'error', 'message' => 'DB prepare failed'];
    }

    $swl = (string)($payload['swl'] ?? '');
    $plantnumber = trim((string)($payload['plantnumber'] ?? ''));
    $serialnumber = trim((string)($payload['serialnumber'] ?? ''));
    $model = (string)($payload['model'] ?? '');
    $dateofmanf = (string)($payload['year'] ?? $payload['dateofmanf'] ?? '');
    $manf = (string)($payload['manufacturer'] ?? $payload['manf'] ?? '');
    $duedate = isset($payload['duedate']) && $payload['duedate'] !== '' ? (int)$payload['duedate'] : null;
    $currdate = isset($payload['currdate']) && $payload['currdate'] !== '' ? (int)$payload['currdate'] : null;
    $subloc = trim((string)($payload['subloc'] ?? ''));
    $statuslive = 1;
    $ancillary = (string)($payload['ancillarynumber'] ?? '');
    $reptype = (string)($payload['reptype'] ?? '500');
    $linked = '';
    $created = time();

    $types = 'iissssssssiiisisssi';
    $params = [
        $locnumber,
        $clientnumber,
        $code,
        $desc,
        $swl,
        $plantnumber,
        $serialnumber,
        $model,
        $dateofmanf,
        $manf,
        $duedate,
        $currdate,
        $freq,
        $subloc,
        $statuslive,
        $ancillary,
        $reptype,
        $linked,
        $created,
    ];

    $refs = [&$types];
    foreach ($params as $key => $value) {
        $refs[] = &$params[$key];
    }

    if (!call_user_func_array([$stmt, 'bind_param'], $refs) || !$stmt->execute()) {
        $error = $stmt->error ?: 'Item insert failed';
        $stmt->close();
        return ['status' => 'error', 'message' => $error];
    }

    $itemnumber = (int)$GLOBALS['con']->insert_id;
    $stmt->close();
    plantChangeLogAdd($itemnumber, 'asset_mobile_insert');

    if ($itemnumber <= 0) {
        return ['status' => 'error', 'message' => 'Item insert did not return an item number'];
    }

    $stmtVerify = $GLOBALS['con']->prepare("SELECT `itemnumber` FROM `itemdetails` WHERE `itemnumber`=? AND `clientnumber`=? LIMIT 1");
    if (!$stmtVerify) {
        return ['status' => 'error', 'message' => 'Item insert verification unavailable'];
    }
    $stmtVerify->bind_param('ii', $itemnumber, $clientnumber);
    $stmtVerify->execute();
    $verifyResult = $stmtVerify->get_result();
    $stmtVerify->close();
    if (!$verifyResult || mysqli_num_rows($verifyResult) === 0) {
        return ['status' => 'error', 'message' => 'Item insert was not verified'];
    }

    if (!empty($payload['itemnotes'])) {
        $notes = trim((string)$payload['itemnotes']);
        $stmtNotes = $GLOBALS['con']->prepare("UPDATE `itemdetails` SET `itemnotes`=? WHERE `itemnumber`=?");
        if ($stmtNotes) {
            $stmtNotes->bind_param('si', $notes, $itemnumber);
            $stmtNotes->execute();
            $stmtNotes->close();
        }
    }

    return ['status' => 'ok', 'itemnumber' => $itemnumber, 'locnumber' => $locnumber];
}
