<?php //Generator repeat
// ==== expects: $parts from assembler (no re-includes here) ====
// keys: wrapper_Start, wrapper_End, headerTemplate, contractHeader, inst, body, footerTemplate, orientation, customImages

$tenantBase = '../../../' . TENANT_URL;
$ENGINES_DIR = $tenantBase . '/engines/pdf_structure';

// Ensure output dir
$reportsDir = $tenantBase . '/output/reports/' . ($_REQUEST['clientnumber'] ?? '');
if (!is_dir($reportsDir)) {
    @mkdir($reportsDir, 0777, true);
}

// QR
require "../../packages/phpqrcode/qrlib.php";
$qrPath = $tenantBase . '/images/repQR.png';
QRcode::png(getCompanyDetails('web') . '/preview.php?repnumber=' . ($_REQUEST['repnumber'] ?? ''), $qrPath, 'L', 4, 2);

// Resolve header/footer templates (they are always NAME.php)
$headerHtml = '';
$footerHtml = '';
if (!empty($parts['headerTemplate'])) {
    $p = $ENGINES_DIR . '/' . $parts['headerTemplate'];
    if (is_file($p)) $headerHtml = file_get_contents($p);
}
if (!empty($parts['footerTemplate'])) {
    $p = $ENGINES_DIR . '/' . $parts['footerTemplate'];
    if (is_file($p)) $footerHtml = file_get_contents($p);
}


// ----- Contractor context + precompute address/logo + AF suppression flag -----
$clientId = isset($_REQUEST['clientnumber']) ? (int)$_REQUEST['clientnumber'] : 0;
$isContract = false;
$contract = null;
$contractAddressHtml = '';
$contractLogoHtml = '';

if ($clientId > 0) {
    // single fetch: clientMode + contractor row
    $sql = "SELECT c.clientMode,
                   cc.id,
                   cc.cont_company, cc.cont_company_short,
                   cc.cont_address1, cc.cont_address2, cc.cont_town, cc.cont_county, cc.cont_post,
                   cc.cont_tel, cc.cont_main_email, cc.cont_finance_email, cc.cont_web
            FROM clientdetails c
            LEFT JOIN contract_companies cc ON cc.client_id = c.clientnumber
            WHERE c.clientnumber = ? LIMIT 1";
    $st = $GLOBALS['con']->prepare($sql);
    $st->bind_param('i', $clientId);
    $st->execute();
    $res = $st->get_result();
    if ($row = $res->fetch_assoc()) {
        $isContract = ((int)$row['clientMode'] === 1) && !empty($row['id']);
        if ($isContract) {
            $contract = $row;

            // address (single line) with bold company
            $companyName = '';
            if (!empty($contract['cont_company'])) {
                $companyName = '<strong>' . htmlspecialchars($contract['cont_company'], ENT_QUOTES, 'UTF-8') . '</strong>';
            } elseif (!empty($contract['cont_company_short'])) {
                $companyName = '<strong>' . htmlspecialchars($contract['cont_company_short'], ENT_QUOTES, 'UTF-8') . '</strong>';
            }

            $addrParts = array(
                $companyName,
                !empty($contract['cont_address1']) ? $contract['cont_address1'] : '',
                !empty($contract['cont_address2']) ? $contract['cont_address2'] : '',
                trim((!empty($contract['cont_town']) ? $contract['cont_town'] : '') . ' ' . (!empty($contract['cont_post']) ? $contract['cont_post'] : '')),
                !empty($contract['cont_county']) ? $contract['cont_county'] : '',
            );

            $filtered = array();
            foreach ($addrParts as $p) {
                if ($p !== '' && $p !== null) {
                    // company is already escaped+wrapped
                    if ($p === $companyName) $filtered[] = $p;
                    else $filtered[] = htmlspecialchars($p, ENT_QUOTES, 'UTF-8');
                }
            }
            $contractAddressHtml = implode(', ', $filtered);

            // contractor logo
            $cLogoPath = $tenantBase . '/images/contractorCompany/' . (int)$contract['id'] . '.jpg';
            if (is_file($cLogoPath)) {
                $contractLogoHtml = '<img src="' . $cLogoPath . '" height="70px" />';
            }
        }
    }
    $st->close();
}

