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

if (session_status() === PHP_SESSION_NONE) {
    session_start();
}

function dc_db() {
    static $pdo = null;
    if ($pdo instanceof PDO) {
        return $pdo;
    }

    $dsn = 'mysql:host=' . DC_DB_HOST . ';dbname=' . DC_DB_NAME . ';charset=' . DC_DB_CHARSET;
    $pdo = new PDO($dsn, DC_DB_USER, DC_DB_PASS, array(
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    ));
    dc_ensure_v2_schema($pdo);
    return $pdo;
}

function dc_ensure_v2_schema($pdo) {
    static $done = false;
    if ($done) {
        return;
    }
    $done = true;
    try {
        $stmt = $pdo->query("SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'door_cert_doors' AND COLUMN_NAME = 'po_number'");
        if ((int)$stmt->fetchColumn() === 0) {
            $pdo->exec('ALTER TABLE door_cert_doors ADD COLUMN po_number VARCHAR(80) DEFAULT NULL AFTER door_number');
        }
        $pdo->exec("CREATE TABLE IF NOT EXISTS door_cert_standards (
            id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
            name VARCHAR(255) NOT NULL UNIQUE,
            is_active TINYINT(1) NOT NULL DEFAULT 1,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
        $countStmt = $pdo->query('SELECT COUNT(*) FROM door_cert_standards');
        if ((int)$countStmt->fetchColumn() === 0) {
            $seed = array(
                'UL-10C, NFPA-252 & B.S 476 STANDARD',
                'UL-10C, NFPA-252, FM 4100 & B.S 476 STANDARD'
            );
            $insert = $pdo->prepare('INSERT IGNORE INTO door_cert_standards (name, is_active) VALUES (?, 1)');
            foreach ($seed as $name) {
                $insert->execute(array($name));
            }
        }
    } catch (Exception $e) {
    }
}

function dc_h($value) {
    return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
}

function dc_base_url() {
    if (defined('DC_BASE_URL') && DC_BASE_URL !== '') {
        return rtrim(DC_BASE_URL, '/');
    }
    $https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443);
    $scheme = $https ? 'https' : 'http';
    $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
    $dir = rtrim(str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'])), '/');
    if (substr($dir, -6) === '/admin') {
        $dir = substr($dir, 0, -6);
    }
    return $scheme . '://' . $host . $dir;
}

function dc_url($path) {
    return dc_base_url() . '/' . ltrim($path, '/');
}

function dc_redirect($path) {
    header('Location: ' . dc_url($path));
    exit;
}

function dc_flash($type = null, $message = null) {
    if ($type !== null && $message !== null) {
        $_SESSION['dc_flash'] = array($type, $message);
        return null;
    }
    if (empty($_SESSION['dc_flash'])) {
        return '';
    }
    $flash = $_SESSION['dc_flash'];
    unset($_SESSION['dc_flash']);
    return '<div class="dc-alert ' . dc_h($flash[0]) . '">' . dc_h($flash[1]) . '</div>';
}

function dc_csrf_token() {
    if (empty($_SESSION['dc_csrf'])) {
        $_SESSION['dc_csrf'] = bin2hex(random_bytes(32));
    }
    return $_SESSION['dc_csrf'];
}

function dc_csrf_field() {
    return '<input type="hidden" name="csrf" value="' . dc_h(dc_csrf_token()) . '">';
}

function dc_security_headers() {
    if (!headers_sent()) {
        header('X-Content-Type-Options: nosniff');
        header('Referrer-Policy: same-origin');
    }
}

function dc_require_csrf() {
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $token = isset($_POST['csrf']) ? $_POST['csrf'] : '';
        if (!hash_equals(dc_csrf_token(), $token)) {
            http_response_code(400);
            exit('Invalid form token.');
        }
    }
}

function dc_is_logged_in() {
    return !empty($_SESSION['dc_admin_id']);
}

function dc_require_login() {
    if (!dc_is_logged_in()) {
        dc_redirect('admin/login.php');
    }
}

function dc_admin_header($title) {
    dc_security_headers();
    echo '<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">';
    echo '<title>' . dc_h($title) . ' - Door Certificates</title><link rel="stylesheet" href="../assets/style.css?v=' . (int)dc_style_version() . '"></head><body><div class="dc-shell">';
    echo '<div class="dc-header"><h1>' . dc_h($title) . '</h1></div>';
    if (dc_is_logged_in()) {
        echo '<div class="dc-nav">';
        echo '<a class="dc-btn light" href="index.php">Dashboard</a>';
        echo '<a class="dc-btn light" href="projects.php">Projects</a>';
        echo '<a class="dc-btn light" href="categories.php">Categories</a>';
        echo '<a class="dc-btn light" href="standards.php">Standards</a>';
        echo '<a class="dc-btn light" href="doors.php">Doors</a>';
        echo '<a class="dc-btn light" href="export-doors.php">Backup CSV</a>';
        echo '<a class="dc-btn secondary" href="logout.php">Logout</a>';
        echo '</div>';
    }
    echo dc_flash();
}

function dc_public_header($title) {
    dc_security_headers();
    echo '<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">';
    echo '<meta name="referrer" content="same-origin"><title>' . dc_h($title) . ' - ' . dc_h(DC_COMPANY_NAME) . '</title><link rel="stylesheet" href="assets/style.css?v=' . (int)dc_style_version() . '"></head><body><div class="dc-shell">';
}

function dc_footer() {
    echo '</div></body></html>';
}

function dc_random_token() {
    return bin2hex(random_bytes(24));
}

function dc_project_code_for_door_id($projectNumber) {
    $project = strtoupper(trim((string)$projectNumber));
    $project = preg_replace('/[^A-Z0-9]+/', '', $project);
    if (preg_match('/^PRJ(\d+)$/', $project, $matches)) {
        return str_pad($matches[1], 3, '0', STR_PAD_LEFT);
    }
    return $project;
}

function dc_slug_code($value) {
    $value = strtoupper(trim((string)$value));
    $value = preg_replace('/[^A-Z0-9]+/', '', $value);
    return $value;
}

function dc_build_door_id($categoryCode, $year, $projectNumber, $doorNumber) {
    $project = dc_project_code_for_door_id($projectNumber);
    $door = strtoupper(trim($doorNumber));
    if (ctype_digit($door)) {
        $door = str_pad($door, 3, '0', STR_PAD_LEFT);
    } else {
        $door = preg_replace('/[^A-Z0-9]+/', '', $door);
    }
    return dc_slug_code($categoryCode) . '-' . (int)$year . '-' . $project . '-' . $door;
}

function dc_door_id_exists($doorId, $excludeId = 0) {
    $sql = 'SELECT id FROM door_cert_doors WHERE door_id = ?';
    $params = array($doorId);
    if ((int)$excludeId > 0) {
        $sql .= ' AND id <> ?';
        $params[] = (int)$excludeId;
    }
    $sql .= ' LIMIT 1';
    $stmt = dc_db()->prepare($sql);
    $stmt->execute($params);
    return (bool)$stmt->fetch();
}

function dc_recent_field_values($field, $fallback, $limit = 8) {
    if (!in_array($field, array('standards', 'fire_rating'), true)) {
        return array($fallback);
    }
    $stmt = dc_db()->query('SELECT ' . $field . ' value FROM door_cert_doors WHERE ' . $field . ' IS NOT NULL AND ' . $field . ' <> "" GROUP BY ' . $field . ' ORDER BY MAX(updated_at) DESC, MAX(created_at) DESC LIMIT ' . (int)$limit);
    $values = array();
    if ($fallback !== '') {
        $values[] = $fallback;
    }
    foreach ($stmt->fetchAll() as $row) {
        if (!in_array($row['value'], $values, true)) {
            $values[] = $row['value'];
        }
    }
    return $values;
}