// AF images (optional exclude per customImages[form])
$form = $_REQUEST['form'] ?? '';
$excludeImage = 0;
if (!empty($parts['customImages']) && is_array($parts['customImages']) && isset($parts['customImages'][$form])) {
    $excludeImage = (int)$parts['customImages'][$form];
}
for ($i = 1; $i <= 6; $i++) {
    if ($isContract) { // hide all AF images in contractor mode
        $headerHtml = str_replace("[AF{$i}]", '', $headerHtml);
        continue;
    }
    $img = $tenantBase . "/images/company/afl_{$i}.jpg";
    if ($excludeImage === $i) {
        $headerHtml = str_replace("[AF{$i}]", '', $headerHtml);
        continue;
    }
    $headerHtml = str_replace("[AF{$i}]", file_exists($img) ? '<td><img src="' . $img . '" height="40px" /></td>' : '', $headerHtml);
}

// Data for swaps
$sdata = explode("|", getSurveyorDetails($_REQUEST['repnumber'] ?? '', 'REPDATA'));
$rdata = explode("|", getItemReportDetails($_REQUEST['repnumber'] ?? '', 'REPDATA'));

// Surveyor signature to base64
$base64ImageSrc = '';
$signPath = $tenantBase . '/images/signatures/' . ($sdata[2] ?? '') . '.jpg';
if (file_exists($signPath)) $base64ImageSrc = 'data:image/jpeg;base64,' . base64_encode(file_get_contents($signPath));

// Styles (default generic style.php; swap if you later add per-type)
$styleHtml = '';
$stylePath = $ENGINES_DIR . '/style.php';
if (is_file($stylePath)) $styleHtml = file_get_contents($stylePath);

// ---------- BUILD CONTENT FOR SETTER MODE ----------
// ---------- BUILD CONTENT FOR SETTER MODE ----------
$footer = $footerHtml;

// Contract header will repeat on every page
$contractHeaderExtras = '';
if (!empty($parts['contractHeader'])) {
    $contractHeaderExtras .= $parts['contractHeader'];
}

// Header fragment + contract header (repeated)
$header = $headerHtml . $contractHeaderExtras;

// Body HTML (wrapper + inst once + body + wrapper end)
$body  = ($parts['wrapper_Start'] ?? '');
if (!empty($parts['inst'])) {
    $body .= $parts['inst']; // inst appears only once
}
$body .= ($parts['body'] ?? '');