function dc_parse_standards($value) {
    if (is_array($value)) {
        $parts = $value;
    } else {
        $value = trim((string)$value);
        if ($value === '') {
            return array();
        }
        $parts = strpos($value, ' || ') !== false ? explode(' || ', $value) : array($value);
    }
    $standards = array();
    foreach ($parts as $part) {
        $part = trim((string)$part);
        if ($part !== '' && !in_array($part, $standards, true)) {
            $standards[] = $part;
        }
    }
    return $standards;
}

function dc_store_standards($value) {
    return implode(' || ', dc_parse_standards($value));
}

function dc_display_standards($value) {
    return implode('; ', dc_parse_standards($value));
}

function dc_latest_field_value($field, $fallback) {
    if (!in_array($field, array('standards', 'fire_rating'), true)) {
        return $fallback;
    }
    $stmt = dc_db()->query('SELECT ' . $field . ' value FROM door_cert_doors WHERE ' . $field . ' IS NOT NULL AND ' . $field . ' <> "" ORDER BY updated_at DESC, created_at DESC LIMIT 1');
    $row = $stmt->fetch();
    return $row ? $row['value'] : $fallback;
}

function dc_format_date($date) {
    if (!$date || $date === '0000-00-00') {
        return '';
    }
    return date('d-m-Y', strtotime($date));
}

function dc_company_website_label() {
    $website = trim((string)DC_COMPANY_WEBSITE);
    if ($website === '') {
        return '';
    }
    $host = parse_url($website, PHP_URL_HOST);
    if ($host) {
        return $host;
    }
    return rtrim(preg_replace('#^https?://#i', '', $website), '/');
}

function dc_asset_path($name) {
    return __DIR__ . '/../assets/brand/' . $name;
}

function dc_asset_url($name) {
    return dc_url('assets/brand/' . rawurlencode($name));
}

function dc_style_version() {
    $path = __DIR__ . '/../assets/style.css';
    return is_file($path) ? filemtime($path) : time();
}

function dc_file_data_uri($path) {
    if (!is_file($path)) {
        return '';
    }
    $mime = function_exists('mime_content_type') ? mime_content_type($path) : 'image/jpeg';
    return 'data:' . $mime . ';base64,' . base64_encode(file_get_contents($path));
}

function dc_status_for_door($door) {
    if ($door['status'] === 'suspended') {
        return 'suspended';
    }
    if (!empty($door['valid_to']) && strtotime($door['valid_to'] . ' 23:59:59') < time()) {
        return 'expired';
    }
    return $door['status'];
}

function dc_verify_url($door) {
    return dc_url('verify.php?id=' . rawurlencode($door['door_id']) . '&key=' . rawurlencode($door['qr_token']));
}

function dc_qr_api_url($text, $size = 220) {
    return 'https://api.qrserver.com/v1/create-qr-code/?size=' . (int)$size . 'x' . (int)$size . '&data=' . rawurlencode($text);
}

function dc_http_get($url) {
    $data = false;
    if (ini_get('allow_url_fopen')) {
        $context = stream_context_create(array(
            'http' => array('timeout' => 15),
            'ssl' => array('verify_peer' => true, 'verify_peer_name' => true),
        ));
        $data = @file_get_contents($url, false, $context);
    }
    if ($data === false && function_exists('curl_init')) {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        curl_setopt($ch, CURLOPT_TIMEOUT, 20);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        $data = curl_exec($ch);
        $status = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        if ($status < 200 || $status >= 300) {
            $data = false;
        }
    }
    return $data;
}

function dc_is_png_data($data) {
    return is_string($data) && substr($data, 0, 8) === "\x89PNG\x0d\x0a\x1a\x0a";
}

function dc_save_qr($doorId, $url) {
    $dir = __DIR__ . '/../storage/qrcodes';
    if (!is_dir($dir)) {
        mkdir($dir, 0755, true);
    }
    $file = $dir . '/' . preg_replace('/[^A-Za-z0-9_-]+/', '_', $doorId) . '.png';
    $data = dc_http_get(dc_qr_api_url($url, 320));
    if (dc_is_png_data($data) && strlen($data) > 100) {
        file_put_contents($file, $data);
        return 'storage/qrcodes/' . basename($file);
    }
    return null;
}

function dc_qr_path_for_door($door) {
    $qrPath = !empty($door['qr_image_path']) ? __DIR__ . '/../' . $door['qr_image_path'] : '';
    if (is_file($qrPath)) {
        return $qrPath;
    }

    $saved = dc_save_qr($door['door_id'], dc_verify_url($door));
    if ($saved) {
        $stmt = dc_db()->prepare('UPDATE door_cert_doors SET qr_image_path=? WHERE id=?');
        $stmt->execute(array($saved, $door['id']));
        return __DIR__ . '/../' . $saved;
    }

    return '';
}

function dc_label_download_filename($door, $extension) {
    $base = preg_replace('/[^A-Za-z0-9_-]+/', '-', (string)$door['door_id']);
    $base = trim($base, '-_');
    if ($base === '') {
        $base = 'door';
    }
    return $base . '-label.' . ltrim((string)$extension, '.');
}

function dc_label_rating_number($door) {
    $ratingNumber = preg_replace('/\D+/', '', isset($door['fire_rating']) ? $door['fire_rating'] : '');
    return $ratingNumber !== '' ? $ratingNumber : '120';
}

function dc_label_qr_src($door) {
    $qrPath = dc_qr_path_for_door($door);
    $qrSrc = dc_file_data_uri($qrPath);
    return $qrSrc !== '' ? $qrSrc : dc_qr_api_url(dc_verify_url($door), 220);
}

function dc_label_logo_src() {
    $labelLogo = dc_preferred_logo_asset();
    if ($labelLogo === '') {
        return '';
    }
    $path = dc_asset_path($labelLogo);
    $dataUri = dc_file_data_uri($path);
    return $dataUri !== '' ? $dataUri : dc_asset_url($labelLogo);
}

function dc_label_contacts() {
    return array(
        array('email', DC_COMPANY_EMAIL),
        array('whatsapp', DC_COMPANY_PHONE),
    );
}

function dc_label_wrap_text($text, $maxChars) {
    $words = preg_split('/\s+/', trim((string)$text));
    $lines = array();
    $line = '';
    foreach ($words as $word) {
        if ($word === '') {
            continue;
        }
        $candidate = $line === '' ? $word : $line . ' ' . $word;
        if (strlen($candidate) > $maxChars && $line !== '') {
            $lines[] = $line;
            $line = $word;
        } else {
            $line = $candidate;
        }
    }
    if ($line !== '') {
        $lines[] = $line;
    }
    return $lines ?: array('');
}

function dc_label_svg_image($href, $x, $y, $width, $height, $extra = '') {
    $href = dc_h($href);
    return '<image href="' . $href . '" xlink:href="' . $href . '" x="' . (int)$x . '" y="' . (int)$y . '" width="' . (int)$width . '" height="' . (int)$height . '"' . $extra . '/>';
}

function dc_label_svg_text_lines($text, $x, $startY, $fontSize, $weight, $maxChars, $lineHeight) {
    $lines = dc_label_wrap_text($text, $maxChars);
    $svg = '';
    foreach ($lines as $i => $line) {
        $svg .= '<text x="' . (int)$x . '" y="' . (int)($startY + ($i * $lineHeight)) . '" font-family="Arial, Helvetica, sans-serif" font-size="' . (int)$fontSize . '" font-weight="' . dc_h($weight) . '" text-anchor="middle">' . dc_h($line) . '</text>';
    }
    return array($svg, count($lines));
}