// === Photos at the end (imageMode=1) ===
if (!empty($_REQUEST['imageMode']) && $_REQUEST['imageMode'] === "1") {
    @file_put_contents(__DIR__ . "/imagePath.txt", "AFTER CALL imageMode=" . $_REQUEST['imageMode'] . '|' . ($cx['itemnumber'] ?? '') . PHP_EOL, FILE_APPEND);

    // Collect up to 6 images named {itemnumber}_1..6.jpg
    $imagePaths = [];
    for ($i = 1; $i <= 6; $i++) {
        $imgPath = '../../../' . TENANT_URL . '/images/report_images/' . ($cx['itemnumber'] ?? '') . '_' . $i . '.jpg';
        if (file_exists($imgPath)) $imagePaths[] = $imgPath;
    }
    $imgCount = count($imagePaths);
    if ($imgCount === 0) return;

    // --- layout (decide columns + target height mm once) ---
    if ($imgCount === 1) {
        $cols = 1;
        $maxH_mm = 230;
        $tableBefore = true;
    } elseif ($imgCount === 2) {
        $cols = 2;
        $maxH_mm = 200;
        $tableBefore = true;
    } elseif ($imgCount === 3) {
        $cols = 3;
        $maxH_mm = 160;
        $tableBefore = true;
    } elseif ($imgCount === 4) {
        $cols = 2;
        $maxH_mm = 120;
        $tableBefore = true;
    } else { // 5-6
        $cols = 3;
        $maxH_mm = 75;
        $tableBefore = true;
    }
    $cellWidth = floor(100 / max(1, $cols));

    // --- fast rounded-corner processor with caching + downscale ---
    if (!function_exists('enrep_process_photo_fast')) {
        function enrep_process_photo_fast(string $src, int $radius = 24, int $maxH_px = 600): string
        {
            if (!file_exists($src)) return $src;

            $tenantBase = '../../../' . TENANT_URL;
            $cacheDir   = $tenantBase . '/images/cache';
            if (!is_dir($cacheDir)) @mkdir($cacheDir, 0777, true);

            $mtime = filemtime($src) ?: 0;
            // include "|square" in cache key so old non-square versions don't collide
            $hash  = md5($src . '|' . $mtime . '|r' . $radius . '|h' . $maxH_px . '|square');
            $dest  = $cacheDir . "/$hash.png";
            if (file_exists($dest)) return $dest;

            // Prefer Imagick
            if (extension_loaded('imagick')) {
                try {
                    $im = new Imagick($src);
                    $im->setImageColorspace(Imagick::COLORSPACE_RGB);
                    $im->setImageAlphaChannel(Imagick::ALPHACHANNEL_SET);

                    // ---- square crop (center) ----
                    $w = $im->getImageWidth();
                    $h = $im->getImageHeight();
                    $side = min($w, $h);
                    $x = (int) floor(($w - $side) / 2);
                    $y = (int) floor(($h - $side) / 2);
                    $im->cropImage($side, $side, $x, $y);
                    $im->setImagePage(0, 0, 0, 0); // reset virtual canvas

                    // ---- resize to target square ----
                    if ($side !== $maxH_px) {
                        $im->resizeImage($maxH_px, $maxH_px, Imagick::FILTER_LANCZOS, 1, true);
                    }

                    // ---- rounded mask ----
                    $w = $im->getImageWidth();
                    $h = $im->getImageHeight();
                    $r = max(2, min($radius, intdiv(min($w, $h), 2)));

                    $mask = new Imagick();
                    $mask->newImage($w, $h, 'transparent', 'png');
                    $draw = new ImagickDraw();
                    $draw->setFillColor('white');
                    $draw->roundRectangle(0, 0, $w - 1, $h - 1, $r, $r);
                    $mask->drawImage($draw);

                    $im->setImageFormat('png');
                    $im->compositeImage($mask, Imagick::COMPOSITE_DSTIN, 0, 0);

                    $im->writeImage($dest);
                    $im->clear();
                    $im->destroy();
                    $mask->clear();
                    $mask->destroy();

                    return $dest;
                } catch (Throwable $e) {
                    // fall through to GD
                }
            }

            // ---- GD fallback ----
            $ext = strtolower(pathinfo($src, PATHINFO_EXTENSION));
            if ($ext === 'png') $srcIm = @imagecreatefrompng($src);
            else $srcIm = @imagecreatefromjpeg($src);
            if (!$srcIm) return $src;

            $sw = imagesx($srcIm);
            $sh = imagesy($srcIm);
            $side = min($sw, $sh);
            $srcX = (int) floor(($sw - $side) / 2);
            $srcY = (int) floor(($sh - $side) / 2);

            // square crop
            $squareIm = imagecreatetruecolor($side, $side);
            imagecopy($squareIm, $srcIm, 0, 0, $srcX, $srcY, $side, $side);
            imagedestroy($srcIm);

            // resize to target square
            $tw = $maxH_px;
            $th = $maxH_px;
            $im = imagecreatetruecolor($tw, $th);
            imagealphablending($im, false);
            imagesavealpha($im, true);
            $transparent = imagecolorallocatealpha($im, 0, 0, 0, 127);
            imagefill($im, 0, 0, $transparent);
            imagecopyresampled($im, $squareIm, 0, 0, 0, 0, $tw, $th, $side, $side);
            imagedestroy($squareIm);

            // rounded mask
            $mask = imagecreatetruecolor($tw, $th);
            imagealphablending($mask, false);
            imagesavealpha($mask, true);
            imagefill($mask, 0, 0, $transparent);
            $white = imagecolorallocatealpha($mask, 255, 255, 255, 0);
            enrep_gd_rounded_rect($mask, 0, 0, $tw - 1, $th - 1, min($radius, intdiv(min($tw, $th), 2)), $white);

            // apply mask (outside -> transparent)
            for ($y = 0; $y < $th; $y++) {
                for ($x = 0; $x < $tw; $x++) {
                    $m = imagecolorsforindex($mask, imagecolorat($mask, $x, $y));
                    if ($m['alpha'] >= 100) {
                        imagesetpixel($im, $x, $y, $transparent);
                    }
                }
            }
            imagedestroy($mask);

            imagepng($im, $dest, 6);
            imagedestroy($im);

            return $dest;
        }


        function enrep_gd_rounded_rect($img, $x1, $y1, $x2, $y2, $radius, $color)
        {
            $w = $x2 - $x1 + 1;
            $h = $y2 - $y1 + 1;
            $r = max(0, min($radius, min($w, $h) >> 1));
            imagefilledrectangle($img, $x1 + $r, $y1, $x2 - $r, $y2, $color);
            imagefilledrectangle($img, $x1, $y1 + $r, $x2, $y2 - $r, $color);
            imagefilledellipse($img, $x1 + $r, $y1 + $r, 2 * $r, 2 * $r, $color);
            imagefilledellipse($img, $x2 - $r, $y1 + $r, 2 * $r, 2 * $r, $color);
            imagefilledellipse($img, $x1 + $r, $y2 - $r, 2 * $r, 2 * $r, $color);
            imagefilledellipse($img, $x2 - $r, $y2 - $r, 2 * $r, 2 * $r, $color);
        }
    }

    // px per mm (approx mPDF CSS pixel ratio)
    $pxPerMm = 96 / 25.4; // ≈ 3.7795
    $maxH_px = (int)round($maxH_mm * $pxPerMm);

    // Process + cache to display paths
    $displayPaths = [];
    foreach ($imagePaths as $p) {
        $displayPaths[] = enrep_process_photo_fast($p, 24, $maxH_px); // radius 24, target height in px
    }

    // Render
    $body .= '<div style="page-break-before: always;"></div>';
    if ($imgCount === 1) {
        $body .= '
            <table width="100%" cellspacing="0" cellpadding="0" style="table-layout:fixed;border-collapse:collapse;page-break-inside:avoid;">
                <tr>
                    <td align="center" style="padding:5mm;">
                       <img src="' . $displayPaths[0] . '" style="max-width:180mm; max-height:' . $maxH_mm . 'mm;">
                    </td>
                </tr>
            </table>';
    } else {
        $body .= '<table width="100%" cellspacing="0" cellpadding="0" style="table-layout:fixed;border-collapse:separate;border-spacing:4mm;page-break-inside:avoid;">';
        for ($i = 0; $i < $imgCount; $i++) {
            if ($i % $cols === 0) $body .= '<tr style="page-break-inside:avoid;">';
            $body .= '
                <td align="center" style="width:' . $cellWidth . '%;vertical-align:top;padding:0;page-break-inside:avoid;">
                    <img src="' . $displayPaths[$i] . '" style="width:100%; height:auto; max-height:' . $maxH_mm . 'mm;">
                </td>';
            if (($i % $cols === $cols - 1) || ($i === $imgCount - 1)) {
                $remaining = ($cols - 1) - ($i % $cols);
                if ($i === $imgCount - 1 && $remaining > 0) {
                    for ($f = 0; $f < $remaining; $f++) {
                        $body .= '<td style="width:' . $cellWidth . '%">&nbsp;</td>';
                    }
                }
                $body .= '</tr>';
            }
        }
        $body .= '</table>';
    }
}