function dc_label_svg_contact_icon($type, $x, $y) {
    $tx = (int)$x;
    $ty = (int)$y;
    if ($type === 'email') {
        return '<g transform="translate(' . $tx . ' ' . $ty . ')"><circle cx="11" cy="11" r="11" fill="#cc1111"/><g transform="translate(4 4) scale(.58)"><path d="M2 6a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v.01L12 13 2 6.01V6z" fill="#fff"/><path d="M2 8.5V18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8.5l-10 6.5L2 8.5z" fill="#fff"/></g></g>';
    }
    if ($type === 'whatsapp') {
        return '<g transform="translate(' . $tx . ' ' . $ty . ')"><circle cx="11" cy="11" r="11" fill="#cc1111"/><g transform="translate(4 4) scale(.58)"><path fill-rule="evenodd" clip-rule="evenodd" d="M12 2C6.477 2 2 6.477 2 12c0 1.89.525 3.66 1.438 5.168L2 22l4.832-1.438A9.956 9.956 0 0 0 12 22c5.523 0 10-4.477 10-10S17.523 2 12 2zm-2.965 5.545c-.18.04-.43.16-.67.4-.24.24-.92.9-.92 2.19s.94 2.54 1.07 2.72c.13.17 1.83 2.93 4.52 3.99.63.27 1.12.43 1.5.55.63.2 1.2.17 1.66.1.51-.075 1.56-.64 1.78-1.26.22-.62.22-1.15.155-1.26-.065-.11-.24-.175-.5-.305-.26-.13-1.56-.77-1.8-.855-.24-.09-.415-.13-.59.13-.175.26-.675.855-.825 1.03-.15.175-.3.195-.56.065-.26-.13-1.095-.405-2.085-1.285-.77-.685-1.29-1.53-1.44-1.79-.15-.26-.015-.4.115-.53.115-.115.26-.3.39-.45.13-.15.175-.26.26-.435.085-.175.04-.325-.02-.455-.065-.13-.59-1.42-.81-1.94-.21-.5-.425-.43-.59-.44-.2-.005-.4.003-.58.043z" fill="#fff"/></g></g>';
    }
    return '';
}

function dc_label_svg($door, &$width = null, &$height = null) {
    $width = 312;
    $center = 156;
    $logo = dc_label_logo_src();
    $qr = dc_label_qr_src($door);
    $ratingNumber = dc_label_rating_number($door);
    list($standardsSvg, $standardsLines) = dc_label_svg_text_lines(dc_display_standards($door['standards']), $center, 194, 14, '700', 30, 21);
    $afterStandardsY = 194 + max(1, $standardsLines) * 21;
    $mfgY = $afterStandardsY + 18;
    $categoryY = $mfgY + 34;
    $ratingCy = $categoryY + 49;
    $ratingTextY = $ratingCy + 11;
    $linkY = $ratingCy + 58;
    $qrY = $linkY + 18;
    $qrSize = 180;
    $doorY = $qrY + $qrSize + 30;
    $firstContactY = $doorY + 29;
    $height = $firstContactY + 58;

    $svg = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    $svg .= '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="' . $width . '" height="' . (int)$height . '" viewBox="0 0 ' . $width . ' ' . (int)$height . '">' . "\n";
    $svg .= '<rect width="' . $width . '" height="' . (int)$height . '" fill="#fff"/>';
    $svg .= '<rect x="1" y="1" width="' . ($width - 2) . '" height="' . ((int)$height - 2) . '" fill="#fff" stroke="#cc1111" stroke-width="2"/>';
    if ($logo) {
        $svg .= dc_label_svg_image($logo, 41, 16, 230, 82, ' preserveAspectRatio="xMidYMid meet"');
    } else {
        $svg .= '<text x="' . $center . '" y="58" font-family="Arial, Helvetica, sans-serif" font-size="24" font-weight="700" text-anchor="middle">' . dc_h(DC_COMPANY_NAME) . '</text>';
    }
    $svg .= '<text x="' . $center . '" y="123" font-family="Arial, Helvetica, sans-serif" font-size="14" font-weight="700" text-anchor="middle">Attested by PCSIR</text>';
    $svg .= '<line x1="16" y1="145" x2="296" y2="145" stroke="#cc1111" stroke-width="1.5"/>';
    $svg .= '<text x="' . $center . '" y="172" font-family="Arial, Helvetica, sans-serif" font-size="14" font-weight="700" text-anchor="middle">AS PER</text>';
    $svg .= $standardsSvg;
    $svg .= '<text x="' . $center . '" y="' . (int)$mfgY . '" font-family="Arial, Helvetica, sans-serif" font-size="14" font-weight="700" text-anchor="middle">MFG DATE ' . dc_h(dc_format_date($door['manufacture_date'])) . '</text>';
    $svg .= '<text x="' . $center . '" y="' . (int)$categoryY . '" font-family="Arial, Helvetica, sans-serif" font-size="22" font-weight="700" fill="#cc1111" text-anchor="middle">' . dc_h($door['category_code']) . '</text>';
    $svg .= '<ellipse cx="' . $center . '" cy="' . (int)$ratingCy . '" rx="43" ry="36" fill="#fff" stroke="#cc1111" stroke-width="4"/>';
    $svg .= '<text x="' . $center . '" y="' . (int)$ratingTextY . '" font-family="Arial, Helvetica, sans-serif" font-size="30" font-weight="900" fill="#cc1111" text-anchor="middle">' . dc_h($ratingNumber) . '</text>';
    $svg .= '<text x="' . $center . '" y="' . (int)$linkY . '" font-family="Arial, Helvetica, sans-serif" font-size="14" font-weight="700" text-anchor="middle">Link to Full Info</text>';
    $svg .= '<rect x="65.5" y="' . (int)($qrY - .5) . '" width="' . ($qrSize + 1) . '" height="' . ($qrSize + 1) . '" fill="#fff" stroke="#d8dee6" stroke-width="1"/>';
    if ($qr) {
        $svg .= dc_label_svg_image($qr, 66, $qrY, $qrSize, $qrSize);
    }
    $svg .= '<text x="' . $center . '" y="' . (int)$doorY . '" font-family="Arial, Helvetica, sans-serif" font-size="12" font-weight="700" text-anchor="middle">' . dc_h($door['door_id']) . '</text>';
    foreach (dc_label_contacts() as $i => $contact) {
        $y = $firstContactY + ($i * 28);
        $svg .= dc_label_svg_contact_icon($contact[0], 75, $y - 17);
        $svg .= '<text x="105" y="' . (int)$y . '" font-family="Arial, Helvetica, sans-serif" font-size="11" font-weight="700">' . dc_h($contact[1]) . '</text>';
    }
    $svg .= '</svg>';
    return $svg;
}

function dc_label_preview_html($door) {
    $svg = dc_label_svg($door);
    return '<div class="dc-label-preview"><img src="data:image/svg+xml;base64,' . base64_encode($svg) . '" alt="Door label artwork preview"></div>';
}

function dc_standard_certificate_slug($value) {
    $value = strtolower(trim((string)$value));
    $value = preg_replace('/[^a-z0-9]+/', '-', $value);
    return trim($value, '-');
}

function dc_company_certificate_dir() {
    return __DIR__ . '/../storage/company-certificates';
}

function dc_company_certificate_for_standard($standard) {
    $certificates = dc_company_certificates_for_standards($standard);
    return $certificates ? $certificates[0]['path'] : '';
}

function dc_company_certificate_matches($fileSlug, $standardSlugs) {
    if ($fileSlug === '') {
        return false;
    }
    $parts = strpos($fileSlug, '__') !== false ? explode('__', $fileSlug) : array($fileSlug);
    foreach ($parts as $part) {
        $part = trim($part, '-_ ');
        if ($part === '') {
            continue;
        }
        $matched = false;
        foreach ($standardSlugs as $standardSlug) {
            if (strpos($standardSlug, $part) !== false || strpos($part, $standardSlug) !== false) {
                $matched = true;
                break;
            }
        }
        if (!$matched) {
            return false;
        }
    }
    return true;
}