$body .= ($parts['wrapper_End'] ?? '');


// precompute address + logo
$contractAddressHtml = '';
$contractLogoHtml = '';
if ($contract) {
    $companyName = '';
    if (!empty($contract['cont_company'])) {
        $companyName = '<strong>' . htmlspecialchars($contract['cont_company'], ENT_QUOTES, 'UTF-8') . '</strong>';
    } elseif (!empty($contract['cont_company_short'])) {
        $companyName = '<strong>' . htmlspecialchars($contract['cont_company_short'], ENT_QUOTES, 'UTF-8') . '</strong>';
    }

    $addrParts = array(
        $companyName,
        isset($contract['cont_address1']) ? $contract['cont_address1'] : '',
        isset($contract['cont_address2']) ? $contract['cont_address2'] : '',
        trim((isset($contract['cont_town']) ? $contract['cont_town'] : '') . ' ' . (isset($contract['cont_post']) ? $contract['cont_post'] : '')),
        isset($contract['cont_county']) ? $contract['cont_county'] : '',
    );

    // remove empties
    $filtered = array();
    foreach ($addrParts as $p) {
        if ($p !== '' && $p !== null) {
            // already escaped company above
            if ($p === $companyName) {
                $filtered[] = $p;
            } else {
                $filtered[] = htmlspecialchars($p, ENT_QUOTES, 'UTF-8');
            }
        }
    }
    $contractAddressHtml = implode(', ', $filtered);

    $cLogoPath = $tenantBase . '/images/contractorCompany/' . $contract['id'] . '.jpg';
    if (is_file($cLogoPath)) {
        $contractLogoHtml = '<img src="' . $cLogoPath . '" height="70px" />';
    }
}


// Common replacements (apply to header, footer, and body)
$repl = [
    '[SURVEYOR_NAME]'      => $sdata[0] ?? '',
    '[SURVEYOR_QUAL]'      => $sdata[1] ?? '',
    '[SURVEYOR_SIGNITURE]' => $base64ImageSrc,
    '[GARY_QUAL]'          => 'IEng MSOE MIPlantE MBES',
    '[GARY_SIGNITURE]'     => '2',
    '[REPNO]'              => $rdata[0] ?? '',
    '[EXAM_DATE]'          => $rdata[1] ?? '',
    '[EXAM_PREVDATE]'      => $rdata[2] ?? '',
    '[EXAM_NEXTDATE]'      => $rdata[3] ?? '',
    '[REPORT_DATE]'        => date('d-m-Y'),
    '[REP]'                => $_REQUEST['repnumber'] ?? '',
    '[ITE]'                => $cx['itemnumber'] ?? '',
    '[ADDRESS]'     => ($isContract && $contractAddressHtml !== '') ? $contractAddressHtml : getCompanyDetails('addressLong'),
    '[CONTACT]'            => getCompanyDetails('contact'),
    '[TEL]'                => getCompanyDetails('tel'),
    '[REPORT_PATH]'        => getCompanyDetails('web'),
    '[QR]'                 => '<td><img src="' . $qrPath . '" height="40px"></td>',
];

// Logos
$companyLogoPath = $tenantBase . '/images/company/logo.jpg';
$repl['[LGO]'] = ($isContract && $contractLogoHtml !== '')
    ? $contractLogoHtml
    : (file_exists($companyLogoPath) ? '<img src="' . $companyLogoPath . '" height="70px" />' : '');
$repl['[CL1]'] = file_exists($clientLogo) ? '<td align="center"><img src="' . $clientLogo . '" height="70px" /></td>' : '';

// Apply replacements to all pieces
$header = str_replace(array_keys($repl), array_values($repl), $header);
$footer = str_replace(array_keys($repl), array_values($repl), $footer);
$body   = str_replace(array_keys($repl), array_values($repl), $body);

// ---------- FILE DEST ----------
if (($_REQUEST['mode'] ?? '') === "preview") {
    $filestore = $tenantBase . '/output/reports/' . ($_REQUEST['clientnumber'] ?? '') . '/preview.pdf';
} else {
    if (($_REQUEST['mode'] ?? '') === "hse") {
        $filestore = $tenantBase . '/output/reports/' . ($_REQUEST['clientnumber'] ?? '') . '/' . ($_REQUEST['repnumber'] ?? '') . '_' . ($_REQUEST['items'] ?? '') . '_HSE.pdf';
    } else {
        $filestore = $tenantBase . '/output/reports/' . ($_REQUEST['clientnumber'] ?? '') . '/' . ($_REQUEST['repnumber'] ?? '') . '_' . ($_REQUEST['items'] ?? '') . '.pdf';
    }
}

// ---------- mPDF ----------
require_once '../../packages/mpd/vendor/autoload.php';
$orientation = $parts['orientation'] ?? 'P';

$mpdf = new \Mpdf\Mpdf([
    'mode' => 'utf-8',
    'format' => 'A4',
    'orientation' => $orientation,
    'margin_top' => 30,
    'margin_left' => 10,
    'margin_right' => 10,
    'margin_bottom' => 6,
    'setAutoTopMargin' => 'stretch',
    'setAutoBottomMargin' => 'stretch',
]);

$mpdf->shrink_tables_to_fit = 1;

// Load CSS so it applies to header/footer AND body
if (!empty($styleHtml)) {
    $mpdf->WriteHTML($styleHtml, \Mpdf\HTMLParserMode::HEADER_CSS);
}

// Encode & set header/footer for odd+even
$header = mb_convert_encoding($header, 'UTF-8', 'UTF-8');
$footer = mb_convert_encoding($footer, 'UTF-8', 'UTF-8');
$mpdf->SetHTMLHeader($header, 'O');
$mpdf->SetHTMLHeader($header, 'E');
$mpdf->SetHTMLFooter($footer, 'O');
$mpdf->SetHTMLFooter($footer, 'E');

// Write body
$body = mb_convert_encoding($body, 'UTF-8', 'UTF-8');
$mpdf->WriteHTML($body);

// Output
$mpdf->Output($filestore);