function dc_company_certificates_for_standards($standardsValue) {
    $dir = dc_company_certificate_dir();
    if (!is_dir($dir)) {
        return array();
    }
    $standards = dc_parse_standards($standardsValue);
    if (!$standards) {
        $standards = array($standardsValue);
    }
    $standardSlugs = array();
    foreach ($standards as $oneStandard) {
        $slug = dc_standard_certificate_slug($oneStandard);
        if ($slug !== '') {
            $standardSlugs[] = $slug;
        }
    }
    $files = glob($dir . '/*.{pdf,jpg,jpeg,png,webp}', GLOB_BRACE);
    $certificates = array();
    foreach ($files ? $files : array() as $path) {
        $fileSlug = dc_standard_certificate_slug(str_replace('__', ' doubleunderscore ', pathinfo($path, PATHINFO_FILENAME)));
        $fileSlug = str_replace('-doubleunderscore-', '__', $fileSlug);
        if (dc_company_certificate_matches($fileSlug, $standardSlugs)) {
            $base = pathinfo($path, PATHINFO_FILENAME);
            $certificates[$base] = array(
                'slug' => $base,
                'path' => $path,
                'name' => dc_company_certificate_title($base),
            );
        }
    }
    uasort($certificates, function ($a, $b) {
        return strcmp($a['name'], $b['name']);
    });
    return array_values($certificates);
}

function dc_company_certificate_title($slug) {
    $parts = explode('__', $slug);
    $names = array();
    foreach ($parts as $part) {
        $part = strtoupper(str_replace('-', ' ', trim($part)));
        $part = str_replace(array('UL 10C', 'NFPA 252', 'FM 4100', 'B S 476'), array('UL-10C', 'NFPA-252', 'FM 4100', 'B.S 476'), $part);
        if ($part !== '') {
            $names[] = $part;
        }
    }
    return implode(' + ', $names);
}

function dc_company_certificate_url($door, $download = false, $certificateSlug = '') {
    $url = dc_url('company-certificate.php?id=' . rawurlencode($door['door_id']) . '&key=' . rawurlencode($door['qr_token']));
    if ($certificateSlug !== '') {
        $url .= '&cert=' . rawurlencode($certificateSlug);
    }
    return $download ? $url . '&download=1' : $url;
}

function dc_company_certificate_viewer_url($door, $certificateSlug = '') {
    return dc_company_certificate_url($door, false, $certificateSlug) . '&viewer=1';
}

function dc_company_certificate_path_for_door($door, $certificateSlug = '') {
    $certificates = dc_company_certificates_for_standards($door['standards']);
    if (!$certificates) {
        return '';
    }
    if ($certificateSlug === '') {
        return $certificates[0]['path'];
    }
    foreach ($certificates as $certificate) {
        if (hash_equals($certificate['slug'], $certificateSlug)) {
            return $certificate['path'];
        }
    }
    return '';
}

function dc_send_company_certificate($door, $download = false, $certificateSlug = '') {
    $path = dc_company_certificate_path_for_door($door, $certificateSlug);
    if ($path === '') {
        http_response_code(404);
        exit('Company certificate not found for this standard.');
    }
    $mime = function_exists('mime_content_type') ? mime_content_type($path) : 'application/octet-stream';
    $filename = pathinfo($path, PATHINFO_BASENAME);
    header('Content-Type: ' . $mime);
    header('Content-Disposition: ' . ($download ? 'attachment' : 'inline') . '; filename="' . $filename . '"');
    header('Content-Length: ' . filesize($path));
    readfile($path);
    exit;
}

function dc_find_public_door($doorId, $key) {
    if (trim((string)$doorId) === '' || trim((string)$key) === '') {
        return null;
    }
    $stmt = dc_db()->prepare('SELECT d.*, c.code category_code, c.name category_name, p.project_number, p.client_name, p.site_location
        FROM door_cert_doors d
        JOIN door_cert_categories c ON c.id = d.category_id
        JOIN door_cert_projects p ON p.id = d.project_id
        WHERE d.door_id = ?
        LIMIT 1');
    $stmt->execute(array($doorId));
    $door = $stmt->fetch();
    if (!$door || !hash_equals((string)$door['qr_token'], (string)$key)) {
        return null;
    }
    return $door;
}

function dc_log_download($doorId, $type) {
    $stmt = dc_db()->prepare('INSERT INTO door_cert_download_logs (door_id, file_type, ip_address, user_agent) VALUES (?, ?, ?, ?)');
    $stmt->execute(array(
        $doorId,
        $type,
        isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '',
        substr(isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '', 0, 255),
    ));
}

function dc_door_export_rows() {
    return dc_db()->query('SELECT
            d.id,
            d.door_id,
            d.door_number,
            d.po_number,
            d.area_location,
            d.fire_rating,
            d.standards,
            d.manufacture_date,
            d.valid_from,
            d.valid_to,
            d.status,
            d.qr_token,
            d.qr_image_path,
            d.notes,
            d.created_at,
            d.updated_at,
            c.code category_code,
            c.name category_name,
            p.project_number,
            p.client_name,
            p.site_location
        FROM door_cert_doors d
        JOIN door_cert_categories c ON c.id = d.category_id
        JOIN door_cert_projects p ON p.id = d.project_id
        ORDER BY d.created_at DESC')->fetchAll();
}

function dc_write_doors_csv($handle) {
    $headers = array(
        'id', 'door_id', 'door_number', 'po_number', 'category_code', 'category_name', 'project_number',
        'client_name', 'site_location', 'area_location', 'fire_rating', 'standards',
        'manufacture_date', 'valid_from', 'valid_to', 'status', 'qr_token',
        'qr_image_path', 'notes', 'created_at', 'updated_at'
    );
    fputcsv($handle, $headers);
    foreach (dc_door_export_rows() as $row) {
        fputcsv($handle, array(
            $row['id'], $row['door_id'], $row['door_number'], $row['po_number'], $row['category_code'], $row['category_name'],
            $row['project_number'], $row['client_name'], $row['site_location'], $row['area_location'],
            $row['fire_rating'], dc_display_standards($row['standards']), $row['manufacture_date'], $row['valid_from'],
            $row['valid_to'], $row['status'], $row['qr_token'], $row['qr_image_path'], $row['notes'],
            $row['created_at'], $row['updated_at']
        ));
    }
}

function dc_create_doors_backup() {
    $dir = __DIR__ . '/../storage/backups';
    if (!is_dir($dir)) {
        mkdir($dir, 0755, true);
    }
    $file = $dir . '/doors-backup-' . date('Ymd-His') . '.csv';
    $handle = fopen($file, 'w');
    if (!$handle) {
        return false;
    }
    dc_write_doors_csv($handle);
    fclose($handle);
    return $file;
}

function dc_certificate_values($door) {
    return array(
        'REFERENCE_NO' => $door['door_id'],
        'DATE' => date('d-m-Y'),
        'CLIENT_NAME' => $door['client_name'],
        'PROJECT_LOCATION' => $door['site_location'],
        'DOOR_ID' => $door['door_id'],
        'PO_NUMBER' => isset($door['po_number']) ? $door['po_number'] : '',
        'CATEGORY' => dc_clean_door_category($door['category_name']),
        'AREA' => $door['area_location'],
        'FIRE_RATING' => $door['fire_rating'],
        'STANDARDS' => dc_display_standards($door['standards']),
        'MFG_DATE' => dc_format_date($door['manufacture_date']),
        'VALID_FROM' => dc_format_date($door['valid_from']),
        'VALID_TO' => dc_format_date($door['valid_to']),
        'STATUS' => strtoupper(dc_status_for_door($door)),
    );
}

function dc_certificate_template_dir() {
    return __DIR__ . '/../templates/certificate';
}

function dc_certificate_html($door, $fitWidth = 0) {
    $templatePath = dc_certificate_template_dir() . '/certificate.html';
    $stylePath = dc_certificate_template_dir() . '/certificate.css';
    if (!is_file($templatePath) || !is_file($stylePath)) {
        http_response_code(500);
        exit('Certificate template is missing.');
    }

    $v = dc_certificate_values($door);
    $html = file_get_contents($templatePath);
    $css = file_get_contents($stylePath);
    $qrPath = dc_qr_path_for_door($door);
    $qrSrc = dc_file_data_uri($qrPath);
    if ($qrSrc === '') {
        $qrSrc = dc_qr_api_url(dc_verify_url($door), 320);
    }
    $sealPath = dc_certificate_template_dir() . '/samcon-seal-print.png';
    if (!is_file($sealPath)) {
        $sealPath = dc_certificate_template_dir() . '/samcon-seal.png';
    }
    $sealSrc = dc_file_data_uri($sealPath);
    $headerLogoSrc = dc_file_data_uri(dc_asset_path('samcon-pvt-ltd-logo.jpeg'));
    $watermarkLogoSrc = dc_file_data_uri(dc_asset_path('samcon-pvt-ltd-logo.jpeg'));
    $footerImageSrc = dc_file_data_uri(dc_asset_path('Samcon Letter Pad.jpg.jpeg'));
    $validity = trim($v['VALID_FROM'] . ' to ' . $v['VALID_TO']);
    if ($validity === 'to') {
        $validity = '';
    }
    $status = $v['STATUS'] === 'ACTIVE' ? 'VALID & COMPLIANT' : $v['STATUS'];

    $replace = array(
        '{{CATEGORY}}' => dc_h($v['CATEGORY']),
        '{{REFERENCE_NO}}' => dc_h($v['REFERENCE_NO']),
        '{{DOOR_CERTIFICATE_NO}}' => dc_h($v['DOOR_ID']),
        '{{DATE}}' => dc_h($v['DATE']),
        '{{CLIENT}}' => dc_h($v['CLIENT_NAME']),
        '{{PROJECT_SITE}}' => dc_h($v['PROJECT_LOCATION']),
        '{{AREA}}' => dc_h($v['AREA']),
        '{{MANUFACTURING_DATE}}' => dc_h($v['MFG_DATE']),
        '{{FIRE_RATING}}' => dc_h($v['FIRE_RATING']),
        '{{STANDARDS_COMPLIED}}' => dc_h($v['STANDARDS']),
        '{{VALIDITY_PERIOD}}' => dc_h($validity),
        '{{CURRENT_STATUS}}' => dc_h($status),
        '{{QR_CODE}}' => '<img src="' . dc_h($qrSrc) . '" alt="Verification QR code">',
        '{{SEAL_IMAGE}}' => dc_h($sealSrc),
        '{{HEADER_LOGO}}' => dc_h($headerLogoSrc),
        '{{WATERMARK_LOGO}}' => dc_h($watermarkLogoSrc),
        '{{FOOTER_IMAGE}}' => dc_h($footerImageSrc),
        '{{PDF_DOWNLOAD_URL}}' => dc_h(dc_url('download.php?type=pdf&id=' . rawurlencode($door['door_id']) . '&key=' . rawurlencode($door['qr_token']))),
    );

    $html = str_replace('<link rel="stylesheet" href="certificate.css">', '<style>' . $css . '</style>', $html);
    $fitWidth = (int)$fitWidth;
    if ($fitWidth > 0) {
        $sheetWidth = 210 / 25.4 * 96;
        $sheetHeight = 297 / 25.4 * 96;
        $fitWidth = max(240, min(760, $fitWidth));
        $scale = min(1, $fitWidth / $sheetWidth);
        $fitHeight = (int)ceil($sheetHeight * $scale);
        $fitStyle = '--certificate-fit-width:' . $fitWidth . 'px;--certificate-fit-scale:' . round($scale, 4) . ';--certificate-fit-height:' . $fitHeight . 'px';
        $html = str_replace('<body>', '<body class="certificate-fit" style="' . $fitStyle . '">', $html);
    }
    return strtr($html, $replace);
}

function dc_send_certificate_html($door, $download = false) {
    $fitWidth = isset($_GET['fit_width']) ? (int)$_GET['fit_width'] : 0;
    $html = dc_certificate_html($door, $fitWidth);
    header('Content-Type: text/html; charset=utf-8');
    if ($download) {
        header('Content-Disposition: attachment; filename="' . $door['door_id'] . '-certificate.html"');
    }
    header('Content-Length: ' . strlen($html));
    echo $html;
    exit;
}

function dc_certificate_download_filename($door, $extension) {
    $base = preg_replace('/[^A-Za-z0-9_-]+/', '-', (string)$door['door_id']);
    $base = trim($base, '-_');
    if ($base === '') {
        $base = 'door';
    }
    return $base . '-certificate.' . ltrim((string)$extension, '.');
}

function dc_pdf_export_library_url() {
    $path = __DIR__ . '/../assets/html2pdf.bundle.min.js';
    if (is_file($path)) {
        return dc_url('assets/html2pdf.bundle.min.js?v=' . filemtime($path));
    }
    return 'https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js';
}

function dc_pdf_export_library_script() {
    $path = __DIR__ . '/../assets/html2pdf.bundle.min.js';
    if (is_file($path)) {
        $script = file_get_contents($path);
        return '<script>' . str_replace('</script', '<\/script', $script) . '</script>';
    }
    return '<script src="' . dc_h(dc_pdf_export_library_url()) . '"></script>';
}

function dc_send_certificate_pdf_export($door) {
    $html = dc_certificate_html($door, 0);
    $filename = dc_certificate_download_filename($door, 'pdf');
    $filenameJson = json_encode($filename);
    $libraryScript = dc_pdf_export_library_script();
    $exportTools = <<<HTML
<style>
  .certificate-export {
    background: #f5f7fa;
  }

  .certificate-export .certificate-page {
    padding: 0;
  }

  .certificate-export .certificate-sheet {
    box-shadow: none;
  }

  .certificate-export-status {
    position: fixed;
    right: 16px;
    bottom: 16px;
    z-index: 20;
    max-width: 360px;
    border: 1px solid rgba(5, 22, 45, .16);
    border-radius: 6px;
    background: rgba(255, 255, 255, .96);
    box-shadow: 0 16px 40px rgba(7, 18, 35, .18);
    color: #061a35;
    font: 14px/1.35 Arial, Helvetica, sans-serif;
    padding: 14px 16px;
  }

  .certificate-export-status strong,
  .certificate-export-status span {
    display: block;
  }

  .certificate-export-status span {
    margin-top: 4px;
  }

  .certificate-export-status button,
  .certificate-export-status a {
    display: inline-block;
    margin-top: 10px;
    border: 0;
    border-radius: 4px;
    background: #0b5ea8;
    color: #fff;
    cursor: pointer;
    font-weight: 700;
    padding: 8px 10px;
    text-decoration: none;
  }

  .certificate-export {
    min-width: 210mm;
  }

  .certificate-export .certificate-page {
    display: block !important;
    position: absolute !important;
    top: 0 !important;
    left: 0 !important;
    width: 210mm !important;
    height: 296.5mm !important;
    margin: 0 !important;
    padding: 0 !important;
    overflow: visible !important;
  }

  .certificate-export .certificate-sheet {
    position: absolute !important;
    top: 0 !important;
    left: 0 !important;
    width: 210mm !important;
    height: 296.5mm !important;
    min-height: 296.5mm !important;
    margin: 0 !important;
    overflow: hidden !important;
    padding: 12mm 20mm 58mm !important;
    box-shadow: none !important;
    transform: none !important;
  }

  .certificate-export .certificate-verification {
    position: absolute !important;
    right: 20mm !important;
    bottom: 45mm !important;
    left: 20mm !important;
    height: 29mm !important;
  }

  .certificate-export .certificate-footer {
    position: absolute !important;
    right: 0 !important;
    bottom: .5mm !important;
    left: 0 !important;
    height: 23.7mm !important;
    min-height: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
  }

  @media screen and (max-width: 860px) {
    .certificate-export-status {
      right: 10px;
      bottom: 10px;
      left: 10px;
      max-width: none;
    }
  }
</style>
<div class="certificate-export-status" id="certificate-export-status" role="status" aria-live="polite">
  <strong>Preparing PDF...</strong>
  <span>Waiting for certificate images...</span>
  <button type="button" id="certificate-export-retry" hidden>Retry Download</button>
  <button type="button" id="certificate-print-fallback" onclick="window.print()" hidden>Print / Save as PDF</button>
</div>
{$libraryScript}
<script>
(function () {
  var fileName = {$filenameJson};
  var status = document.getElementById('certificate-export-status');
  var fallback = document.getElementById('certificate-print-fallback');
  var retry = document.getElementById('certificate-export-retry');
  var exporting = false;

  function setStatus(title, message, showFallback, showRetry) {
    if (!status) {
      return;
    }
    status.innerHTML = '<strong>' + title + '</strong><span>' + message + '</span>';
    if (showRetry && retry) {
      status.appendChild(retry);
      retry.hidden = false;
    }
    if (showFallback && fallback) {
      status.appendChild(fallback);
      fallback.hidden = false;
    }
  }

  function waitForImages(root) {
    var images = Array.prototype.slice.call(root.querySelectorAll('img'));
    return Promise.all(images.map(function (image) {
      if (image.complete && image.naturalWidth > 0) {
        return Promise.resolve();
      }
      return new Promise(function (resolve) {
        var done = function () {
          image.removeEventListener('load', done);
          image.removeEventListener('error', done);
          resolve();
        };
        image.addEventListener('load', done);
        image.addEventListener('error', done);
        window.setTimeout(done, 8000);
      });
    }));
  }

  function startExport() {
    if (exporting) {
      return;
    }
    var certificate = document.querySelector('.certificate-sheet');
    if (!certificate) {
      setStatus('PDF not ready', 'The certificate preview could not be found.', true, true);
      return;
    }
    if (typeof html2pdf === 'undefined') {
      setStatus('PDF library did not load', 'Use Print / Save as PDF, or check the internet connection and try again.', true, true);
      return;
    }

    exporting = true;
    setStatus('Preparing PDF...', 'Waiting for certificate images...', false, false);
    waitForImages(certificate).then(function () {
      document.body.classList.add('certificate-pdf-mode');
      setStatus('Preparing PDF...', 'Rendering the certificate. The download will start shortly.', false, false);
      var captureWidth = Math.ceil(certificate.offsetWidth);
      var captureHeight = Math.ceil(certificate.offsetHeight);
      return html2pdf().set({
        margin: 0,
        filename: fileName,
        image: { type: 'jpeg', quality: .98 },
        html2canvas: {
          scale: 2,
          backgroundColor: '#ffffff',
          useCORS: true,
          allowTaint: true,
          ignoreElements: function (element) {
            return element && element.tagName && element.tagName.toLowerCase() === 'svg';
          },
          onclone: function (clonedDocument) {
            Array.prototype.forEach.call(clonedDocument.querySelectorAll('svg'), function (svg) {
              if (svg.parentNode) {
                svg.parentNode.removeChild(svg);
              }
            });
            Array.prototype.forEach.call(clonedDocument.querySelectorAll('.footer-icon'), function (icon) {
              icon.textContent = '';
            });
            Array.prototype.forEach.call(clonedDocument.querySelectorAll('.seal'), function (seal) {
              seal.style.filter = 'none';
            });
          },
          scrollX: 0,
          scrollY: 0,
          x: 0,
          y: 0,
          width: captureWidth,
          height: captureHeight,
          windowWidth: captureWidth,
          windowHeight: captureHeight
        },
        jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' },
        enableLinks: false
      }).from(certificate).save();
    }).then(function () {
      exporting = false;
      document.body.classList.remove('certificate-pdf-mode');
      setStatus('PDF downloaded', 'You can close this tab or go back to the verification page.', false, false);
    }).catch(function (error) {
      exporting = false;
      document.body.classList.remove('certificate-pdf-mode');
      var detail = error && error.message ? error.message : 'Use Print / Save as PDF from this page.';
      setStatus('PDF download failed', detail, true, true);
    });
  }

  if (retry) {
    retry.addEventListener('click', startExport);
  }

  if (fallback) {
    fallback.addEventListener('click', function () {
      window.print();
    });
  }

  if (document.readyState === 'complete') {
    window.setTimeout(startExport, 300);
  } else {
    window.addEventListener('load', function () {
      window.setTimeout(startExport, 300);
    });
  }
})();
</script>
HTML;

    $html = str_replace('<body>', '<body class="certificate-export">', $html);
    $html = str_replace('</body>', $exportTools . "\n</body>", $html);
    dc_log_download($door['id'], 'pdf');
    header('Content-Type: text/html; charset=utf-8');
    header('Content-Length: ' . strlen($html));
    echo $html;
    exit;
}

function dc_send_docx($door) {
    $values = dc_certificate_values($door);
    $tmp = tempnam(sys_get_temp_dir(), 'dc_docx_');
    $zip = new ZipArchive();
    $zip->open($tmp, ZipArchive::OVERWRITE);
    $zip->addFromString('[Content_Types].xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Default Extension="jpeg" ContentType="image/jpeg"/><Default Extension="jpg" ContentType="image/jpeg"/><Default Extension="png" ContentType="image/png"/><Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/></Types>');
    $zip->addFromString('_rels/.rels', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/></Relationships>');
    $rels = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">';
    $media = array(
        'rFooter' => array('footer.jpeg', 'footer.jpeg'),
    );
    $logoAsset = dc_preferred_logo_asset();
    if ($logoAsset !== '') {
        $media = array('rLogo' => array($logoAsset, $logoAsset)) + $media;
    }
    foreach ($media as $rid => $info) {
        if (is_file(dc_asset_path($info[0]))) {
            $zip->addFile(dc_asset_path($info[0]), 'word/media/' . $info[1]);
            $rels .= '<Relationship Id="' . $rid . '" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/' . $info[1] . '"/>';
        }
    }
    $rels .= '</Relationships>';
    $zip->addFromString('word/_rels/document.xml.rels', $rels);
    $body = dc_docx_body($values);
    $zip->addFromString('word/document.xml', $body);
    $zip->close();
    dc_log_download($door['id'], 'docx');
    header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
    header('Content-Disposition: attachment; filename="' . $door['door_id'] . '-certificate.docx"');
    header('Content-Length: ' . filesize($tmp));
    readfile($tmp);
    unlink($tmp);
    exit;
}

function dc_clean_door_category($category) {
    $category = trim((string)$category);
    $category = str_ireplace('Fire Dorr', 'Fire Door', $category);
    return $category === '' ? 'Fire Door' : $category;
}

function dc_certificate_subject($v) {
    return 'Certificate of Compliance and Conformity for ' . $v['CATEGORY'];
}

function dc_certificate_note() {
    return 'This is a system-generated document and hence does not require any signature.';
}

function dc_certificate_statement($v) {
    return DC_COMPANY_NAME . ' certifies that the fire door identified below has been recorded for compliance and verification against the stated standards.';
}

function dc_preferred_logo_asset() {
    if (is_file(dc_asset_path('samcon-pvt-ltd-logo.jpeg'))) {
        return 'samcon-pvt-ltd-logo.jpeg';
    }
    if (is_file(dc_asset_path('logo.png'))) {
        return 'logo.png';
    }
    if (is_file(dc_asset_path('logo.jpeg'))) {
        return 'logo.jpeg';
    }
    return '';
}

function dc_preferred_pdf_logo_asset() {
    if (is_file(dc_asset_path('samcon-pvt-ltd-logo.jpeg'))) {
        return 'samcon-pvt-ltd-logo.jpeg';
    }
    if (is_file(dc_asset_path('logo-white.jpeg'))) {
        return 'logo-white.jpeg';
    }
    if (is_file(dc_asset_path('logo.jpeg'))) {
        return 'logo.jpeg';
    }
    return '';
}

function dc_docx_p($text, $bold = false, $size = 24, $align = 'left') {
    $text = dc_h($text);
    $b = $bold ? '<w:b/>' : '';
    $alignXml = $align !== 'left' ? '<w:pPr><w:jc w:val="' . dc_h($align) . '"/></w:pPr>' : '';
    return '<w:p>' . $alignXml . '<w:r><w:rPr>' . $b . '<w:sz w:val="' . (int)$size . '"/></w:rPr><w:t>' . $text . '</w:t></w:r></w:p>';
}

function dc_docx_image($rid, $cx, $cy, $name) {
    return '<w:p><w:pPr><w:jc w:val="center"/></w:pPr><w:r><w:drawing><wp:inline xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" distT="0" distB="0" distL="0" distR="0"><wp:extent cx="' . (int)$cx . '" cy="' . (int)$cy . '"/><wp:docPr id="' . mt_rand(100, 9999) . '" name="' . dc_h($name) . '"/><a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"><a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:nvPicPr><pic:cNvPr id="0" name="' . dc_h($name) . '"/><pic:cNvPicPr/></pic:nvPicPr><pic:blipFill><a:blip xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:embed="' . $rid . '"/><a:stretch><a:fillRect/></a:stretch></pic:blipFill><pic:spPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="' . (int)$cx . '" cy="' . (int)$cy . '"/></a:xfrm><a:prstGeom prst="rect"><a:avLst/></a:prstGeom></pic:spPr></pic:pic></a:graphicData></a:graphic></wp:inline></w:drawing></w:r></w:p>';
}

function dc_docx_body($v) {
    $xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>';
    $xml .= '<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"><w:body>';
    if (dc_preferred_logo_asset() !== '') {
        $xml .= dc_docx_image('rLogo', 2600000, 910000, 'SAMCON Associates Pvt Ltd Logo');
    } else {
        $xml .= dc_docx_p(DC_COMPANY_NAME, true, 34);
    }
    $xml .= dc_docx_p('CERTIFICATE OF COMPLIANCE & CONFORMITY', true, 30, 'center');
    $xml .= dc_docx_p('Reference No: ' . $v['REFERENCE_NO'] . '    Date: ' . $v['DATE']);
    $xml .= dc_docx_p('Client: ' . $v['CLIENT_NAME'], true);
    $xml .= dc_docx_p('Address: ' . $v['PROJECT_LOCATION']);
    $xml .= dc_docx_p('Subject: ' . dc_certificate_subject($v), true);
    $xml .= dc_docx_p('Door Certificate No: ' . $v['DOOR_ID'], true);
    $xml .= dc_docx_p('Area / Site: ' . $v['AREA']);
    $xml .= dc_docx_p('Manufacturing Date: ' . $v['MFG_DATE']);
    $xml .= dc_docx_p('Fire Rating: ' . $v['FIRE_RATING']);
    $xml .= dc_docx_p('As per: ' . $v['STANDARDS']);
    $xml .= dc_docx_p('Validation: This certificate is valid from ' . $v['VALID_FROM'] . ' to ' . $v['VALID_TO'] . '.');
    $xml .= dc_docx_p('Current Status: ' . $v['STATUS'], true);
    $xml .= dc_docx_p(dc_certificate_statement($v), false, 24);
    $xml .= dc_docx_p(dc_certificate_note(), false, 22, 'center');
    if (is_file(dc_asset_path('footer.jpeg'))) {
        $xml .= dc_docx_image('rFooter', 5200000, 540000, 'Certificate Footer');
    }
    $xml .= '<w:sectPr><w:pgSz w:w="11906" w:h="16838"/><w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440"/></w:sectPr>';
    $xml .= '</w:body></w:document>';
    return $xml;
}

function dc_send_pdf($door) {
    $v = dc_certificate_values($door);
    $qrPath = !empty($door['qr_image_path']) ? __DIR__ . '/../' . $door['qr_image_path'] : '';
    if (!is_file($qrPath)) {
        $saved = dc_save_qr($door['door_id'], dc_verify_url($door));
        $qrPath = $saved ? __DIR__ . '/../' . $saved : '';
        if ($saved) {
            $stmt = dc_db()->prepare('UPDATE door_cert_doors SET qr_image_path=? WHERE id=?');
            $stmt->execute(array($saved, $door['id']));
        }
    }
    $pdf = dc_certificate_pdf($v, $qrPath);
    dc_log_download($door['id'], 'pdf');
    header('Content-Type: application/pdf');
    header('Content-Disposition: attachment; filename="' . $door['door_id'] . '-certificate.pdf"');
    header('Content-Length: ' . strlen($pdf));
    echo $pdf;
    exit;
}

function dc_pdf_escape($text) {
    return str_replace(array('\\', '(', ')'), array('\\\\', '\\(', '\\)'), $text);
}

function dc_pdf_text($text, $x, $y, $size = 11) {
    return "BT\n/F1 " . (int)$size . " Tf\n" . (float)$x . " " . (float)$y . " Td\n(" . dc_pdf_escape($text) . ") Tj\nET\n";
}

function dc_pdf_bold_text($text, $x, $y, $size = 11) {
    return "BT\n/F2 " . (int)$size . " Tf\n" . (float)$x . " " . (float)$y . " Td\n(" . dc_pdf_escape($text) . ") Tj\nET\n";
}

function dc_pdf_text_width($text, $size = 11) {
    return strlen((string)$text) * (float)$size * 0.52;
}

function dc_pdf_center_text($text, $y, $size = 11, $pageWidth = 595) {
    $x = max(36, ($pageWidth - dc_pdf_text_width($text, $size)) / 2);
    return dc_pdf_text($text, $x, $y, $size);
}

function dc_pdf_center_bold_text($text, $y, $size = 11, $pageWidth = 595) {
    $x = max(36, ($pageWidth - dc_pdf_text_width($text, $size)) / 2);
    return dc_pdf_bold_text($text, $x, $y, $size);
}

function dc_pdf_justified_line($line, $x, $y, $size, $width, $justify = true) {
    $words = preg_split('/\s+/', trim((string)$line));
    if (!$justify || count($words) < 2) {
        return dc_pdf_text($line, $x, $y, $size);
    }
    $textWidth = dc_pdf_text_width($line, $size);
    $spacing = max(0, ($width - $textWidth) / (count($words) - 1));
    return "BT\n/F1 " . (int)$size . " Tf\n" . round($spacing, 3) . " Tw\n" . (float)$x . " " . (float)$y . " Td\n(" . dc_pdf_escape($line) . ") Tj\n0 Tw\nET\n";
}

function dc_pdf_wrap_text($text, $maxChars) {
    $words = preg_split('/\s+/', trim((string)$text));
    $lines = array();
    $line = '';
    foreach ($words as $word) {
        $test = $line === '' ? $word : $line . ' ' . $word;
        if (strlen($test) > $maxChars && $line !== '') {
            $lines[] = $line;
            $line = $word;
        } else {
            $line = $test;
        }
    }
    if ($line !== '') {
        $lines[] = $line;
    }
    return $lines ? $lines : array('');
}

function dc_pdf_text_block($text, $x, $y, $size = 10, $maxChars = 68, $lineHeight = 15) {
    $content = '';
    $lines = dc_pdf_wrap_text($text, $maxChars);
    foreach ($lines as $i => $line) {
        $content .= dc_pdf_text($line, $x, $y - ($i * $lineHeight), $size);
    }
    return array($content, count($lines) * $lineHeight);
}

function dc_pdf_center_text_block($text, $y, $size = 10, $maxChars = 68, $lineHeight = 15, $pageWidth = 595) {
    $content = '';
    $lines = dc_pdf_wrap_text($text, $maxChars);
    foreach ($lines as $i => $line) {
        $content .= dc_pdf_center_text($line, $y - ($i * $lineHeight), $size, $pageWidth);
    }
    return array($content, count($lines) * $lineHeight);
}

function dc_pdf_justified_text_block($text, $x, $y, $size = 10, $maxChars = 68, $lineHeight = 15, $width = 451) {
    $content = '';
    $lines = dc_pdf_wrap_text($text, $maxChars);
    $last = count($lines) - 1;
    foreach ($lines as $i => $line) {
        $content .= dc_pdf_justified_line($line, $x, $y - ($i * $lineHeight), $size, $width, $i !== $last);
    }
    return array($content, count($lines) * $lineHeight);
}

function dc_pdf_line($x1, $y1, $x2, $y2) {
    return (float)$x1 . " " . (float)$y1 . " m " . (float)$x2 . " " . (float)$y2 . " l S\n";
}

function dc_pdf_rect($x, $y, $w, $h, $fill = false) {
    return (float)$x . " " . (float)$y . " " . (float)$w . " " . (float)$h . " re " . ($fill ? "f\n" : "S\n");
}

function dc_pdf_image_draw($name, $x, $y, $w, $h) {
    return "q\n" . (float)$w . " 0 0 " . (float)$h . " " . (float)$x . " " . (float)$y . " cm\n/" . $name . " Do\nQ\n";
}

function dc_certificate_pdf($v, $qrPath = '') {
    $content = "1.1 w\n";
    $images = array();
    $content .= "0.96 0.96 0.93 rg\n" . dc_pdf_rect(28, 26, 539, 790, true);
    $content .= "1 1 1 rg\n" . dc_pdf_rect(42, 42, 511, 758, true);
    $content .= "0 0 0 RG\n1.8 w\n" . dc_pdf_rect(54, 54, 487, 734, false);

    $content .= "0.02 0.08 0.20 rg\n";
    $content .= dc_pdf_center_bold_text('CERTIFICATE', 734, 44);
    $content .= dc_pdf_center_bold_text('OF COMPLIANCE & CONFORMITY', 704, 24);
    $content .= "0.55 0.43 0.08 rg\n";
    $content .= dc_pdf_center_bold_text($v['CATEGORY'], 666, 18);
    $content .= "0 0 0 rg\n";

    $rows = array(
        array('Reference No.', $v['REFERENCE_NO']),
        array('Door Certificate No.', $v['DOOR_ID']),
        array('Date', $v['DATE']),
        array('Client', $v['CLIENT_NAME']),
        array('Address', $v['PROJECT_LOCATION']),
        array('Area / Site', $v['AREA']),
        array('PO Number', $v['PO_NUMBER']),
        array('Manufacturing Date', $v['MFG_DATE']),
        array('Fire Rating', $v['FIRE_RATING']),
        array('Standards Complied', $v['STANDARDS']),
        array('Validity Period', $v['VALID_FROM'] . ' to ' . $v['VALID_TO']),
        array('Current Status', $v['STATUS'] === 'ACTIVE' ? 'VALID & COMPLIANT' : $v['STATUS']),
    );
    $rows = array_values(array_filter($rows, function ($row) {
        return trim((string)$row[1]) !== '';
    }));

    $tableX = 82;
    $tableY = 628;
    $labelW = 190;
    $valueW = 242;
    $rowH = 24;
    $content .= "0.02 0.08 0.20 rg\n" . dc_pdf_rect($tableX, $tableY, $labelW + $valueW, $rowH, true);
    $content .= "1 1 1 rg\n";
    $content .= dc_pdf_bold_text('Particulars', $tableX + 14, $tableY + 7, 13);
    $content .= dc_pdf_bold_text('Details', $tableX + $labelW + 14, $tableY + 7, 13);
    $content .= "0 0 0 rg\n";
    $content .= dc_pdf_rect($tableX, $tableY, $labelW + $valueW, $rowH, false);
    $content .= dc_pdf_line($tableX + $labelW, $tableY, $tableX + $labelW, $tableY + $rowH);

    $y = $tableY - $rowH;
    foreach ($rows as $row) {
        $valueLines = dc_pdf_wrap_text($row[1], 34);
        $height = max($rowH, count($valueLines) * 12 + 10);
        $content .= dc_pdf_rect($tableX, $y - ($height - $rowH), $labelW + $valueW, $height, false);
        $content .= dc_pdf_line($tableX + $labelW, $y - ($height - $rowH), $tableX + $labelW, $y + $rowH);
        $content .= dc_pdf_bold_text($row[0], $tableX + 12, $y + 7, 11);
        foreach ($valueLines as $lineIndex => $line) {
            $content .= dc_pdf_text($line, $tableX + $labelW + 12, $y + 7 - ($lineIndex * 12), 11);
        }
        $y -= $height;
    }

    list($statement, $statementHeight) = dc_pdf_text_block(dc_certificate_statement($v), 82, 235, 10, 56, 13);
    $content .= $statement;
    list($noteText, $noteHeight) = dc_pdf_text_block(dc_certificate_note(), 82, 174, 9, 58, 12);
    $content .= $noteText;

    if (is_file($qrPath)) {
        $images['ImQr'] = $qrPath;
        $content .= dc_pdf_image_draw('ImQr', 250, 112, 82, 82);
    }
    $logoAsset = dc_preferred_pdf_logo_asset();
    if ($logoAsset !== '') {
        $images['ImSeal'] = dc_asset_path($logoAsset);
        $content .= dc_pdf_image_draw('ImSeal', 380, 112, 96, 72);
    }
    $content .= "0.02 0.08 0.20 rg\n" . dc_pdf_rect(54, 54, 487, 38, true);
    $content .= "1 1 1 rg\n";
    $content .= dc_pdf_center_text(DC_COMPANY_EMAIL . ' | ' . DC_COMPANY_PHONE . ' | ' . DC_COMPANY_WEBSITE, 70, 9);
    $content .= "0 0 0 rg\n";
    return dc_simple_pdf($content, $images);
}

function dc_pdf_image_object($path) {
    $info = getimagesize($path);
    if (!$info) {
        return '';
    }
    $width = (int)$info[0];
    $height = (int)$info[1];
    if ($info[2] === IMAGETYPE_JPEG) {
        $data = file_get_contents($path);
        return "<< /Type /XObject /Subtype /Image /Width " . $width . " /Height " . $height . " /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter /DCTDecode /Length " . strlen($data) . " >>\nstream\n" . $data . "\nendstream";
    }
    if ($info[2] === IMAGETYPE_PNG && function_exists('imagecreatefrompng')) {
        $image = imagecreatefrompng($path);
        if (!$image) {
            return '';
        }
        $raw = '';
        for ($y = 0; $y < $height; $y++) {
            for ($x = 0; $x < $width; $x++) {
                $rgb = imagecolorat($image, $x, $y);
                $raw .= chr(($rgb >> 16) & 0xFF) . chr(($rgb >> 8) & 0xFF) . chr($rgb & 0xFF);
            }
        }
        imagedestroy($image);
        $data = gzcompress($raw);
        return "<< /Type /XObject /Subtype /Image /Width " . $width . " /Height " . $height . " /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter /FlateDecode /Length " . strlen($data) . " >>\nstream\n" . $data . "\nendstream";
    }
    return '';
}

function dc_simple_pdf($content, $images = array()) {
    $objects = array();
    $objects[] = "<< /Type /Catalog /Pages 2 0 R >>";
    $objects[] = "<< /Type /Pages /Kids [3 0 R] /Count 1 >>";
    $imageResources = '';
    $imageObjectIds = array();
    $nextId = 7;
    foreach ($images as $name => $path) {
        $imageObjectIds[$name] = $nextId++;
        $imageResources .= '/' . $name . ' ' . $imageObjectIds[$name] . ' 0 R ';
    }
    $objects[] = "<< /Type /Page /Parent 2 0 R /MediaBox [0 0 595 842] /Resources << /Font << /F1 4 0 R /F2 5 0 R >> /XObject << " . $imageResources . " >> >> /Contents 6 0 R >>";
    $objects[] = "<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>";
    $objects[] = "<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica-Bold >>";
    $objects[] = "<< /Length " . strlen($content) . " >>\nstream\n" . $content . "endstream";
    foreach ($images as $path) {
        $objects[] = dc_pdf_image_object($path);
    }
    $pdf = "%PDF-1.4\n";
    $offsets = array(0);
    foreach ($objects as $i => $obj) {
        $offsets[] = strlen($pdf);
        $pdf .= ($i + 1) . " 0 obj\n" . $obj . "\nendobj\n";
    }
    $xref = strlen($pdf);
    $pdf .= "xref\n0 " . (count($objects) + 1) . "\n0000000000 65535 f \n";
    for ($i = 1; $i <= count($objects); $i++) {
        $pdf .= sprintf("%010d 00000 n \n", $offsets[$i]);
    }
    $pdf .= "trailer\n<< /Size " . (count($objects) + 1) . " /Root 1 0 R >>\nstartxref\n" . $xref . "\n%%EOF";
    return $pdf;
}
