<?php
/**
 * Sistem Pengurusan Fail MAINPP - Pemprosesan Draf Surat & Memo
 * Kemaskini: 21 Ogos 2026
 * - Sokongan markMemoDeliveryRecipientsDelivered & activateMemoApprovalRecipients
 * - Logik permohonan pindaan (perlu_pindaan_penyedia) & integrasi push notification
 */
require_once 'auth.php';
include 'db.php';
requireLogin($conn);

$action = $_GET['action'] ?? '';
$role = $_SESSION['role'] ?? 'user';
$user_department = currentUserDepartment($conn);

function buildDraftRecipientSummary($recipient_name, $recipient_organization, $attention_to) {
    $parts = [];
    $recipient_name = trim((string) $recipient_name);
    $recipient_organization = trim((string) $recipient_organization);
    $attention_to = trim((string) $attention_to);

    if ($recipient_organization !== '') {
        $parts[] = $recipient_organization;
    }
    if ($recipient_name !== '') {
        $parts[] = $recipient_name;
    }
    if ($attention_to !== '') {
        $parts[] = 'Perhatian: ' . $attention_to;
    }

    return !empty($parts) ? implode(' | ', $parts) : '-';
}

function normalizeMemoDisplayPositions($checked_values, $fallback_value = '') {
    $values = [];
    foreach ((array) $checked_values as $value) {
        $value = trim((string) $value);
        if ($value !== '' && !in_array($value, $values, true)) {
            $values[] = $value;
        }
    }

    $fallback_value = trim((string) $fallback_value);
    if (empty($values) && $fallback_value !== '') {
        $values[] = $fallback_value;
    }

    return implode("\n", $values);
}

function splitMemoDisplayPositions($value) {
    $items = preg_split('/\r\n|\r|\n/', (string) $value);
    $values = [];
    foreach ($items as $item) {
        $item = trim((string) $item);
        if ($item !== '' && !in_array($item, $values, true)) {
            $values[] = $item;
        }
    }
    return $values;
}

function memoDistributionRecipientLabel() {
    return 'Seperti dalam Senarai Edaran';
}

function decodeSelectedDistributionStaffIds($value) {
    return function_exists('normalizeStaffDistributionIds') ? normalizeStaffDistributionIds($value) : [];
}

function memoUsesDistributionRecipients($kepada) {
    return in_array(memoDistributionRecipientLabel(), splitMemoDisplayPositions($kepada), true);
}

function ensureMemoDistributionRecipientSelection($kepada, $include_distribution_page, $selected_distribution_staff_ids) {
    if (!memoUsesDistributionRecipients($kepada)) {
        return;
    }
    if (!$include_distribution_page || empty($selected_distribution_staff_ids)) {
        throw new Exception('distribution_recipient_required');
    }
}

function getMemoPersonRecipientToken($user_id, $fullname) {
    $user_id = (int) $user_id;
    $fullname = trim((string) $fullname);
    return $user_id > 0 && $fullname !== '' ? 'Pegawai: ' . $fullname . ' (user:' . $user_id . ')' : '';
}

function parseMemoPersonRecipientToken($value) {
    $value = trim((string) $value);
    if (preg_match('/^Pegawai:\s*(.*?)\s*\(user:(\d+)\)$/iu', $value, $matches)) {
        return [
            'name' => trim((string) $matches[1]),
            'user_id' => (int) $matches[2],
        ];
    }
    return null;
}

function sanitizeDraftLetterInlineStyle($style, $default_font_size = '16px') {
    $safe_styles = [];
    foreach (explode(';', (string) $style) as $declaration) {
        $parts = explode(':', $declaration, 2);
        if (count($parts) !== 2) {
            continue;
        }
        $property = strtolower(trim($parts[0]));
        $value = trim($parts[1]);
        if ($property === 'text-align' && preg_match('/^(left|center|right|justify)$/i', $value)) {
            $safe_styles[] = 'text-align: ' . strtolower($value);
        } elseif ($property === 'margin-left' && preg_match('/^(?:0|[0-9]+(?:\.[0-9]+)?(?:cm|mm|pt|px))$/i', $value)) {
            $safe_styles[] = 'margin-left: ' . strtolower($value);
        } elseif (in_array($property, ['height', 'min-height', 'width', 'min-width'], true) && preg_match('/^(?:0|[0-9]+(?:\.[0-9]+)?(?:cm|mm|pt|px))$/i', $value)) {
            $safe_styles[] = $property . ': ' . strtolower($value);
        } elseif ($property === 'display' && in_array(strtolower($value), ['block', 'flex'], true)) {
            $safe_styles[] = 'display: ' . strtolower($value);
        } elseif ($property === 'align-items' && strtolower($value) === 'center') {
            $safe_styles[] = 'align-items: center';
        } elseif ($property === 'justify-content' && in_array(strtolower($value), ['center', 'flex-start'], true)) {
            $safe_styles[] = 'justify-content: ' . strtolower($value);
        } elseif ($property === 'margin' && preg_match('/^(?:0|[0-9]+(?:\.[0-9]+)?(?:cm|mm|pt|px))$/i', $value)) {
            $safe_styles[] = 'margin: ' . strtolower($value);
        } elseif ($property === 'margin-top' && preg_match('/^(?:0|[0-9]+(?:\.[0-9]+)?(?:cm|mm|pt|px))$/i', $value)) {
            $safe_styles[] = 'margin-top: ' . strtolower($value);
        } elseif ($property === 'font-size' && preg_match('/^8(?:px|pt)$/i', $value)) {
            $safe_styles[] = 'font-size: 8px';
        } elseif ($property === 'line-height' && preg_match('/^(?:1|1\.0|1\.00)$/i', $value)) {
            $safe_styles[] = 'line-height: 1';
        } elseif (in_array($property, ['line-height', 'font-size', 'font-family'], true)) {
            continue;
        }
    }

    $safe_styles[] = 'font-family: Arial, Helvetica, sans-serif';
    if (!preg_grep('/^font-size\s*:/i', $safe_styles)) {
        $safe_styles[] = 'font-size: ' . $default_font_size;
    }
    if (!preg_grep('/^line-height\s*:/i', $safe_styles)) {
        $safe_styles[] = 'line-height: 1.5';
    }

    return implode('; ', array_unique($safe_styles));
}

function applyDraftLetterBodyTypography($html, $default_font_size = '16px') {
    $html = trim((string) $html);
    if ($html === '') {
        return '';
    }

    return preg_replace_callback('/<(p|div|li|td|th|blockquote|h3|h4|span)(\s[^>]*)?>/i', function ($matches) use ($default_font_size) {
        $tag = $matches[1];
        $attrs = $matches[2] ?? '';

        if (preg_match('/style\s*=\s*(["\'])(.*?)\1/i', $attrs, $style_match)) {
            $quote = $style_match[1];
            $safe_style = sanitizeDraftLetterInlineStyle($style_match[2], $default_font_size);
            $attrs = preg_replace(
                '/style\s*=\s*(["\']).*?\1/i',
                'style=' . $quote . htmlspecialchars($safe_style, ENT_QUOTES) . $quote,
                $attrs,
                1
            );
        } else {
            $attrs .= ' style="font-family: Arial, Helvetica, sans-serif; font-size: ' . $default_font_size . '; line-height: 1.5"';
        }

        return '<' . $tag . $attrs . '>';
    }, $html);
}

function normalizeQuillListHtml($html) {
    $html = (string) $html;
    if (stripos($html, 'data-list') === false && stripos($html, 'ql-ui') === false) {
        return $html;
    }

    $html = preg_replace('/<span\b(?=[^>]*\bclass\s*=\s*(["\'])[^"\']*\bql-ui\b[^"\']*\1)[^>]*>\s*<\/span>/i', '', $html);
    return preg_replace_callback('/<ol\b([^>]*)>(.*?)<\/ol>/is', function ($matches) {
        $content = $matches[2];
        if (stripos($content, 'data-list') === false) {
            return $matches[0];
        }

        preg_match_all('/<li\b([^>]*)>(.*?)<\/li>/is', $content, $items, PREG_SET_ORDER);
        if (empty($items)) {
            return $matches[0];
        }

        $html_parts = [];
        $current_type = '';
        foreach ($items as $item) {
            $attrs = $item[1] ?? '';
            $item_type = preg_match('/\bdata-list\s*=\s*(["\'])bullet\1/i', $attrs) ? 'ul' : 'ol';
            $attrs = preg_replace('/\s*data-list\s*=\s*(["\']).*?\1/i', '', $attrs);
            $attrs = preg_replace('/\s*data-list\s*=\s*[^\s>]+/i', '', $attrs);
            if ($current_type !== $item_type) {
                if ($current_type !== '') {
                    $html_parts[] = '</' . $current_type . '>';
                }
                $current_type = $item_type;
                $html_parts[] = '<' . $current_type . '>';
            }
            $html_parts[] = '<li' . $attrs . '>' . $item[2] . '</li>';
        }
        if ($current_type !== '') {
            $html_parts[] = '</' . $current_type . '>';
        }

        return implode('', $html_parts);
    }, $html);
}

function sanitizeDraftLetterBodyHtml($html, $default_font_size = '16px') {
    $html = trim((string) $html);
    if ($html === '') {
        return '';
    }

    $html = preg_replace('/(<div\b[^>]*class\s*=\s*(["\'])generated-closing-lock\s+signature-block\2)\s+signature-block(?:"|\')/i', '$1', $html);
    $html = normalizeQuillListHtml($html);
    $allowed_tags = '<p><br><strong><b><em><i><u><ol><ul><li><table><thead><tbody><tr><th><td><colgroup><col><blockquote><h3><h4><div><span><img>';
    $html = strip_tags($html, $allowed_tags);
    $html = preg_replace('/\s+on[a-z]+\s*=\s*(".*?"|\'.*?\'|[^\s>]+)/i', '', $html);
    $html = preg_replace_callback('/\s+style\s*=\s*(["\'])(.*?)\1/i', function ($matches) use ($default_font_size) {
        $safe_style = sanitizeDraftLetterInlineStyle($matches[2], $default_font_size);
        if (preg_match('/(?:^|;)\s*text-align\s*:\s*(left|center|right|justify)\s*(?:;|$)/i', $matches[2], $alignment)) {
            return ' align="' . strtolower($alignment[1]) . '"' . ' style="' . htmlspecialchars($safe_style, ENT_QUOTES) . '"';
        }
        return ' style="' . htmlspecialchars($safe_style, ENT_QUOTES) . '"';
    }, $html);
    $html = preg_replace('/\s+style\s*=\s*(?!["\'])[^\s>]+/i', '', $html);
    $html = preg_replace('/\s+id\s*=\s*(".*?"|\'.*?\'|[^\s>]+)/i', '', $html);
    $html = preg_replace_callback('/\s+class\s*=\s*(["\'])(.*?)\1/i', function ($matches) {
        $classes = preg_split('/\s+/', trim((string) $matches[2]));
        $allowed_classes = array_values(array_intersect($classes, ['generated-closing-lock', 'signature-block', 'prepared-by-line']));
        return !empty($allowed_classes)
            ? ' class="' . htmlspecialchars(implode(' ', $allowed_classes), ENT_QUOTES) . '"'
            : '';
    }, $html);
    $html = preg_replace_callback('/\s+class\s*=\s*(?!["\'])([^\s>]+)/i', function ($matches) {
        $classes = preg_split('/\s+/', trim((string) $matches[1]));
        $allowed_classes = array_values(array_intersect($classes, ['generated-closing-lock', 'signature-block', 'prepared-by-line']));
        return !empty($allowed_classes)
            ? ' class="' . htmlspecialchars(implode(' ', $allowed_classes), ENT_QUOTES) . '"'
            : '';
    }, $html);
    $html = preg_replace('/<div\b(?=[^>]*data-generated-closing\s*=\s*(["\'])1\1)(?![^>]*\sclass\s*=)/i', '<div class="generated-closing-lock signature-block"', $html);
    $html = preg_replace('/javascript\s*:/i', '', $html);
    $html = preg_replace_callback('/<img\b[^>]*>/i', function ($matches) {
        $tag = $matches[0];
        if (!preg_match('/\s+src\s*=\s*(["\'])(.*?)\1/i', $tag, $src_match)) {
            return '';
        }

        $src = str_replace('\\', '/', trim(html_entity_decode($src_match[2], ENT_QUOTES)));
        if (!preg_match('#^uploads/signatures/[A-Za-z0-9._/-]+\.(?:png|jpe?g|gif|webp)$#i', $src)) {
            return '';
        }

        $full_path = __DIR__ . '/' . $src;
        if (!is_file($full_path)) {
            return '';
        }

        return '<img src="' . htmlspecialchars($src, ENT_QUOTES) . '" alt="Tandatangan Digital" style="max-width:150px;max-height:58px;object-fit:contain;">';
    }, $html);

    return applyDraftLetterBodyTypography(trim($html), $default_font_size);
}

function draftLetterHasGeneratedClosing($letter_body, $letter_pages_json = '') {
    $haystack = (string) $letter_body . "\n" . (string) $letter_pages_json;

    return stripos($haystack, 'data-generated-closing') !== false
        || stripos($haystack, 'generated-closing-lock') !== false
        || stripos($haystack, 'data-signature-block') !== false;
}

function savePostedDocumentDigitalSignature($user_id, $draft_id, $signature_data) {
    $signature_data = trim((string) $signature_data);
    if ($signature_data === '') {
        return '';
    }

    if (!preg_match('#^data:image/(png|jpeg|jpg|webp);base64,([A-Za-z0-9+/=\r\n]+)$#', $signature_data, $matches)) {
        throw new Exception('signature_invalid');
    }

    $binary = base64_decode(preg_replace('/\s+/', '', $matches[2]), true);
    if ($binary === false || strlen($binary) < 100 || strlen($binary) > 1024 * 1024) {
        throw new Exception('signature_invalid');
    }

    $image_info = @getimagesizefromstring($binary);
    if (!$image_info || empty($image_info['mime']) || strpos($image_info['mime'], 'image/') !== 0) {
        throw new Exception('signature_invalid');
    }

    $upload_dir = __DIR__ . '/uploads/signatures';
    if (!is_dir($upload_dir) && !mkdir($upload_dir, 0755, true)) {
        throw new Exception('signature_invalid');
    }

    $user_id = max(0, (int) $user_id);
    $draft_id = max(0, (int) $draft_id);
    $filename = 'document_signature_user_' . $user_id . '_draft_' . $draft_id . '_' . date('Ymd_His') . '_' . bin2hex(random_bytes(4)) . '.png';
    $full_path = $upload_dir . '/' . $filename;
    if (file_put_contents($full_path, $binary) === false) {
        throw new Exception('signature_invalid');
    }

    return 'uploads/signatures/' . $filename;
}

function replacePostedDocumentDigitalSignatureSource($value, $signature_data, $signature_path) {
    $signature_data = trim((string) $signature_data);
    $signature_path = trim((string) $signature_path);
    if ($signature_data === '' || $signature_path === '') {
        return $value;
    }

    return str_replace([$signature_data, str_replace('/', '\\/', $signature_data)], $signature_path, (string) $value);
}

function sanitizeDraftLetterPagesJson($json, $default_font_size = '16px') {
    $decoded = json_decode((string) $json, true);
    $pages = [];

    if (is_array($decoded)) {
        foreach ($decoded as $page) {
            $clean_page = sanitizeDraftLetterBodyHtml($page, $default_font_size);
            if (draftLetterBodyHasContent($clean_page)) {
                $pages[] = $clean_page;
            }
        }
    }

    return $pages;
}

function replaceSuratRasmiGeneratedReferenceLine($html, $reference_display) {
    $reference_display = htmlspecialchars(trim((string) $reference_display), ENT_QUOTES);
    if ($reference_display === '') {
        return $html;
    }

    return preg_replace_callback(
        '/(<p\b(?=[^>]*data-surat-rasmi-generated-line=(?:"ref"|\'ref\'))[^>]*>)(.*?)(<\/p>)/is',
        function ($matches) use ($reference_display) {
            return $matches[1] . $reference_display . $matches[3];
        },
        (string) $html
    );
}

function applySuratRasmiGeneratedReferenceToPages($pages, $reference_display) {
    $updated_pages = [];
    foreach ((array) $pages as $page) {
        $updated_pages[] = replaceSuratRasmiGeneratedReferenceLine($page, $reference_display);
    }
    return $updated_pages;
}

function sanitizeDraftApprovalRouteBodiesJson($json, $default_font_size = '16px') {
    $decoded = json_decode((string) $json, true);
    $bodies = [];

    if (is_array($decoded)) {
        foreach ($decoded as $key => $body) {
            $key = trim((string) $key);
            if ($key === '' || !preg_match('/^(?:user:\d+|position:.+)$/', $key)) {
                continue;
            }
            $bodies[$key] = sanitizeDraftLetterBodyHtml($body, $default_font_size);
        }
    }

    return json_encode($bodies, JSON_UNESCAPED_UNICODE);
}

function approvalRouteBodiesCoverRecipients($json, $recipients) {
    $bodies = json_decode((string) $json, true);
    if (!is_array($bodies) || empty($recipients)) {
        return false;
    }

    foreach ($recipients as $recipient) {
        $user_key = 'user:' . (int) ($recipient['id'] ?? $recipient['user_id'] ?? 0);
        $position_key = 'position:' . trim((string) ($recipient['routing_position'] ?? $recipient['position_label'] ?? ''));
        $body = $bodies[$user_key] ?? $bodies[$position_key] ?? '';
        if (!draftLetterBodyHasContent($body)) {
            return false;
        }
    }

    return true;
}

function sanitizeDraftLetterPageSignersJson($json, $page_count) {
    $decoded = json_decode((string) $json, true);
    $allowed = ['preparer', 'department_officer'];
    $page_count = max(1, (int) $page_count);
    $signers = [];

    for ($index = 0; $index < $page_count; $index++) {
        $value = is_array($decoded) ? (string) ($decoded[$index] ?? '') : '';
        $signers[] = in_array($value, $allowed, true) ? $value : ($index === 0 ? 'preparer' : '');
    }

    return json_encode($signers, JSON_UNESCAPED_UNICODE);
}

function draftLetterBodyHasContent($html) {
    $plain = html_entity_decode(strip_tags((string) $html), ENT_QUOTES | ENT_HTML5, 'UTF-8');
    $plain = preg_replace('/[\s\x{00A0}]+/u', '', $plain);

    return trim((string) $plain) !== '';
}

function stripSuratRasmiGeneratedLinesForContentCheck($html) {
    $html = (string) $html;
    $html = preg_replace('/<p\b(?=[^>]*data-surat-rasmi-generated-line=(?:"ref"|\'ref\'|"date"|\'date\'))[^>]*>.*?<\/p>/is', '', $html);
    return $html;
}

function suratRasmiBodyHasUserContent($html) {
    return draftLetterBodyHasContent(stripSuratRasmiGeneratedLinesForContentCheck($html));
}

function saveDraftSignatureUpload($input_name, $existing_path = '') {
    if (empty($_FILES[$input_name]) || !isset($_FILES[$input_name]['error']) || $_FILES[$input_name]['error'] === UPLOAD_ERR_NO_FILE) {
        return trim((string) $existing_path);
    }

    if ($_FILES[$input_name]['error'] !== UPLOAD_ERR_OK) {
        throw new Exception('Gagal memuat naik tandatangan digital.');
    }

    $tmp_name = $_FILES[$input_name]['tmp_name'] ?? '';
    $original_name = basename((string) ($_FILES[$input_name]['name'] ?? 'signature'));
    $extension = strtolower(pathinfo($original_name, PATHINFO_EXTENSION));
    $allowed = ['png', 'jpg', 'jpeg', 'webp'];

    if (!in_array($extension, $allowed, true)) {
        throw new Exception('Format tandatangan digital hanya PNG, JPG, JPEG atau WEBP.');
    }

    $upload_dir = 'uploads/signatures/';
    if (!is_dir($upload_dir)) {
        mkdir($upload_dir, 0775, true);
    }

    $filename = 'sign_' . date('YmdHis') . '_' . bin2hex(random_bytes(4)) . '.' . $extension;
    $target_path = $upload_dir . $filename;

    if (!move_uploaded_file($tmp_name, $target_path)) {
        throw new Exception('Gagal menyimpan fail tandatangan digital.');
    }

    return $target_path;
}

function getSupportUserById($conn, $support_user_id) {
    $support_user_id = (int) $support_user_id;
    if ($support_user_id <= 0) {
        return null;
    }

    $stmt = mysqli_prepare($conn, "SELECT id, fullname, email, department, position, role FROM users WHERE id = ? AND status = 'approved' LIMIT 1");
    if (!$stmt) {
        return null;
    }
    mysqli_stmt_bind_param($stmt, "i", $support_user_id);
    mysqli_stmt_execute($stmt);
    $user = mysqli_fetch_assoc(mysqli_stmt_get_result($stmt));

    return $user ?: null;
}

function getApprovedUserById($conn, $user_id) {
    return getSupportUserById($conn, $user_id);
}

function applyDepartmentHeadSignatory(&$signatory_name, &$signatory_position, &$signatory_department, $department_head_user, $fallback_department = '') {
    if (!$department_head_user) {
        return;
    }

    $signatory_name = trim((string) ($department_head_user['fullname'] ?? $signatory_name));
    $signatory_department = trim((string) ($department_head_user['department'] ?? ($fallback_department ?: $signatory_department)));
    $signatory_position = getDisplayPositionForUser($department_head_user, $signatory_department) ?: trim((string) ($department_head_user['position'] ?? $signatory_position));
}

function normalizeMemoRoutingSelection($positions, $orders) {
    $selected = [];
    foreach ((array) $positions as $index => $position) {
        $position = trim((string) $position);
        if ($position === '' || isset($selected[$position])) {
            continue;
        }
        $order = max(1, (int) (($orders[$position] ?? 0) ?: ($index + 1)));
        $selected[$position] = [
            'position' => $position,
            'order' => $order,
            'index' => (int) $index,
        ];
    }
    uasort($selected, function ($left, $right) {
        return [$left['order'], $left['index']] <=> [$right['order'], $right['index']];
    });

    $normalized = [];
    $route_order = 1;
    foreach ($selected as $item) {
        $normalized[] = [
            'position' => $item['position'],
            'order' => $route_order++,
        ];
    }
    return $normalized;
}

function resolveMemoApprovalRecipients($conn, $kepada, $melalui, $routing_selection, $preparer_user_id, $excluded_user_ids = [], $exclude_preparer = true, $distribution_staff_ids = []) {
    $requested = [];
    $kepada_positions = splitMemoDisplayPositions($kepada);
    $melalui_positions = splitMemoDisplayPositions($melalui);
    $excluded_lookup = array_fill_keys(array_map('intval', (array) $excluded_user_ids), true);
    $append_recipient = function (&$recipients, $user, $request_meta, $fallback_position = '') use ($preparer_user_id, $excluded_lookup, $exclude_preparer) {
        $user_id = (int) ($user['id'] ?? 0);
        if ($user_id <= 0 || ($exclude_preparer && $user_id === (int) $preparer_user_id) || isset($excluded_lookup[$user_id])) {
            return;
        }
        $user['routing_position'] = trim((string) (($user['routing_position'] ?? '') ?: ($fallback_position ?: getDisplayPositionForUser($user))));
        $user['source_type'] = $request_meta['source_type'] ?? 'tambahan';
        $user['route_order'] = max(1, (int) ($request_meta['route_order'] ?? 1));
        $recipients[$user_id] = $user;
    };

    foreach ((array) $routing_selection as $item) {
        $position = trim((string) ($item['position'] ?? ''));
        if ($position !== '' && !isset($requested[$position])) {
            $requested[$position] = [
                'source_type' => in_array($position, $kepada_positions, true) ? 'kepada' : (in_array($position, $melalui_positions, true) ? 'melalui' : 'tambahan'),
                'route_order' => max(1, (int) ($item['order'] ?? 1)),
            ];
        }
    }

    $recipients = [];
    $all_staff_request = $requested['Semua Kakitangan'] ?? null;
    $all_kbku_request = $requested['Semua KBKU'] ?? null;
    $distribution_request = $requested[memoDistributionRecipientLabel()] ?? null;
    if ($all_staff_request) {
        $staff_stmt = mysqli_prepare($conn, "SELECT id, fullname, email, department, position, role FROM users WHERE status = 'approved' ORDER BY department, fullname");
        if ($staff_stmt) {
            mysqli_stmt_execute($staff_stmt);
            $staff_rows = mysqli_fetch_all(mysqli_stmt_get_result($staff_stmt), MYSQLI_ASSOC);
            foreach ($staff_rows as $staff_user) {
                $append_recipient($recipients, $staff_user, $all_staff_request, getDisplayPositionForUser($staff_user));
            }
        }
    }
    if ($all_kbku_request) {
        foreach (getDepartmentHeadOfficerUsers($conn) as $head_user) {
            $append_recipient($recipients, $head_user, $all_kbku_request, getDisplayPositionForUser($head_user));
        }
    }
    if ($distribution_request) {
        $distribution_ids = decodeSelectedDistributionStaffIds($distribution_staff_ids);
        if (!empty($distribution_ids)) {
            $id_list = implode(',', array_map('intval', $distribution_ids));
            $sql = "SELECT u.id, u.fullname, u.email, u.department, u.position, u.role, s.name AS distribution_name
                FROM staff_distribution_list s
                INNER JOIN users u ON u.id = s.user_id AND u.status = 'approved'
                WHERE s.deleted_at IS NULL
                  AND s.agency_type = 'MAINPP'
                  AND s.user_id IS NOT NULL
                  AND s.id IN ($id_list)
                ORDER BY s.name, u.fullname";
            $distribution_stmt = mysqli_prepare($conn, $sql);
            if ($distribution_stmt) {
                mysqli_stmt_execute($distribution_stmt);
                $distribution_rows = mysqli_fetch_all(mysqli_stmt_get_result($distribution_stmt), MYSQLI_ASSOC);
                foreach ($distribution_rows as $distribution_user) {
                    $fallback_label = trim((string) ($distribution_user['distribution_name'] ?? ''));
                    $append_recipient($recipients, $distribution_user, $distribution_request, $fallback_label ?: getDisplayPositionForUser($distribution_user));
                }
            }
        }
    }
    foreach ($requested as $position => $request_meta) {
        $person_token = parseMemoPersonRecipientToken($position);
        if (!$person_token) {
            continue;
        }
        $person_user = getApprovedUserById($conn, (int) $person_token['user_id']);
        if ($person_user) {
            $append_recipient($recipients, $person_user, $request_meta, $person_token['name']);
        }
    }
    foreach (getMemoRoutingUsers($conn) as $user) {
        $routing_position = $user['routing_position'] ?? '';
        if (!isset($requested[$routing_position])) {
            continue;
        }
        $append_recipient($recipients, $user, $requested[$routing_position], $routing_position);
    }

    $recipients = array_values($recipients);
    usort($recipients, function ($left, $right) {
        return [(int) ($left['route_order'] ?? 1), (int) ($left['id'] ?? 0)]
            <=> [(int) ($right['route_order'] ?? 1), (int) ($right['id'] ?? 0)];
    });
    return $recipients;
}

function syncMemoApprovalRecipients($conn, $draft_id, $recipients, $activate_now) {
    $draft_id = (int) $draft_id;
    $delete_stmt = mysqli_prepare($conn, "DELETE FROM letter_approval_recipients WHERE draft_id = ?");
    mysqli_stmt_bind_param($delete_stmt, "i", $draft_id);
    mysqli_stmt_execute($delete_stmt);

    $insert_stmt = mysqli_prepare($conn, "INSERT INTO letter_approval_recipients
        (draft_id, user_id, position_label, source_type, route_order, status, requested_at)
        VALUES (?, ?, ?, ?, ?, ?, NULL)");
    if (!$insert_stmt) {
        throw new Exception(mysqli_error($conn));
    }

    foreach ($recipients as $recipient) {
        $user_id = (int) ($recipient['id'] ?? 0);
        $position_label = trim((string) ($recipient['routing_position'] ?? ''));
        $source_type = trim((string) ($recipient['source_type'] ?? 'tambahan'));
        $route_order = max(1, (int) ($recipient['route_order'] ?? 1));
        $status = 'belum_mula';
        mysqli_stmt_bind_param($insert_stmt, "iissis", $draft_id, $user_id, $position_label, $source_type, $route_order, $status);
        if (!mysqli_stmt_execute($insert_stmt)) {
            throw new Exception(mysqli_error($conn));
        }
    }
    if ($activate_now) {
        activateMemoApprovalRecipients($conn, $draft_id);
    }
}

function buildMemoFinalRecipientSelection($kepada) {
    $selection = [];
    $order = 1;
    foreach (splitMemoDisplayPositions($kepada) as $position) {
        $position = trim((string) $position);
        if ($position === '') {
            continue;
        }
        $selection[] = [
            'position' => $position,
            'order' => $order++,
        ];
    }
    return $selection;
}

function syncMemoDeliveryRecipients($conn, $draft_id, $recipients, $delivered_now) {
    $draft_id = (int) $draft_id;
    $delete_stmt = mysqli_prepare($conn, "DELETE FROM letter_approval_recipients WHERE draft_id = ?");
    mysqli_stmt_bind_param($delete_stmt, "i", $draft_id);
    mysqli_stmt_execute($delete_stmt);

    $insert_stmt = mysqli_prepare($conn, "INSERT INTO letter_approval_recipients
        (draft_id, user_id, position_label, source_type, route_order, status, decision, requested_at, approved_at, responded_at)
        VALUES (?, ?, ?, 'kepada', ?, ?, ?, " . ($delivered_now ? "NOW()" : "NULL") . ", " . ($delivered_now ? "NOW()" : "NULL") . ", " . ($delivered_now ? "NOW()" : "NULL") . ")");
    if (!$insert_stmt) {
        throw new Exception(mysqli_error($conn));
    }

    foreach ($recipients as $recipient) {
        $user_id = (int) ($recipient['id'] ?? 0);
        if ($user_id <= 0) {
            continue;
        }
        $position_label = trim((string) ($recipient['routing_position'] ?? getDisplayPositionForUser($recipient)));
        $route_order = max(1, (int) ($recipient['route_order'] ?? 1));
        $status = $delivered_now ? 'lulus' : 'belum_mula';
        $decision = $delivered_now ? 'lulus' : 'belum_diputuskan';
        mysqli_stmt_bind_param($insert_stmt, "iisiss", $draft_id, $user_id, $position_label, $route_order, $status, $decision);
        if (!mysqli_stmt_execute($insert_stmt)) {
            throw new Exception(mysqli_error($conn));
        }
    }
}

function markMemoDeliveryRecipientsDelivered($conn, $draft_id) {
    $draft_id = (int) $draft_id;
    $stmt = mysqli_prepare($conn, "UPDATE letter_approval_recipients
        SET status = 'lulus',
            decision = 'lulus',
            requested_at = IF(requested_at IS NULL, NOW(), requested_at),
            approved_at = IF(approved_at IS NULL, NOW(), approved_at),
            responded_at = IF(responded_at IS NULL, NOW(), responded_at)
        WHERE draft_id = ?
          AND status IN ('belum_mula','menunggu','menunggu_tandatangan')");
    mysqli_stmt_bind_param($stmt, "i", $draft_id);
    if (!mysqli_stmt_execute($stmt)) {
        throw new Exception(mysqli_error($conn));
    }
}

function activateMemoApprovalRecipients($conn, $draft_id) {
    $draft_id = (int) $draft_id;
    $order_stmt = mysqli_prepare($conn, "SELECT MIN(route_order) AS next_order
        FROM letter_approval_recipients
        WHERE draft_id = ? AND status = 'belum_mula'");
    mysqli_stmt_bind_param($order_stmt, "i", $draft_id);
    mysqli_stmt_execute($order_stmt);
    $next_order = (int) (mysqli_fetch_assoc(mysqli_stmt_get_result($order_stmt))['next_order'] ?? 0);
    if ($next_order <= 0) {
        return false;
    }

    $stmt = mysqli_prepare($conn, "UPDATE letter_approval_recipients
        SET status = 'menunggu', requested_at = NOW(), responded_at = NULL
        WHERE draft_id = ? AND route_order = ? AND status = 'belum_mula'");
    mysqli_stmt_bind_param($stmt, "ii", $draft_id, $next_order);
    $executed = mysqli_stmt_execute($stmt);

    if ($executed) {
        $draft_stmt = mysqli_prepare($conn, "SELECT subject, ref_no FROM letter_drafts WHERE id = ? LIMIT 1");
        if ($draft_stmt) {
            mysqli_stmt_bind_param($draft_stmt, "i", $draft_id);
            mysqli_stmt_execute($draft_stmt);
            $draft_res = mysqli_stmt_get_result($draft_stmt);
            $draft = $draft_res ? mysqli_fetch_assoc($draft_res) : [];
            sendMemoApprovalRecipientEmails($conn, $draft_id, $draft ?: []);
        }
    }

    return $executed;
}

function sendMemoApprovalRecipientEmails($conn, $draft_id, $draft) {
    $draft_id = (int) $draft_id;
    $subject_title = (string) ($draft['subject'] ?? 'Draf Surat');
    $ref_no = (string) ($draft['ref_no'] ?? '');

    foreach (getLetterApprovalRecipients($conn, $draft_id) as $recipient) {
        $status = strtolower((string) ($recipient['status'] ?? ''));
        $target_user_id = (int) ($recipient['user_id'] ?? $recipient['id'] ?? 0);

        if ($status !== 'menunggu' || $target_user_id <= 0) {
            continue;
        }

        // Deduplication check: check if an unread notification already exists for this draft and user
        $dup_check = mysqli_prepare($conn, "
            SELECT id FROM push_notifications
            WHERE user_id = ?
              AND notification_type = 'letter_pending_signature'
              AND is_read = 0
              AND payload_json LIKE ?
            LIMIT 1
        ");
        if ($dup_check) {
            $like_pattern = '%"draft_id":' . $draft_id . '%';
            mysqli_stmt_bind_param($dup_check, 'is', $target_user_id, $like_pattern);
            mysqli_stmt_execute($dup_check);
            $dup_res = mysqli_stmt_get_result($dup_check);
            if ($dup_res && mysqli_fetch_assoc($dup_res)) {
                // Already notified and unread, skip duplicate notification
                continue;
            }
        }

        if (!empty($recipient['email'])) {
            @sendDraftLetterSupportRequestEmail($recipient['email'], $recipient['fullname'] ?? '', $draft);
        }

        $push_title = '📝 Menunggu Tandatangan Anda';
        $push_body = "Surat/Memo \"{$subject_title}\" " . ($ref_no !== '' ? "(No. Ruj: {$ref_no}) " : "") . "memerlukan semakan dan tandatangan anda.";

        $notif_stmt = mysqli_prepare($conn, "
            INSERT INTO push_notifications
            (user_id, title, body, payload_json, notification_type, is_read, created_at)
            VALUES (?, ?, ?, ?, 'letter_pending_signature', 0, NOW())
        ");
        if ($notif_stmt) {
            $payload_json = json_encode([
                'draft_id' => $draft_id,
                'type' => 'letter_pending_signature',
                'status' => 'menunggu',
            ], JSON_UNESCAPED_UNICODE);
            mysqli_stmt_bind_param($notif_stmt, 'isss', $target_user_id, $push_title, $push_body, $payload_json);
            mysqli_stmt_execute($notif_stmt);
        }

        if (is_file(__DIR__ . '/includes/push_service.php')) {
            require_once __DIR__ . '/includes/push_service.php';
            if (function_exists('sendMainppPush')) {
                @sendMainppPush($conn, $target_user_id, $push_title, $push_body, [
                    'draft_id' => (string) $draft_id,
                    'type' => 'letter_pending_signature',
                ]);
            }
        }
    }
}

function buildDraftApprovalRoute($conn, $preparer_user_id, $folder_department, $department_officer_user_id, $recipients) {
    $preparer = getApprovedUserById($conn, $preparer_user_id);
    if (!$preparer) {
        throw new Exception('validation');
    }

    $needs_department_officer = !isHeadOfficerPosition($preparer['position'] ?? '');
    $department_officer_user = $needs_department_officer ? getSupportUserById($conn, $department_officer_user_id) : null;

    if (empty($recipients)) {
        throw new Exception('approval_recipient_required');
    }

    if ($needs_department_officer) {
        if (!$department_officer_user) {
            throw new Exception('department_officer_required');
        }

        if (!isHeadOfficerPosition($department_officer_user['position'] ?? '')) {
            throw new Exception('department_officer_required');
        }

        if (!isSameDepartmentDb($conn, $department_officer_user['department'] ?? '', $folder_department)) {
            throw new Exception('department_officer_department');
        }
    }

    $selected_ids = array_map(function ($recipient) {
        return (int) ($recipient['id'] ?? 0);
    }, $recipients);
    if ($needs_department_officer) {
        $selected_ids[] = (int) ($department_officer_user['id'] ?? 0);
    }
    $selected_ids = array_filter($selected_ids);
    if (count($selected_ids) !== count(array_unique($selected_ids))) {
        throw new Exception('duplicate_approver');
    }

    $preparer_id = (int) ($preparer['id'] ?? 0);
    if ($needs_department_officer && (int) ($department_officer_user['id'] ?? 0) === $preparer_id) {
        throw new Exception('duplicate_approver');
    }

    if ($needs_department_officer) {
        return [
            'needs_department_officer' => true,
            'department_officer_user' => $department_officer_user,
            'current_user' => $department_officer_user,
            'approval_status' => 'menunggu_pegawai_bahagian',
            'approval_stage' => 1,
            'department_officer_status' => 'menunggu',
            'department_officer_requested_now' => true,
        ];
    }

    return [
        'needs_department_officer' => false,
        'department_officer_user' => null,
        'current_user' => $recipients[0],
        'approval_status' => 'menunggu_pelulus',
        'approval_stage' => 2,
        'department_officer_status' => 'tidak_perlu',
        'department_officer_requested_now' => false,
    ];
}

function resolveMemoSignatoryUserByPosition($conn, $signatory_position) {
    $signatory_position = trim((string) $signatory_position);
    if ($signatory_position === '') {
        return null;
    }

    foreach (getMemoRoutingUsers($conn) as $user) {
        $routing_position = trim((string) ($user['routing_position'] ?? ''));
        $display_position = getDisplayPositionForUser($user);
        if (strcasecmp($routing_position, $signatory_position) === 0 || strcasecmp($display_position, $signatory_position) === 0) {
            return $user;
        }
    }

    return null;
}

function buildMemoSignatoryRoute($conn, $signatory_user, $preparer_user_id, $folder_department = '', $department_head_user = null) {
    $preparer = getApprovedUserById($conn, (int) $preparer_user_id);
    if (!$preparer) {
        throw new Exception('validation');
    }

    $signatory_user_id = (int) ($signatory_user['id'] ?? 0);
    $department_head_user_id = (int) ($department_head_user['id'] ?? 0);
    $needs_preparer_head_review = !isHeadOfficerPosition($preparer['position'] ?? '')
        && $department_head_user_id > 0
        && $signatory_user_id > 0
        && $signatory_user_id !== $department_head_user_id;

    if ($needs_preparer_head_review) {
        if (!isHeadOfficerPosition($department_head_user['position'] ?? '')) {
            throw new Exception('department_officer_required');
        }
        if (!isSameDepartmentDb($conn, $department_head_user['department'] ?? '', $folder_department)) {
            throw new Exception('department_officer_department');
        }

        return [
            'needs_department_officer' => true,
            'department_officer_user' => $signatory_user,
            'current_user' => $department_head_user,
            'approval_status' => 'menunggu_pegawai_bahagian',
            'approval_stage' => 1,
            'department_officer_status' => 'tidak_perlu',
            'department_officer_requested_now' => false,
            'memo_preparer_head_review_required' => true,
            'memo_preparer_head_user' => $department_head_user,
            'memo_preparer_head_status' => 'menunggu',
            'memo_preparer_head_requested_now' => true,
        ];
    }

    if ($signatory_user_id > 0 && $signatory_user_id !== (int) $preparer_user_id) {
        return [
            'needs_department_officer' => true,
            'department_officer_user' => $signatory_user,
            'current_user' => $signatory_user,
            'approval_status' => 'menunggu_pegawai_bahagian',
            'approval_stage' => 1,
            'department_officer_status' => 'menunggu',
            'department_officer_requested_now' => true,
            'memo_preparer_head_review_required' => false,
            'memo_preparer_head_user' => null,
            'memo_preparer_head_status' => 'tidak_perlu',
            'memo_preparer_head_requested_now' => false,
        ];
    }

    return [
        'needs_department_officer' => false,
        'department_officer_user' => null,
        'current_user' => null,
        'approval_status' => 'lulus',
        'approval_stage' => 0,
        'department_officer_status' => 'tidak_perlu',
        'department_officer_requested_now' => false,
        'memo_preparer_head_review_required' => false,
        'memo_preparer_head_user' => null,
        'memo_preparer_head_status' => 'tidak_perlu',
        'memo_preparer_head_requested_now' => false,
    ];
}

function buildSuratRasmiSignatoryRoute($conn, $signatory_user, $preparer_user_id, $folder_department = '', $department_head_user = null) {
    $preparer = getApprovedUserById($conn, (int) $preparer_user_id);
    if (!$preparer) {
        throw new Exception('validation');
    }

    $signatory_user_id = (int) ($signatory_user['id'] ?? 0);
    $signatory_department = normalizeDepartmentValue($signatory_user['department'] ?? '');
    $sender_department = normalizeDepartmentValue($folder_department ?: ($preparer['department'] ?? ''));
    $department_head_user_id = (int) ($department_head_user['id'] ?? 0);
    $preparer_is_department_head = $department_head_user_id > 0 && $department_head_user_id === (int) $preparer_user_id;
    $needs_preparer_head_review = $signatory_user_id > 0
        && $department_head_user_id > 0
        && !$preparer_is_department_head
        && $signatory_user_id !== $department_head_user_id
        && $sender_department !== ''
        && $signatory_department !== ''
        && !isSameDepartmentDb($conn, $sender_department, $signatory_department);

    if ($needs_preparer_head_review) {
        if (!isHeadOfficerPosition($department_head_user['position'] ?? '')) {
            throw new Exception('department_officer_required');
        }
        if (!isSameDepartmentDb($conn, $department_head_user['department'] ?? '', $sender_department)) {
            throw new Exception('department_officer_department');
        }

        return [
            'needs_department_officer' => true,
            'department_officer_user' => $signatory_user,
            'current_user' => $department_head_user,
            'approval_status' => 'menunggu_pegawai_bahagian',
            'approval_stage' => 1,
            'department_officer_status' => 'tidak_perlu',
            'department_officer_requested_now' => false,
            'memo_preparer_head_review_required' => true,
            'memo_preparer_head_user' => $department_head_user,
            'memo_preparer_head_status' => 'menunggu',
            'memo_preparer_head_requested_now' => true,
        ];
    }

    if ($signatory_user_id > 0 && $signatory_user_id !== (int) $preparer_user_id) {
        return [
            'needs_department_officer' => true,
            'department_officer_user' => $signatory_user,
            'current_user' => $signatory_user,
            'approval_status' => 'menunggu_pegawai_bahagian',
            'approval_stage' => 1,
            'department_officer_status' => 'menunggu',
            'department_officer_requested_now' => true,
            'memo_preparer_head_review_required' => false,
            'memo_preparer_head_user' => null,
            'memo_preparer_head_status' => 'tidak_perlu',
            'memo_preparer_head_requested_now' => false,
        ];
    }

    return [
        'needs_department_officer' => false,
        'department_officer_user' => null,
        'current_user' => null,
        'approval_status' => 'lulus',
        'approval_stage' => 0,
        'department_officer_status' => 'tidak_perlu',
        'department_officer_requested_now' => false,
        'memo_preparer_head_review_required' => false,
        'memo_preparer_head_user' => null,
        'memo_preparer_head_status' => 'tidak_perlu',
        'memo_preparer_head_requested_now' => false,
    ];
}

function resolveSuratRasmiFinalSigner($conn, $target, $management_signer_user_id, $other_department_head_user_id, $department_head_user, $fallback_department = '') {
    $target = in_array($target, ['management', 'other_department_head'], true) ? $target : 'department_head';

    if ($target === 'management') {
        $management_user = getSupportUserById($conn, (int) $management_signer_user_id);
        if (!$management_user || !isManagementApprovalUser($management_user)) {
            throw new Exception('signatory_required');
        }

        $management_user['routing_position'] = getDisplayPositionForUser($management_user) ?: ($management_user['position'] ?? 'Bahagian Pengurusan');
        $management_user['source_type'] = 'pengurusan';
        $management_user['route_order'] = 1;

        return [
            'target' => 'management',
            'signer_user' => $management_user,
            'recipients' => [$management_user],
            'signatory_name' => trim((string) ($management_user['fullname'] ?? '')),
            'signatory_position' => getDisplayPositionForUser($management_user) ?: trim((string) ($management_user['position'] ?? '')),
            'signatory_department' => normalizeDepartmentValue($management_user['department'] ?? 'Pengurusan'),
        ];
    }

    if ($target === 'other_department_head') {
        $other_head_user = getSupportUserById($conn, (int) $other_department_head_user_id);
        $other_department = normalizeDepartmentValue($other_head_user['department'] ?? '');
        if (
            !$other_head_user
            || !isHeadOfficerPosition($other_head_user['position'] ?? '')
            || $other_department === ''
            || $other_department === 'Pengurusan'
            || isSameDepartment($other_department, $fallback_department)
        ) {
            throw new Exception('signatory_required');
        }

        $other_head_user['routing_position'] = getDisplayPositionForUser($other_head_user, $other_department) ?: ($other_head_user['position'] ?? 'Ketua Bahagian');
        $other_head_user['source_type'] = 'ketua_bahagian_lain';
        $other_head_user['route_order'] = 1;

        return [
            'target' => 'other_department_head',
            'signer_user' => $other_head_user,
            'recipients' => [$other_head_user],
            'signatory_name' => trim((string) ($other_head_user['fullname'] ?? '')),
            'signatory_position' => getDisplayPositionForUser($other_head_user, $other_department) ?: trim((string) ($other_head_user['position'] ?? '')),
            'signatory_department' => $other_department,
        ];
    }

    if (!$department_head_user) {
        throw new Exception('department_officer_required');
    }

    return [
        'target' => 'department_head',
        'signer_user' => $department_head_user,
        'recipients' => [],
        'signatory_name' => trim((string) ($department_head_user['fullname'] ?? '')),
        'signatory_position' => getDisplayPositionForUser($department_head_user, $fallback_department) ?: trim((string) ($department_head_user['position'] ?? '')),
        'signatory_department' => trim((string) (($department_head_user['department'] ?? '') ?: $fallback_department)),
    ];
}

function buildSuratRasmiApprovalRoute($conn, $preparer_user_id, $folder_department, $department_officer_user_id, $recipients) {
    $preparer = getApprovedUserById($conn, $preparer_user_id);
    if (!$preparer) {
        throw new Exception('validation');
    }

    $needs_department_officer = !isHeadOfficerPosition($preparer['position'] ?? '');
    $department_officer_user = $needs_department_officer ? getSupportUserById($conn, $department_officer_user_id) : null;
    $has_final_recipient = !empty($recipients);

    if ($needs_department_officer) {
        if (!$department_officer_user || !isHeadOfficerPosition($department_officer_user['position'] ?? '')) {
            throw new Exception('department_officer_required');
        }
        if (!isSameDepartmentDb($conn, $department_officer_user['department'] ?? '', $folder_department)) {
            throw new Exception('department_officer_department');
        }
        if ((int) ($department_officer_user['id'] ?? 0) === (int) $preparer_user_id) {
            throw new Exception('duplicate_approver');
        }
    }

    $selected_ids = array_map(function ($recipient) {
        return (int) ($recipient['id'] ?? 0);
    }, $recipients);
    if ($needs_department_officer) {
        $selected_ids[] = (int) ($department_officer_user['id'] ?? 0);
    }
    $selected_ids = array_filter($selected_ids);
    if (count($selected_ids) !== count(array_unique($selected_ids))) {
        throw new Exception('duplicate_approver');
    }

    if ($needs_department_officer) {
        return [
            'needs_department_officer' => true,
            'department_officer_user' => $department_officer_user,
            'current_user' => $department_officer_user,
            'approval_status' => 'menunggu_pegawai_bahagian',
            'approval_stage' => 1,
            'department_officer_status' => 'menunggu',
            'department_officer_requested_now' => true,
        ];
    }

    if ($has_final_recipient) {
        return [
            'needs_department_officer' => false,
            'department_officer_user' => null,
            'current_user' => $recipients[0],
            'approval_status' => 'menunggu_pelulus',
            'approval_stage' => 2,
            'department_officer_status' => 'tidak_perlu',
            'department_officer_requested_now' => false,
        ];
    }

    return [
        'needs_department_officer' => false,
        'department_officer_user' => null,
        'current_user' => null,
        'approval_status' => 'lulus',
        'approval_stage' => 0,
        'department_officer_status' => 'tidak_perlu',
        'department_officer_requested_now' => false,
    ];
}

function redirectDraftSupportError($draft_id, $message = 'system') {
    $draft_id = (int) $draft_id;
    header("Location: draft_letter_print.php?id={$draft_id}&support_error=" . urlencode($message));
    exit();
}

function normalizeApprovalFlow($value) {
    return $value === 'two_level' ? 'two_level' : 'single';
}

function normalizeDraftDocumentType($doc_type) {
    $doc_type = trim((string) $doc_type);
    return $doc_type !== '' ? $doc_type : 'Memo Kelulusan';
}

function getDraftLetterFormPageByDocType($doc_type) {
    $doc_type = normalizeDraftDocumentType($doc_type);
    if ($doc_type === 'Memo') {
        return 'Memo.php';
    }
    if ($doc_type === 'Surat Rasmi') {
        return 'Surat_Rasmi.php';
    }
    return 'Memo_Kelulusan.php';
}

function redirectDraftFormByDocType($doc_type, $query = []) {
    $url = getDraftLetterFormPageByDocType($doc_type);
    if (!empty($query)) {
        $url .= '?' . http_build_query($query);
    }
    header('Location: ' . $url);
    exit();
}

function getDraftDocumentTypeById($conn, $draft_id) {
    $draft_id = (int) $draft_id;
    if ($draft_id <= 0) {
        return 'Memo Kelulusan';
    }
    $stmt = mysqli_prepare($conn, "SELECT doc_type FROM letter_drafts WHERE id = ? LIMIT 1");
    if (!$stmt) {
        return 'Memo Kelulusan';
    }
    mysqli_stmt_bind_param($stmt, "i", $draft_id);
    mysqli_stmt_execute($stmt);
    $row = mysqli_fetch_assoc(mysqli_stmt_get_result($stmt));
    return normalizeDraftDocumentType($row['doc_type'] ?? 'Memo Kelulusan');
}

function redirectDraftPrint($draft_id, $query = []) {
    $url = 'draft_letter_print.php?id=' . (int) $draft_id;
    if (!empty($query)) {
        $url .= '&' . http_build_query($query);
    }
    header('Location: ' . $url);
    exit();
}

function saveReplacementLetterFile($document_id, $folder_id, $file) {
    if (empty($file) || ($file['error'] ?? UPLOAD_ERR_NO_FILE) === UPLOAD_ERR_NO_FILE) {
        throw new RuntimeException('missing');
    }

    if (($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
        throw new RuntimeException('upload');
    }

    $original_name = basename((string) ($file['name'] ?? ''));
    $extension = strtolower(pathinfo($original_name, PATHINFO_EXTENSION));
    $allowed_extensions = ['pdf', 'doc', 'docx'];

    if (!in_array($extension, $allowed_extensions, true)) {
        throw new RuntimeException('format');
    }

    if ((int) ($file['size'] ?? 0) > 10 * 1024 * 1024) {
        throw new RuntimeException('size');
    }

    $upload_dir = 'uploads/documents/';
    if (!is_dir($upload_dir)) {
        mkdir($upload_dir, 0755, true);
    }

    $filename = 'replace_' . (int) $folder_id . '_' . (int) $document_id . '_' . date('YmdHis') . '_' . bin2hex(random_bytes(4)) . '.' . $extension;
    $target_path = $upload_dir . $filename;

    if (!move_uploaded_file($file['tmp_name'] ?? '', $target_path)) {
        throw new RuntimeException('upload');
    }

    return [$target_path, $original_name];
}

function lockFolderForDocumentNumbering($conn, $folder_id) {
    $folder_id = (int) $folder_id;
    if ($folder_id <= 0) {
        return false;
    }

    $stmt = mysqli_prepare($conn, "SELECT id FROM folders WHERE id = ? AND deleted_at IS NULL LIMIT 1 FOR UPDATE");
    if (!$stmt) {
        return false;
    }

    mysqli_stmt_bind_param($stmt, "i", $folder_id);
    mysqli_stmt_execute($stmt);
    $row = mysqli_fetch_assoc(mysqli_stmt_get_result($stmt));

    return !empty($row);
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && $action === 'replace_letter_file') {
    $draft_id = (int) ($_POST['id'] ?? 0);
    $current_user_id = (int) ($_SESSION['user_id'] ?? 0);

    if ($draft_id <= 0) {
        header("Location: draft_letters.php?error=not_found");
        exit();
    }

    $draft_stmt = mysqli_prepare($conn, "SELECT id, document_id, folder_id, ref_no, subject, doc_type, created_by, approval_status, status, department
        FROM letter_drafts
        WHERE id = ? AND deleted_at IS NULL
        LIMIT 1");
    mysqli_stmt_bind_param($draft_stmt, "i", $draft_id);
    mysqli_stmt_execute($draft_stmt);
    $draft = mysqli_fetch_assoc(mysqli_stmt_get_result($draft_stmt));

    if (!$draft) {
        header("Location: draft_letters.php?error=not_found");
        exit();
    }

    if ((int) ($draft['created_by'] ?? 0) !== $current_user_id) {
        redirectDraftPrint($draft_id, ['replace_error' => 'permission']);
    }

    if (($draft['approval_status'] ?? '') !== 'lulus') {
        redirectDraftPrint($draft_id, ['replace_error' => 'status']);
    }

    $document_id = (int) ($draft['document_id'] ?? 0);
    $folder_id = (int) ($draft['folder_id'] ?? 0);
    if ($document_id <= 0 || $folder_id <= 0) {
        redirectDraftPrint($draft_id, ['replace_error' => 'system']);
    }

    $new_file_path = '';
    $old_file_path = '';

    try {
        [$new_file_path, $original_name] = saveReplacementLetterFile($document_id, $folder_id, $_FILES['replacement_file'] ?? []);

        mysqli_begin_transaction($conn);

        $existing_stmt = mysqli_prepare($conn, "SELECT id, file_path FROM document_attachments WHERE document_id = ? AND is_replacement_letter = 1 ORDER BY id ASC LIMIT 1 FOR UPDATE");
        mysqli_stmt_bind_param($existing_stmt, "i", $document_id);
        mysqli_stmt_execute($existing_stmt);
        $existing_attachment = mysqli_fetch_assoc(mysqli_stmt_get_result($existing_stmt));

        if ($existing_attachment) {
            $attachment_id = (int) ($existing_attachment['id'] ?? 0);
            $old_file_path = trim((string) ($existing_attachment['file_path'] ?? ''));
            $update_attachment = mysqli_prepare($conn, "UPDATE document_attachments SET file_path = ?, original_name = ?, created_at = CURRENT_TIMESTAMP WHERE id = ?");
            mysqli_stmt_bind_param($update_attachment, "ssi", $new_file_path, $original_name, $attachment_id);
            if (!mysqli_stmt_execute($update_attachment)) {
                throw new RuntimeException('system');
            }
        } else {
            $insert_attachment = mysqli_prepare($conn, "INSERT INTO document_attachments (document_id, file_path, original_name, is_replacement_letter) VALUES (?, ?, ?, 1)");
            mysqli_stmt_bind_param($insert_attachment, "iss", $document_id, $new_file_path, $original_name);
            if (!mysqli_stmt_execute($insert_attachment)) {
                throw new RuntimeException('system');
            }
        }

        $update_document = mysqli_prepare($conn, "UPDATE documents SET file_path = ? WHERE id = ?");
        mysqli_stmt_bind_param($update_document, "si", $new_file_path, $document_id);
        if (!mysqli_stmt_execute($update_document)) {
            throw new RuntimeException('system');
        }

        mysqli_commit($conn);
    } catch (RuntimeException $e) {
        if (mysqli_errno($conn)) {
            mysqli_rollback($conn);
        }
        if ($new_file_path !== '' && file_exists(__DIR__ . '/' . $new_file_path)) {
            unlink(__DIR__ . '/' . $new_file_path);
        }
        $error_code = in_array($e->getMessage(), ['missing', 'format', 'size'], true) ? $e->getMessage() : 'system';
        redirectDraftPrint($draft_id, ['replace_error' => $error_code]);
    }

    if ($old_file_path !== '' && $old_file_path !== $new_file_path) {
        $old_full_path = preg_match('/^[A-Za-z]:[\\\\\\/]/', $old_file_path)
            ? $old_file_path
            : __DIR__ . '/' . $old_file_path;
        if (is_file($old_full_path)) {
            unlink($old_full_path);
        }
    }

    logActivity($conn, $current_user_id, 'replace_draft_letter_file', "Replace letter file: {$draft['ref_no']} - {$draft['subject']} (Draft ID: {$draft_id}, Document ID: {$document_id})");
    redirectDraftPrint($draft_id, ['success' => 'letter_replaced']);
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && $action === 'add') {
    if (!currentUserCan($conn, 'draft_letter', 'create')) {
        echo "<script>alert('Anda tidak mempunyai kebenaran untuk menyediakan surat.'); window.location='draft_letters.php';</script>";
        exit();
    }

    $folder_id = (int) ($_POST['folder_id'] ?? 0);
    $template_id = (int) ($_POST['template_id'] ?? 0);
    $subject = trim((string) ($_POST['subject'] ?? ''));
    $letter_date = trim((string) ($_POST['letter_date'] ?? ''));
    $doc_type = normalizeDraftDocumentType($_POST['doc_type'] ?? 'Memo Kelulusan');
    $is_surat_rasmi = strcasecmp($doc_type, 'Surat Rasmi') === 0;
    $is_memo = strcasecmp($doc_type, 'Memo') === 0;
    $recipient_name = trim((string) ($_POST['recipient_name'] ?? ''));
    $recipient_organization = normalizeMemoDisplayPositions($_POST['recipient_organization_checked'] ?? [], $_POST['recipient_organization'] ?? '');
    $recipient_address = '';
    $attention_to = normalizeMemoDisplayPositions($_POST['attention_to_checked'] ?? [], $_POST['attention_to'] ?? '');
    $default_body_font_size = $is_surat_rasmi ? '16px' : '12px';
    if (strcasecmp($doc_type, 'Memo') === 0 || $is_surat_rasmi) {
        $attention_to = '';
    }
    $routing_selection = normalizeMemoRoutingSelection($_POST['routing_positions'] ?? [], $_POST['routing_order'] ?? []);
    $routing_positions = array_column($routing_selection, 'position');
    $routing_positions_json = json_encode($routing_positions, JSON_UNESCAPED_UNICODE);
    $greeting = trim((string) ($_POST['greeting'] ?? ''));
    $current_user_id = (int) ($_SESSION['user_id'] ?? 0);
    $document_signature_data = trim((string) ($_POST['document_signature_data'] ?? ''));
    $posted_document_signature_path = savePostedDocumentDigitalSignature($current_user_id, 0, $document_signature_data);
    if ($posted_document_signature_path !== '') {
        foreach (['letter_pages', 'letter_body', 'approval_page_body', 'approval_route_bodies', 'page_header_text', 'page_footer_text', 'distribution_page_content'] as $signature_field) {
            if (isset($_POST[$signature_field])) {
                $_POST[$signature_field] = replacePostedDocumentDigitalSignatureSource($_POST[$signature_field], $document_signature_data, $posted_document_signature_path);
            }
        }
    }
    $letter_pages = sanitizeDraftLetterPagesJson($_POST['letter_pages'] ?? '', $default_body_font_size);
    $letter_body = $letter_pages[0] ?? sanitizeDraftLetterBodyHtml($_POST['letter_body'] ?? '', $default_body_font_size);
    $letter_pages_json = json_encode(!empty($letter_pages) ? $letter_pages : [$letter_body], JSON_UNESCAPED_UNICODE);
    $approval_page_body = sanitizeDraftLetterBodyHtml($_POST['approval_page_body'] ?? '', $default_body_font_size);
    $approval_page_subject = '';
    $approval_route_bodies_json = sanitizeDraftApprovalRouteBodiesJson($_POST['approval_route_bodies'] ?? '', $default_body_font_size);
    $letter_page_signers_json = sanitizeDraftLetterPageSignersJson('', count(!empty($letter_pages) ? $letter_pages : [$letter_body]));
    $page_number_position = in_array($_POST['page_number_position'] ?? '', ['none', 'bottom_center', 'bottom_right'], true)
        ? $_POST['page_number_position']
        : 'none';
    $page_header_text = sanitizeDraftLetterBodyHtml($_POST['page_header_text'] ?? '', $default_body_font_size);
    $page_footer_text = sanitizeDraftLetterBodyHtml($_POST['page_footer_text'] ?? '', $default_body_font_size);
    $closing_text = trim((string) ($_POST['closing_text'] ?? ''));
    $signatory_name = trim((string) ($_POST['signatory_name'] ?? ''));
    $signatory_position = trim((string) ($_POST['signatory_position'] ?? ''));
    $signatory_department = trim((string) ($_POST['signatory_department'] ?? ''));
    $posted_signatory_target = trim((string) ($_POST['signatory_target'] ?? 'department_head'));
    $signatory_target = in_array($posted_signatory_target, ['management', 'other_department_head'], true) ? $posted_signatory_target : 'department_head';
    $management_signer_user_id = (int) ($_POST['management_signer_user_id'] ?? 0);
    $other_department_head_user_id = (int) ($_POST['other_department_head_user_id'] ?? 0);
    $signatory_signature_path = '';
    $approval_flow = 'two_level';
    $department_officer_user_id = (int) ($_POST['department_officer_user_id'] ?? 0);
    $status = trim((string) ($_POST['status'] ?? 'draf'));
    $status = array_key_exists($status, getDraftLetterStatusList()) ? $status : 'draf';
    $is_ready_to_send = $status === 'siap';
    $uploaded_files = normalizeUploadedFiles('file_upload');
    $preparer_signed = (string) ($_POST['preparer_signed'] ?? '') === '1';

    // Distribution staff list
    $selected_distribution_staff = $_POST['selected_distribution_staff'] ?? '[]';
    $selected_distribution_staff_ids = decodeSelectedDistributionStaffIds($selected_distribution_staff);
    $include_distribution_page = isset($_POST['include_distribution_page']) && (string) $_POST['include_distribution_page'] === '1';

    // Distribution page content
    $distribution_page_content = $_POST['distribution_page_content'] ?? '';
    if (!$include_distribution_page || empty($selected_distribution_staff_ids)) {
        $selected_distribution_staff_ids = [];
        $distribution_staff_list_json = '[]';
        $distribution_page_content = '';
    } else {
        if (function_exists('isStaffDistributionPageContentInvalid') && isStaffDistributionPageContentInvalid($distribution_page_content)) {
            $distribution_page_content = buildStaffDistributionPageContent($conn, $selected_distribution_staff_ids);
        }
        $distribution_staff_list_json = json_encode($selected_distribution_staff_ids, JSON_UNESCAPED_UNICODE);
    }

    $body_has_user_content = $is_surat_rasmi ? suratRasmiBodyHasUserContent($letter_body) : draftLetterBodyHasContent($letter_body);
    if ($folder_id <= 0 || $subject === '' || $letter_date === '' || $doc_type === '' || (!$is_surat_rasmi && $recipient_organization === '') || !$body_has_user_content) {
        redirectDraftFormByDocType($doc_type, ['error' => 'validation']);
    }
    if ($is_memo || $is_surat_rasmi) {
        ensureMemoDistributionRecipientSelection($recipient_organization, $include_distribution_page, $selected_distribution_staff_ids);
    }

    mysqli_begin_transaction($conn);

    try {
        $folder_stmt = mysqli_prepare($conn, "SELECT id, folder_name, folder_code, department, closed_at
            FROM folders
            WHERE id = ? AND deleted_at IS NULL AND COALESCE(folder_type, 'office') <> 'sendirian'
            LIMIT 1 FOR UPDATE");
        mysqli_stmt_bind_param($folder_stmt, "i", $folder_id);
        mysqli_stmt_execute($folder_stmt);
        $folder = mysqli_fetch_assoc(mysqli_stmt_get_result($folder_stmt));

        if (!$folder) {
            throw new Exception('folder');
        }

        if (!empty($folder['closed_at'])) {
            throw new Exception('folder_closed');
        }

        if (!isSameDepartmentDb($conn, $folder['department'] ?? '', $user_department)) {
            throw new Exception('unauthorized');
        }

        $department_head_user = getDepartmentHeadOfficerByDepartment($conn, $folder['department'] ?? '');
        if ($department_head_user && $department_officer_user_id <= 0) {
            $department_officer_user_id = (int) ($department_head_user['id'] ?? 0);
        }
        $memo_signatory_user = null;
        $memo_signatory_is_current = false;
        $surat_rasmi_signatory_user = null;
        $surat_rasmi_signatory_is_current = false;
        if ($is_surat_rasmi) {
            $surat_rasmi_signatory_user = resolveMemoSignatoryUserByPosition($conn, $signatory_position);
            if (!$surat_rasmi_signatory_user) {
                throw new Exception('signatory_required');
            }
            $signatory_name = trim((string) ($surat_rasmi_signatory_user['fullname'] ?? ''));
            $signatory_position = getDisplayPositionForUser($surat_rasmi_signatory_user) ?: trim((string) ($surat_rasmi_signatory_user['position'] ?? $signatory_position));
            $signatory_department = normalizeDepartmentValue($surat_rasmi_signatory_user['department'] ?? '');
            $department_officer_user_id = (int) ($surat_rasmi_signatory_user['id'] ?? 0);
            $surat_rasmi_signatory_is_current = (int) ($surat_rasmi_signatory_user['id'] ?? 0) === $current_user_id;
            if ($preparer_signed && !$surat_rasmi_signatory_is_current) {
                throw new Exception('signatory_permission');
            }
        } elseif ($is_memo) {
            $memo_signatory_user = resolveMemoSignatoryUserByPosition($conn, $signatory_position);
            if (!$memo_signatory_user) {
                throw new Exception('signatory_required');
            }
            $signatory_name = trim((string) ($memo_signatory_user['fullname'] ?? ''));
            $signatory_position = getDisplayPositionForUser($memo_signatory_user) ?: trim((string) ($memo_signatory_user['position'] ?? $signatory_position));
            $signatory_department = normalizeDepartmentValue($memo_signatory_user['department'] ?? '');
            $department_officer_user_id = (int) ($memo_signatory_user['id'] ?? 0);
            $memo_signatory_is_current = (int) ($memo_signatory_user['id'] ?? 0) === $current_user_id;
            if ($preparer_signed && !$memo_signatory_is_current) {
                throw new Exception('signatory_permission');
            }
        } else {
            applyDepartmentHeadSignatory($signatory_name, $signatory_position, $signatory_department, $department_head_user, $folder['department'] ?? '');
        }

        $approval_recipients = [];
        $route = [
            'needs_department_officer' => false,
            'department_officer_user' => null,
            'current_user' => null,
            'approval_status' => $is_surat_rasmi && $is_ready_to_send ? 'lulus' : 'draft',
            'approval_stage' => 0,
            'department_officer_status' => 'tidak_perlu',
            'department_officer_requested_now' => false,
        ];
        $support_user = null;
        $support_user_id = 0;
        $support_required = 0;
        $support_name = null;
        $support_email = null;
        $support_status = 'tidak_perlu';

        if ($is_memo) {
            $approval_recipients = resolveMemoApprovalRecipients(
                $conn,
                $recipient_organization,
                '',
                buildMemoFinalRecipientSelection($recipient_organization),
                $current_user_id,
                [],
                false,
                $selected_distribution_staff_ids
            );
            if ($is_ready_to_send) {
                $route = buildMemoSignatoryRoute($conn, $memo_signatory_user, $current_user_id, $folder['department'] ?? '', $department_head_user);
                $support_user = $route['current_user'];
                $support_user_id = (int) ($support_user['id'] ?? 0);
                $support_required = $support_user_id > 0 ? 1 : 0;
                $support_name = $support_user['fullname'] ?? null;
                $support_email = $support_user['email'] ?? null;
                $support_status = $support_required ? 'menunggu' : 'tidak_perlu';
            } else {
                $route['approval_status'] = 'draft';
            }
        } else {
            $excluded_approval_user_ids = $department_head_user ? [(int) ($department_head_user['id'] ?? 0)] : [];
            $approval_recipients = $is_surat_rasmi
                ? ($recipient_organization !== '' ? resolveMemoApprovalRecipients($conn, $recipient_organization, '', buildMemoFinalRecipientSelection($recipient_organization), $current_user_id, [(int) ($surat_rasmi_signatory_user['id'] ?? 0)], false, $selected_distribution_staff_ids) : [])
                : resolveMemoApprovalRecipients($conn, $recipient_organization, $attention_to, $routing_selection, $current_user_id, $excluded_approval_user_ids);

            if ($is_ready_to_send) {
                if (!$is_surat_rasmi && !approvalRouteBodiesCoverRecipients($approval_route_bodies_json, $approval_recipients)) {
                    throw new Exception('approval_content_required');
                }
                if ($is_surat_rasmi) {
                    $route = buildSuratRasmiSignatoryRoute($conn, $surat_rasmi_signatory_user, $current_user_id, $folder['department'] ?? '', $department_head_user);
                    $support_user = $route['current_user'];
                    $support_user_id = (int) ($support_user['id'] ?? 0);
                    $support_required = $support_user_id > 0 ? 1 : 0;
                    $support_name = $support_user['fullname'] ?? null;
                    $support_email = $support_user['email'] ?? null;
                    $support_status = $support_required ? 'menunggu' : 'tidak_perlu';
                } else {
                    $route = buildDraftApprovalRoute($conn, $current_user_id, $folder['department'] ?? '', $department_officer_user_id, $approval_recipients);
                    $support_user = $route['current_user'];
                    $support_user_id = (int) ($support_user['id'] ?? 0);
                    $support_required = $support_user_id > 0 ? 1 : 0;
                    $support_name = $support_user['fullname'] ?? null;
                    $support_email = $support_user['email'] ?? null;
                    $support_status = $support_required ? 'menunggu' : 'tidak_perlu';
                    applyDepartmentHeadSignatory($signatory_name, $signatory_position, $signatory_department, $department_head_user, $folder['department'] ?? '');
                }
            }
        }

        $ref_no = generateNextDocumentReference($folder['folder_code'] ?? '');
        if ($ref_no === '') {
            throw new Exception('Gagal menjana nombor rujukan surat.');
        }

        $file_numbering = $is_ready_to_send ? generateNextDocumentFileNumbering($conn, $folder_id) : 'X';
        if ($is_surat_rasmi) {
            $surat_rasmi_reference_display = formatDraftLetterReferenceDisplay($folder['department'] ?? '', $ref_no, $is_ready_to_send ? $file_numbering : 'X');
            $letter_pages = applySuratRasmiGeneratedReferenceToPages(!empty($letter_pages) ? $letter_pages : [$letter_body], $surat_rasmi_reference_display);
            $letter_pages = applySuratRasmiGeneratedReferenceToPages(!empty($letter_pages) ? $letter_pages : [$letter_body], $surat_rasmi_reference_display);
            $letter_body = $letter_pages[0] ?? $letter_body;
            $letter_pages_json = json_encode($letter_pages, JSON_UNESCAPED_UNICODE);
        }
        $submitted_at_sql = $is_ready_to_send ? "NOW(6)" : "NULL";

        if ($is_ready_to_send && $preparer_signed && !draftLetterHasGeneratedClosing($letter_body, $letter_pages_json)) {
            throw new Exception('closing_required_before_signature');
        }

        $signatory_signature_path = '';
        $surat_rasmi_has_final_recipient = $is_surat_rasmi && !empty($approval_recipients);
        if ($is_ready_to_send) {
            if ($is_memo) {
                $signatory_signature_path = ($memo_signatory_is_current && $preparer_signed) ? ($posted_document_signature_path ?: getUserSignaturePath($conn, $current_user_id)) : '';
                if ($preparer_signed && $signatory_signature_path === '') {
                    throw new Exception('preparer_signature_missing');
                }
            } elseif ($is_surat_rasmi) {
                $signatory_signature_path = ($surat_rasmi_signatory_is_current && $preparer_signed) ? ($posted_document_signature_path ?: getUserSignaturePath($conn, $current_user_id)) : '';
                if ($preparer_signed && $signatory_signature_path === '') {
                    throw new Exception('preparer_signature_missing');
                }
            } else if (empty($route['needs_department_officer']) && !$surat_rasmi_has_final_recipient) {
                if ($is_surat_rasmi) {
                    if (!$preparer_signed) {
                        throw new Exception('preparer_signature_required');
                    }
                    $signatory_signature_path = $preparer_signed ? ($posted_document_signature_path ?: getUserSignaturePath($conn, $current_user_id)) : '';
                    if ($preparer_signed && $signatory_signature_path === '') {
                        throw new Exception('preparer_signature_missing');
                    }
                } else {
                    $signatory_signature_path = $posted_document_signature_path ?: getUserSignaturePath($conn, $current_user_id);
                    if (!$preparer_signed) {
                        throw new Exception('preparer_signature_required');
                    }
                    if ($signatory_signature_path === '') {
                        throw new Exception('preparer_signature_missing');
                    }
                }
            }
        }
        if (!$is_ready_to_send) {
            $signatory_signature_path = '';
        }

        $to_person = buildDraftRecipientSummary($recipient_name, $recipient_organization, $attention_to);
        $from_person = trim((string) ($folder['department'] ?? ''));
        $file_path = null;

        $insert_doc = mysqli_prepare($conn, "INSERT INTO documents (folder_id, ref_no, file_numbering, subject, doc_date, from_person, to_person, doc_type, file_path)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
        mysqli_stmt_bind_param($insert_doc, "issssssss", $folder_id, $ref_no, $file_numbering, $subject, $letter_date, $from_person, $to_person, $doc_type, $file_path);
        if (!mysqli_stmt_execute($insert_doc)) {
            throw new Exception(mysqli_error($conn));
        }

        $document_id = (int) mysqli_insert_id($conn);
        $attachment_result = saveDocumentAttachments($conn, $document_id, $folder_id, $uploaded_files);
        if (!empty($attachment_result['first_path'])) {
            $file_path = $attachment_result['first_path'];
            $update_primary = mysqli_prepare($conn, "UPDATE documents SET file_path = ? WHERE id = ?");
            mysqli_stmt_bind_param($update_primary, "si", $file_path, $document_id);
            mysqli_stmt_execute($update_primary);
        }

        $preparer_signed_value_sql = ($is_ready_to_send && (($is_memo && $memo_signatory_is_current && $preparer_signed) || ($is_surat_rasmi && $surat_rasmi_signatory_is_current && $preparer_signed) || (!$is_memo && !$is_surat_rasmi && empty($route['needs_department_officer']) && $preparer_signed))) ? "NOW()" : "NULL";
        $insert_draft = mysqli_prepare($conn, "INSERT INTO letter_drafts
            (document_id, folder_id, department, ref_no, letter_date, subject, doc_type, recipient_name, recipient_organization, recipient_address, attention_to, routing_positions, greeting, letter_body, letter_pages, approval_page_body, approval_page_subject, approval_route_bodies, letter_page_signers, page_number_position, page_header_text, page_footer_text, closing_text, signatory_name, signatory_position, signatory_department, signatory_signature_path, preparer_signed_at, status, support_required, support_user_id, support_name, support_email, support_status, support_requested_at, distribution_staff_list, distribution_page_content, created_by, updated_by)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, {$preparer_signed_value_sql}, ?, ?, ?, ?, ?, ?, " . ($support_required ? "NOW()" : "NULL") . ", ?, ?, ?, ?)");
        $insert_draft_types = 'ii' . str_repeat('s', 25) . 'siisssssii';
        mysqli_stmt_bind_param(
            $insert_draft,
            $insert_draft_types,
            $document_id,
            $folder_id,
            $folder['department'],
            $ref_no,
            $letter_date,
            $subject,
            $doc_type,
            $recipient_name,
            $recipient_organization,
            $recipient_address,
            $attention_to,
            $routing_positions_json,
            $greeting,
            $letter_body,
            $letter_pages_json,
            $approval_page_body,
            $approval_page_subject,
            $approval_route_bodies_json,
            $letter_page_signers_json,
            $page_number_position,
            $page_header_text,
            $page_footer_text,
            $closing_text,
            $signatory_name,
            $signatory_position,
            $signatory_department,
            $signatory_signature_path,
            $status,
            $support_required,
            $support_user_id,
            $support_name,
            $support_email,
            $support_status,
            $distribution_staff_list_json,
            $distribution_page_content,
            $current_user_id,
            $current_user_id
        );
        if (!mysqli_stmt_execute($insert_draft)) {
            throw new Exception(mysqli_error($conn));
        }

        $draft_id = (int) mysqli_insert_id($conn);
        if ($is_ready_to_send) {
            $submitted_update = mysqli_prepare($conn, "UPDATE letter_drafts SET submitted_at = {$submitted_at_sql} WHERE id = ?");
            mysqli_stmt_bind_param($submitted_update, "i", $draft_id);
            if (!mysqli_stmt_execute($submitted_update)) {
                throw new Exception(mysqli_error($conn));
            }
        }
        $include_distribution_value = $include_distribution_page ? 1 : 0;
        $distribution_state_update = mysqli_prepare($conn, "UPDATE letter_drafts SET include_distribution_page = ? WHERE id = ?");
        mysqli_stmt_bind_param($distribution_state_update, "ii", $include_distribution_value, $draft_id);
        if (!mysqli_stmt_execute($distribution_state_update)) {
            throw new Exception(mysqli_error($conn));
        }
        if ($template_id > 0) {
            $template_update = mysqli_prepare($conn, "UPDATE letter_drafts SET template_id = ? WHERE id = ?");
            mysqli_stmt_bind_param($template_update, "ii", $template_id, $draft_id);
            mysqli_stmt_execute($template_update);
        }
        $approval_status = $is_ready_to_send ? $route['approval_status'] : 'draft';
        $approval_stage = (int) $route['approval_stage'];
        $department_officer_user = $route['department_officer_user'];
        $department_officer_save_id = $is_ready_to_send
            ? ($route['needs_department_officer'] ? (int) ($department_officer_user['id'] ?? $department_officer_user_id) : 0)
            : $department_officer_user_id;
        $department_officer_name = $is_ready_to_send ? ($department_officer_user['fullname'] ?? null) : null;
        $department_officer_email = $is_ready_to_send ? ($department_officer_user['email'] ?? null) : null;
        $department_officer_status = $is_ready_to_send ? $route['department_officer_status'] : 'tidak_perlu';
        $department_officer_requested_sql = ($is_ready_to_send && $route['department_officer_requested_now']) ? "NOW()" : "NULL";
        $memo_preparer_head_user = $route['memo_preparer_head_user'] ?? null;
        $memo_preparer_head_save_id = $is_ready_to_send ? (int) ($memo_preparer_head_user['id'] ?? 0) : 0;
        $memo_preparer_head_name = $is_ready_to_send ? ($memo_preparer_head_user['fullname'] ?? null) : null;
        $memo_preparer_head_email = $is_ready_to_send ? ($memo_preparer_head_user['email'] ?? null) : null;
        $memo_preparer_head_status = $is_ready_to_send ? ($route['memo_preparer_head_status'] ?? 'tidak_perlu') : 'tidak_perlu';
        $memo_preparer_head_requested_sql = ($is_ready_to_send && !empty($route['memo_preparer_head_requested_now'])) ? "NOW()" : "NULL";
        $approval_update = mysqli_prepare($conn, "UPDATE letter_drafts
            SET approval_flow = ?, approval_status = ?, approval_stage = ?,
                department_officer_user_id = ?, department_officer_name = ?, department_officer_email = ?, department_officer_status = ?, department_officer_requested_at = {$department_officer_requested_sql}
                , memo_preparer_head_user_id = ?, memo_preparer_head_name = ?, memo_preparer_head_email = ?, memo_preparer_head_status = ?, memo_preparer_head_requested_at = {$memo_preparer_head_requested_sql}, memo_preparer_head_responded_at = NULL, memo_preparer_head_note = NULL
            WHERE id = ?");
        mysqli_stmt_bind_param(
            $approval_update,
            "ssiisssisssi",
            $approval_flow,
            $approval_status,
            $approval_stage,
            $department_officer_save_id,
            $department_officer_name,
            $department_officer_email,
            $department_officer_status,
            $memo_preparer_head_save_id,
            $memo_preparer_head_name,
            $memo_preparer_head_email,
            $memo_preparer_head_status,
            $draft_id
        );
        if (!mysqli_stmt_execute($approval_update)) {
            throw new Exception(mysqli_error($conn));
        }
        if ($is_memo || $is_surat_rasmi) {
            syncMemoDeliveryRecipients($conn, $draft_id, $approval_recipients, $is_ready_to_send && !$route['needs_department_officer']);
        } else {
            syncMemoApprovalRecipients($conn, $draft_id, $approval_recipients, $is_ready_to_send && !$route['needs_department_officer']);
        }
        mysqli_commit($conn);

        logActivity($conn, $current_user_id, 'create_draft_letter', "Create draft letter: {$ref_no} - {$subject} (Draft ID: {$draft_id}, Document ID: {$document_id})");
        if ($is_ready_to_send && $route['needs_department_officer'] && $support_required && $support_email) {
            sendDraftLetterSupportRequestEmail($support_email, $support_name, [
                'id' => $draft_id,
                'ref_no' => $ref_no,
                'subject' => $subject,
            ]);
        } elseif ($is_ready_to_send && !$route['needs_department_officer'] && !empty($approval_recipients)) {
            sendMemoApprovalRecipientEmails($conn, $draft_id, [
                'id' => $draft_id,
                'ref_no' => $ref_no,
                'subject' => $subject,
            ]);
        }
        header("Location: draft_letter_print.php?id={$draft_id}&success=created");
        exit();
    } catch (Exception $e) {
        mysqli_rollback($conn);

        if ($e->getMessage() === 'folder') {
            redirectDraftFormByDocType($doc_type, ['error' => 'folder']);
        }

        if ($e->getMessage() === 'folder_closed') {
            redirectDraftFormByDocType($doc_type, ['error' => 'folder_closed']);
        }

        if ($e->getMessage() === 'unauthorized') {
            header("Location: draft_letters.php?error=unauthorized");
            exit();
        }

        if (in_array($e->getMessage(), ['validation', 'department_officer_required', 'department_officer_department', 'duplicate_approver', 'approval_recipient_required', 'approval_content_required', 'preparer_signature_required', 'preparer_signature_missing', 'signature_invalid', 'closing_required_before_signature', 'signatory_required', 'signatory_permission', 'distribution_recipient_required'], true)) {
            redirectDraftFormByDocType($doc_type, ['error' => 'validation', 'msg' => $e->getMessage()]);
        }

        redirectDraftFormByDocType($doc_type, ['error' => 'system', 'msg' => $e->getMessage()]);
    }
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && $action === 'update') {
    $has_draft_update_permission = currentUserCan($conn, 'draft_letter', 'update');

    $draft_id = (int) ($_POST['id'] ?? 0);
    $folder_id = (int) ($_POST['folder_id'] ?? 0);
    $template_id = (int) ($_POST['template_id'] ?? 0);
    $subject = trim((string) ($_POST['subject'] ?? ''));
    $letter_date = trim((string) ($_POST['letter_date'] ?? ''));
    $doc_type = normalizeDraftDocumentType($_POST['doc_type'] ?? 'Memo Kelulusan');
    $is_surat_rasmi = strcasecmp($doc_type, 'Surat Rasmi') === 0;
    $is_memo = strcasecmp($doc_type, 'Memo') === 0;
    $recipient_name = trim((string) ($_POST['recipient_name'] ?? ''));
    $recipient_organization = normalizeMemoDisplayPositions($_POST['recipient_organization_checked'] ?? [], $_POST['recipient_organization'] ?? '');
    $recipient_address = '';
    $attention_to = normalizeMemoDisplayPositions($_POST['attention_to_checked'] ?? [], $_POST['attention_to'] ?? '');
    $default_body_font_size = $is_surat_rasmi ? '16px' : '12px';
    if (strcasecmp($doc_type, 'Memo') === 0 || $is_surat_rasmi) {
        $attention_to = '';
    }
    $routing_selection = normalizeMemoRoutingSelection($_POST['routing_positions'] ?? [], $_POST['routing_order'] ?? []);
    $routing_positions = array_column($routing_selection, 'position');
    $routing_positions_json = json_encode($routing_positions, JSON_UNESCAPED_UNICODE);
    $greeting = trim((string) ($_POST['greeting'] ?? ''));
    $current_user_id = (int) ($_SESSION['user_id'] ?? 0);
    $document_signature_data = trim((string) ($_POST['document_signature_data'] ?? ''));
    $posted_document_signature_path = savePostedDocumentDigitalSignature($current_user_id, $draft_id, $document_signature_data);
    if ($posted_document_signature_path !== '') {
        foreach (['letter_pages', 'letter_body', 'approval_page_body', 'approval_route_bodies', 'page_header_text', 'page_footer_text', 'distribution_page_content'] as $signature_field) {
            if (isset($_POST[$signature_field])) {
                $_POST[$signature_field] = replacePostedDocumentDigitalSignatureSource($_POST[$signature_field], $document_signature_data, $posted_document_signature_path);
            }
        }
    }
    $letter_pages = sanitizeDraftLetterPagesJson($_POST['letter_pages'] ?? '', $default_body_font_size);
    $letter_body = $letter_pages[0] ?? sanitizeDraftLetterBodyHtml($_POST['letter_body'] ?? '', $default_body_font_size);
    $letter_pages_json = json_encode(!empty($letter_pages) ? $letter_pages : [$letter_body], JSON_UNESCAPED_UNICODE);
    $approval_page_body = sanitizeDraftLetterBodyHtml($_POST['approval_page_body'] ?? '', $default_body_font_size);
    $approval_page_subject = '';
    $approval_route_bodies_json = sanitizeDraftApprovalRouteBodiesJson($_POST['approval_route_bodies'] ?? '', $default_body_font_size);
    $letter_page_signers_json = sanitizeDraftLetterPageSignersJson('', count(!empty($letter_pages) ? $letter_pages : [$letter_body]));
    $page_number_position = in_array($_POST['page_number_position'] ?? '', ['none', 'bottom_center', 'bottom_right'], true)
        ? $_POST['page_number_position']
        : 'none';
    $page_header_text = sanitizeDraftLetterBodyHtml($_POST['page_header_text'] ?? '', $default_body_font_size);
    $page_footer_text = sanitizeDraftLetterBodyHtml($_POST['page_footer_text'] ?? '', $default_body_font_size);
    $closing_text = trim((string) ($_POST['closing_text'] ?? ''));
    $signatory_name = trim((string) ($_POST['signatory_name'] ?? ''));
    $signatory_position = trim((string) ($_POST['signatory_position'] ?? ''));
    $signatory_department = trim((string) ($_POST['signatory_department'] ?? ''));
    $posted_signatory_target = trim((string) ($_POST['signatory_target'] ?? 'department_head'));
    $signatory_target = in_array($posted_signatory_target, ['management', 'other_department_head'], true) ? $posted_signatory_target : 'department_head';
    $management_signer_user_id = (int) ($_POST['management_signer_user_id'] ?? 0);
    $other_department_head_user_id = (int) ($_POST['other_department_head_user_id'] ?? 0);
    $approval_flow = 'two_level';
    $department_officer_user_id = (int) ($_POST['department_officer_user_id'] ?? 0);
    $status = trim((string) ($_POST['status'] ?? 'draf'));
    $status = array_key_exists($status, getDraftLetterStatusList()) ? $status : 'draf';
    $is_ready_to_send = $status === 'siap';
    $uploaded_files = normalizeUploadedFiles('file_upload');
    $preparer_signed = (string) ($_POST['preparer_signed'] ?? '') === '1';

    // Distribution staff list
    $selected_distribution_staff = $_POST['selected_distribution_staff'] ?? '[]';
    $selected_distribution_staff_ids = decodeSelectedDistributionStaffIds($selected_distribution_staff);
    $include_distribution_page = isset($_POST['include_distribution_page']) && (string) $_POST['include_distribution_page'] === '1';

    // Distribution page content
    $distribution_page_content = $_POST['distribution_page_content'] ?? '';
    if (!$include_distribution_page || empty($selected_distribution_staff_ids)) {
        $selected_distribution_staff_ids = [];
        $distribution_staff_list_json = '[]';
        $distribution_page_content = '';
    } else {
        if (function_exists('isStaffDistributionPageContentInvalid') && isStaffDistributionPageContentInvalid($distribution_page_content)) {
            $distribution_page_content = buildStaffDistributionPageContent($conn, $selected_distribution_staff_ids);
        }
        $distribution_staff_list_json = json_encode($selected_distribution_staff_ids, JSON_UNESCAPED_UNICODE);
    }

    $body_has_user_content = $is_surat_rasmi ? suratRasmiBodyHasUserContent($letter_body) : draftLetterBodyHasContent($letter_body);
    if ($draft_id <= 0 || $folder_id <= 0 || $subject === '' || $letter_date === '' || $doc_type === '' || (!$is_surat_rasmi && $recipient_organization === '') || !$body_has_user_content) {
        redirectDraftFormByDocType($doc_type, ['id' => $draft_id, 'error' => 'validation']);
    }

    mysqli_begin_transaction($conn);

    try {
        $draft_stmt = mysqli_prepare($conn, "SELECT ld.*, f.folder_code, f.department AS folder_department
            FROM letter_drafts ld
            INNER JOIN folders f ON f.id = ld.folder_id
            WHERE ld.id = ? AND ld.deleted_at IS NULL
            LIMIT 1 FOR UPDATE");
        mysqli_stmt_bind_param($draft_stmt, "i", $draft_id);
        mysqli_stmt_execute($draft_stmt);
        $draft = mysqli_fetch_assoc(mysqli_stmt_get_result($draft_stmt));

        if (!$draft) {
            throw new Exception('not_found');
        }

        if (($draft['approval_status'] ?? '') === 'lulus') {
            throw new Exception('approved_locked');
        }

        $is_department_officer_revision = ($draft['approval_status'] ?? '') === 'sedang_dipinda_ketua_bahagian'
            && (int) ($draft['approval_stage'] ?? 0) === 1
            && (
                (int) ($draft['department_officer_user_id'] ?? 0) === $current_user_id
                || (int) ($draft['memo_preparer_head_user_id'] ?? 0) === $current_user_id
            );
        $is_existing_private_draft = ($draft['status'] ?? 'draf') === 'draf' || ($draft['approval_status'] ?? 'draft') === 'draft';
        if (!$has_draft_update_permission && !$is_department_officer_revision) {
            throw new Exception('unauthorized');
        }

        if ($is_existing_private_draft && (int) ($draft['created_by'] ?? 0) !== $current_user_id && $role !== 'superadmin' && !$is_department_officer_revision) {
            throw new Exception('unauthorized');
        }
        if (($draft['approval_status'] ?? '') === 'sedang_dipinda_ketua_bahagian' && !$is_department_officer_revision) {
            throw new Exception('unauthorized');
        }

        $existing_distribution_staff_ids = decodeSelectedDistributionStaffIds($draft['distribution_staff_list'] ?? '[]');
        if ($is_department_officer_revision && (int) ($draft['include_distribution_page'] ?? 0) === 1 && !empty($existing_distribution_staff_ids)) {
            if (!$include_distribution_page || empty($selected_distribution_staff_ids)) {
                $include_distribution_page = true;
                $selected_distribution_staff_ids = $existing_distribution_staff_ids;
            }

            $existing_distribution_content = (string) ($draft['distribution_page_content'] ?? '');
            if (function_exists('isStaffDistributionPageContentInvalid') && isStaffDistributionPageContentInvalid($distribution_page_content)) {
                $distribution_page_content = !isStaffDistributionPageContentInvalid($existing_distribution_content)
                    ? $existing_distribution_content
                    : buildStaffDistributionPageContent($conn, $selected_distribution_staff_ids);
            }
        }

        if (!$include_distribution_page || empty($selected_distribution_staff_ids)) {
            $selected_distribution_staff_ids = [];
            $distribution_staff_list_json = '[]';
            $distribution_page_content = '';
        } else {
            if (function_exists('isStaffDistributionPageContentInvalid') && isStaffDistributionPageContentInvalid($distribution_page_content)) {
                $distribution_page_content = buildStaffDistributionPageContent($conn, $selected_distribution_staff_ids);
            }
            $distribution_staff_list_json = json_encode($selected_distribution_staff_ids, JSON_UNESCAPED_UNICODE);
        }

        if ($is_memo || $is_surat_rasmi) {
            ensureMemoDistributionRecipientSelection($recipient_organization, $include_distribution_page, $selected_distribution_staff_ids);
        }

        if (!isSameDepartmentDb($conn, $draft['department'] ?? '', $user_department)) {
            throw new Exception('unauthorized');
        }

        $preparer_user_id = (int) ($draft['created_by'] ?? $current_user_id);
        $draft_department = $draft['folder_department'] ?? $draft['department'] ?? '';
        $department_head_user = getDepartmentHeadOfficerByDepartment($conn, $draft_department);
        if ($department_head_user && $department_officer_user_id <= 0) {
            $department_officer_user_id = (int) ($department_head_user['id'] ?? 0);
        }
        $memo_signatory_user = null;
        $memo_signatory_is_preparer = false;
        $surat_rasmi_signatory_user = null;
        $surat_rasmi_signatory_is_preparer = false;
        $surat_rasmi_signatory_is_current = false;
        if ($is_surat_rasmi) {
            $surat_rasmi_signatory_user = resolveMemoSignatoryUserByPosition($conn, $signatory_position);
            if (!$surat_rasmi_signatory_user) {
                throw new Exception('signatory_required');
            }
            $signatory_name = trim((string) ($surat_rasmi_signatory_user['fullname'] ?? ''));
            $signatory_position = getDisplayPositionForUser($surat_rasmi_signatory_user) ?: trim((string) ($surat_rasmi_signatory_user['position'] ?? $signatory_position));
            $signatory_department = normalizeDepartmentValue($surat_rasmi_signatory_user['department'] ?? '');
            $department_officer_user_id = (int) ($surat_rasmi_signatory_user['id'] ?? 0);
            $surat_rasmi_signatory_is_preparer = (int) ($surat_rasmi_signatory_user['id'] ?? 0) === $preparer_user_id;
            $surat_rasmi_signatory_is_current = (int) ($surat_rasmi_signatory_user['id'] ?? 0) === $current_user_id;
            if ($preparer_signed && (int) ($surat_rasmi_signatory_user['id'] ?? 0) !== $current_user_id) {
                throw new Exception('signatory_permission');
            }
        } elseif ($is_memo) {
            $memo_signatory_user = resolveMemoSignatoryUserByPosition($conn, $signatory_position);
            if (!$memo_signatory_user) {
                throw new Exception('signatory_required');
            }
            $signatory_name = trim((string) ($memo_signatory_user['fullname'] ?? ''));
            $signatory_position = getDisplayPositionForUser($memo_signatory_user) ?: trim((string) ($memo_signatory_user['position'] ?? $signatory_position));
            $signatory_department = normalizeDepartmentValue($memo_signatory_user['department'] ?? '');
            $department_officer_user_id = (int) ($memo_signatory_user['id'] ?? 0);
            $memo_signatory_is_preparer = (int) ($memo_signatory_user['id'] ?? 0) === $preparer_user_id;
            if ($preparer_signed && !$is_department_officer_revision && (int) ($memo_signatory_user['id'] ?? 0) !== $current_user_id) {
                throw new Exception('signatory_permission');
            }
        } else {
            applyDepartmentHeadSignatory($signatory_name, $signatory_position, $signatory_department, $department_head_user, $draft_department);
        }
        $approval_recipients = [];
        $route = [
            'needs_department_officer' => false,
            'department_officer_user' => null,
            'current_user' => null,
            'approval_status' => $is_surat_rasmi && $is_ready_to_send ? 'lulus' : 'draft',
            'approval_stage' => 0,
            'department_officer_status' => 'tidak_perlu',
            'department_officer_requested_now' => false,
        ];
        $support_user = null;
        $support_user_id = 0;
        $support_required = 0;
        $support_name = null;
        $support_email = null;

        if ($is_memo) {
            $approval_recipients = resolveMemoApprovalRecipients(
                $conn,
                $recipient_organization,
                '',
                buildMemoFinalRecipientSelection($recipient_organization),
                $preparer_user_id,
                [],
                false,
                $selected_distribution_staff_ids
            );
            if ($is_ready_to_send) {
                $route = buildMemoSignatoryRoute($conn, $memo_signatory_user, $preparer_user_id, $draft_department, $department_head_user);
                $support_user = $route['current_user'];
                $support_user_id = (int) ($support_user['id'] ?? 0);
                $support_required = $support_user_id > 0 ? 1 : 0;
                $support_name = $support_user['fullname'] ?? null;
                $support_email = $support_user['email'] ?? null;
            } else {
                $route['approval_status'] = 'draft';
            }
        } else {
            $excluded_approval_user_ids = $department_head_user ? [(int) ($department_head_user['id'] ?? 0)] : [];
            $approval_recipients = $is_surat_rasmi
                ? ($recipient_organization !== '' ? resolveMemoApprovalRecipients($conn, $recipient_organization, '', buildMemoFinalRecipientSelection($recipient_organization), $preparer_user_id, [(int) ($surat_rasmi_signatory_user['id'] ?? 0)], false, $selected_distribution_staff_ids) : [])
                : resolveMemoApprovalRecipients($conn, $recipient_organization, $attention_to, $routing_selection, $preparer_user_id, $excluded_approval_user_ids);

            if ($is_ready_to_send) {
                if (!$is_surat_rasmi && !approvalRouteBodiesCoverRecipients($approval_route_bodies_json, $approval_recipients)) {
                    throw new Exception('approval_content_required');
                }
                if ($is_surat_rasmi) {
                    $route = buildSuratRasmiSignatoryRoute($conn, $surat_rasmi_signatory_user, $preparer_user_id, $draft_department, $department_head_user);
                    $support_user = $route['current_user'];
                    $support_user_id = (int) ($support_user['id'] ?? 0);
                    $support_required = $support_user_id > 0 ? 1 : 0;
                    $support_name = $support_user['fullname'] ?? null;
                    $support_email = $support_user['email'] ?? null;
                } else {
                    $route = buildDraftApprovalRoute($conn, $preparer_user_id, $draft_department, $department_officer_user_id, $approval_recipients);
                    $support_user = $route['current_user'];
                    $support_user_id = (int) ($support_user['id'] ?? 0);
                    $support_required = $support_user_id > 0 ? 1 : 0;
                    $support_name = $support_user['fullname'] ?? null;
                    $support_email = $support_user['email'] ?? null;
                    applyDepartmentHeadSignatory($signatory_name, $signatory_position, $signatory_department, $department_head_user, $draft_department);
                }
            }
        }

        $document_stmt = mysqli_prepare($conn, "SELECT id, file_numbering FROM documents WHERE id = ? AND deleted_at IS NULL LIMIT 1 FOR UPDATE");
        mysqli_stmt_bind_param($document_stmt, "i", $draft['document_id']);
        mysqli_stmt_execute($document_stmt);
        $document_exists = mysqli_fetch_assoc(mysqli_stmt_get_result($document_stmt));
        if (!$document_exists) {
            throw new Exception('document_missing');
        }

        $to_person = buildDraftRecipientSummary($recipient_name, $recipient_organization, $attention_to);
        $from_person = trim((string) ($draft['folder_department'] ?? $draft['department'] ?? ''));
        $ref_no = trim((string) ($draft['ref_no'] ?? ''));
        $file_numbering = trim((string) ($document_exists['file_numbering'] ?? ''));
        if ($is_ready_to_send && ($file_numbering === '' || strtoupper($file_numbering) === 'X' || $file_numbering === $ref_no)) {
            $numbering_folder_id = (int) ($draft['folder_id'] ?? $folder_id);
            if (!lockFolderForDocumentNumbering($conn, $numbering_folder_id)) {
                throw new Exception('folder');
            }
            $file_numbering = generateNextDocumentFileNumbering($conn, $numbering_folder_id);
        } elseif (!$is_ready_to_send) {
            $file_numbering = 'X';
        }
        if ($is_surat_rasmi) {
            $surat_rasmi_reference_display = formatDraftLetterReferenceDisplay($draft_department, $ref_no, $is_ready_to_send ? $file_numbering : 'X');
            $letter_pages = applySuratRasmiGeneratedReferenceToPages(!empty($letter_pages) ? $letter_pages : [$letter_body], $surat_rasmi_reference_display);
            $letter_body = $letter_pages[0] ?? $letter_body;
            $letter_pages_json = json_encode($letter_pages, JSON_UNESCAPED_UNICODE);
        }
        $signatory_signature_path = trim((string) ($draft['signatory_signature_path'] ?? ''));
        $surat_rasmi_has_final_recipient = $is_surat_rasmi && !empty($approval_recipients);
        if ($is_ready_to_send && $is_department_officer_revision && !draftLetterHasGeneratedClosing($letter_body, $letter_pages_json)) {
            throw new Exception('closing_required_before_signature');
        }
        if ($is_ready_to_send && $is_department_officer_revision && !$preparer_signed) {
            throw new Exception('preparer_signature_required');
        }
        if ($is_ready_to_send && $preparer_signed && !draftLetterHasGeneratedClosing($letter_body, $letter_pages_json)) {
            throw new Exception('closing_required_before_signature');
        }

        if ($is_ready_to_send) {
            if ($is_memo) {
                if ($is_department_officer_revision) {
                    $revision_signature_path = $preparer_signed ? ($posted_document_signature_path ?: getUserSignaturePath($conn, $current_user_id)) : '';
                    if ($preparer_signed && $revision_signature_path === '') {
                        throw new Exception('preparer_signature_missing');
                    }
                } else {
                    $signatory_signature_path = ($memo_signatory_is_preparer && $preparer_signed) ? ($posted_document_signature_path ?: getUserSignaturePath($conn, $preparer_user_id)) : '';
                }
                if (!$is_department_officer_revision && $preparer_signed && $signatory_signature_path === '') {
                    throw new Exception('preparer_signature_missing');
                }
            } elseif ($is_surat_rasmi) {
                $signatory_signature_path = ($surat_rasmi_signatory_is_current && $preparer_signed) ? ($posted_document_signature_path ?: getUserSignaturePath($conn, $current_user_id)) : '';
                if ($preparer_signed && $signatory_signature_path === '') {
                    throw new Exception('preparer_signature_missing');
                }
            } else if (empty($route['needs_department_officer']) && !$surat_rasmi_has_final_recipient) {
                if ($is_surat_rasmi) {
                    if (!$preparer_signed) {
                        throw new Exception('preparer_signature_required');
                    }
                    $signatory_signature_path = $preparer_signed ? ($posted_document_signature_path ?: getUserSignaturePath($conn, $preparer_user_id)) : '';
                    if ($preparer_signed && $signatory_signature_path === '') {
                        throw new Exception('preparer_signature_missing');
                    }
                } else {
                    $signatory_signature_path = $posted_document_signature_path ?: getUserSignaturePath($conn, $preparer_user_id);
                    if (!$preparer_signed) {
                        throw new Exception('preparer_signature_required');
                    }
                    if ($signatory_signature_path === '') {
                        throw new Exception('preparer_signature_missing');
                    }
                }
            }
        } elseif ($is_ready_to_send && !empty($route['needs_department_officer']) && in_array($draft['approval_status'] ?? '', ['draft', 'ditolak'], true)) {
            $signatory_signature_path = '';
        }
        if (!$is_ready_to_send) {
            $signatory_signature_path = '';
        }
        $existing_routing_positions = decodeMemoRoutingPositions($draft['routing_positions'] ?? '');
        $new_routing_positions = $routing_positions;
        $support_changed = !$is_surat_rasmi && (($draft['approval_flow'] ?? 'single') !== $approval_flow
            || (int) ($draft['department_officer_user_id'] ?? 0) !== ($route['needs_department_officer'] ? $department_officer_user_id : 0)
            || $existing_routing_positions !== $new_routing_positions);
        if ($is_memo) {
            $existing_recipient_ids = array_map(function ($recipient) {
                return (int) ($recipient['user_id'] ?? 0);
            }, getLetterApprovalRecipients($conn, $draft_id));
            $new_recipient_ids = array_map(function ($recipient) {
                return (int) ($recipient['id'] ?? 0);
            }, $approval_recipients);
            sort($existing_recipient_ids);
            sort($new_recipient_ids);
            $support_changed = (int) ($draft['department_officer_user_id'] ?? 0) !== ($route['needs_department_officer'] ? $department_officer_user_id : 0)
                || (int) ($draft['memo_preparer_head_user_id'] ?? 0) !== (int) (($route['memo_preparer_head_user']['id'] ?? 0))
                || $existing_recipient_ids !== $new_recipient_ids;
        } elseif ($is_surat_rasmi) {
            $existing_recipient_ids = array_map(function ($recipient) {
                return (int) ($recipient['user_id'] ?? 0);
            }, getLetterApprovalRecipients($conn, $draft_id));
            $new_recipient_ids = array_map(function ($recipient) {
                return (int) ($recipient['id'] ?? 0);
            }, $approval_recipients);
            $support_changed = (int) ($draft['department_officer_user_id'] ?? 0) !== ($route['needs_department_officer'] ? $department_officer_user_id : 0)
                || (int) ($draft['memo_preparer_head_user_id'] ?? 0) !== (int) (($route['memo_preparer_head_user']['id'] ?? 0))
                || $existing_recipient_ids !== $new_recipient_ids;
        }
        $is_rejected_resubmission = (($draft['approval_status'] ?? '') === 'ditolak'
            || ($draft['approval_status'] ?? '') === 'perlu_pindaan_penyedia'
            || ($draft['support_status'] ?? '') === 'ditolak');
        $is_draft_submission = $is_ready_to_send
            && ((($draft['status'] ?? 'draf') === 'draf') || (($draft['approval_status'] ?? 'draft') === 'draft'));
        $restart_approval = $support_changed || $is_rejected_resubmission || $is_draft_submission;
        if ($is_department_officer_revision) {
            $restart_approval = false;
        }
        if (!$restart_approval) {
            $support_user_id = (int) ($draft['support_user_id'] ?? 0);
            $support_required = (int) ($draft['support_required'] ?? ($support_user_id > 0 ? 1 : 0));
            $support_name = $draft['support_name'] ?? null;
            $support_email = $draft['support_email'] ?? null;
        }
        $support_status = $is_ready_to_send && $support_required
            ? ($restart_approval ? 'menunggu' : ($draft['support_status'] ?? 'menunggu'))
            : 'tidak_perlu';
        $preparer_signed_sql = ($is_ready_to_send && (($is_memo && $memo_signatory_is_preparer && $preparer_signed) || ($is_surat_rasmi && $surat_rasmi_signatory_is_current && $preparer_signed) || (!$is_memo && !$is_surat_rasmi && empty($route['needs_department_officer']) && $preparer_signed)))
            ? "IF(preparer_signed_at IS NULL, NOW(), preparer_signed_at)"
            : "NULL";
        $support_requested_sql = ($is_ready_to_send && $support_required && $restart_approval) ? "support_requested_at = NOW()," : (!$is_ready_to_send ? "support_requested_at = NULL," : "");
        $support_note_reset_sql = ($is_surat_rasmi || $restart_approval || !$is_ready_to_send) ? "support_note = NULL," : "";
        $submitted_at_sql = $is_ready_to_send
            ? "submitted_at = IF(submitted_at IS NULL, NOW(6), submitted_at),"
            : "submitted_at = NULL,";

        $update_doc = mysqli_prepare($conn, "UPDATE documents
            SET ref_no = ?, file_numbering = ?, subject = ?, doc_date = ?, from_person = ?, to_person = ?, doc_type = ?
            WHERE id = ? AND deleted_at IS NULL");
        mysqli_stmt_bind_param($update_doc, "sssssssi", $ref_no, $file_numbering, $subject, $letter_date, $from_person, $to_person, $doc_type, $draft['document_id']);
        if (!mysqli_stmt_execute($update_doc)) {
            throw new Exception(mysqli_error($conn));
        }

        $attachment_result = saveDocumentAttachments($conn, (int) $draft['document_id'], $folder_id, $uploaded_files);
        if (!empty($attachment_result['first_path'])) {
            syncDocumentPrimaryFilePath($conn, (int) $draft['document_id']);
        }

        $update_draft = mysqli_prepare($conn, "UPDATE letter_drafts
            SET letter_date = ?, subject = ?, doc_type = ?, recipient_name = ?, recipient_organization = ?, recipient_address = ?, attention_to = ?, routing_positions = ?, greeting = ?, letter_body = ?, letter_pages = ?, approval_page_body = ?, approval_page_subject = ?, approval_route_bodies = ?, letter_page_signers = ?, page_number_position = ?, page_header_text = ?, page_footer_text = ?, closing_text = ?, signatory_name = ?, signatory_position = ?, signatory_department = ?, signatory_signature_path = ?, preparer_signed_at = {$preparer_signed_sql}, status = ?, support_required = ?, support_user_id = ?, support_name = ?, support_email = ?, support_status = ?, {$support_requested_sql} {$support_note_reset_sql} {$submitted_at_sql} support_responded_at = IF(? IN ('tidak_perlu','menunggu'), NULL, support_responded_at), distribution_staff_list = ?, distribution_page_content = ?, updated_by = ?, updated_at = CURRENT_TIMESTAMP
            WHERE id = ? AND deleted_at IS NULL");
        mysqli_stmt_bind_param(
            $update_draft,
            'sssssssssssssssssssssssiiisssssiii',
            $letter_date,
            $subject,
            $doc_type,
            $recipient_name,
            $recipient_organization,
            $recipient_address,
            $attention_to,
            $routing_positions_json,
            $greeting,
            $letter_body,
            $letter_pages_json,
            $approval_page_body,
            $approval_page_subject,
            $approval_route_bodies_json,
            $letter_page_signers_json,
            $page_number_position,
            $page_header_text,
            $page_footer_text,
            $closing_text,
            $signatory_name,
            $signatory_position,
            $signatory_department,
            $signatory_signature_path,
            $status,
            $support_required,
            $support_user_id,
            $support_name,
            $support_email,
            $support_status,
            $support_status,
            $distribution_staff_list_json,
            $distribution_page_content,
            $current_user_id,
            $draft_id
        );
        if (!mysqli_stmt_execute($update_draft)) {
            throw new Exception(mysqli_error($conn));
        }
        $include_distribution_value = $include_distribution_page ? 1 : 0;
        $distribution_state_update = mysqli_prepare($conn, "UPDATE letter_drafts SET include_distribution_page = ? WHERE id = ?");
        mysqli_stmt_bind_param($distribution_state_update, "ii", $include_distribution_value, $draft_id);
        if (!mysqli_stmt_execute($distribution_state_update)) {
            throw new Exception(mysqli_error($conn));
        }
        if ($template_id > 0) {
            $template_update = mysqli_prepare($conn, "UPDATE letter_drafts SET template_id = ? WHERE id = ?");
            mysqli_stmt_bind_param($template_update, "ii", $template_id, $draft_id);
            mysqli_stmt_execute($template_update);
        }

        $approval_status = $is_ready_to_send
            ? ($restart_approval ? $route['approval_status'] : ($draft['approval_status'] ?? 'menunggu_pelulus'))
            : 'draft';
        $approval_stage = $is_ready_to_send
            ? ($restart_approval ? (int) $route['approval_stage'] : (int) ($draft['approval_stage'] ?? 1))
            : 0;
        $department_officer_user = $route['department_officer_user'];
        $department_officer_save_id = $is_ready_to_send
            ? ($route['needs_department_officer'] ? (int) ($department_officer_user['id'] ?? $department_officer_user_id) : 0)
            : $department_officer_user_id;
        $department_officer_name = $is_ready_to_send ? ($department_officer_user['fullname'] ?? null) : null;
        $department_officer_email = $is_ready_to_send ? ($department_officer_user['email'] ?? null) : null;
        $department_officer_status = $is_ready_to_send
            ? ($restart_approval ? $route['department_officer_status'] : ($draft['department_officer_status'] ?? 'tidak_perlu'))
            : 'tidak_perlu';
        $memo_preparer_head_user = $route['memo_preparer_head_user'] ?? null;
        $memo_preparer_head_save_id = $is_ready_to_send
            ? ($restart_approval ? (int) ($memo_preparer_head_user['id'] ?? 0) : (int) ($draft['memo_preparer_head_user_id'] ?? 0))
            : 0;
        $memo_preparer_head_name = $is_ready_to_send
            ? ($restart_approval ? ($memo_preparer_head_user['fullname'] ?? null) : ($draft['memo_preparer_head_name'] ?? null))
            : null;
        $memo_preparer_head_email = $is_ready_to_send
            ? ($restart_approval ? ($memo_preparer_head_user['email'] ?? null) : ($draft['memo_preparer_head_email'] ?? null))
            : null;
        $memo_preparer_head_status = $is_ready_to_send
            ? ($restart_approval ? ($route['memo_preparer_head_status'] ?? 'tidak_perlu') : ($draft['memo_preparer_head_status'] ?? 'tidak_perlu'))
            : 'tidak_perlu';
        if ($is_department_officer_revision && $is_ready_to_send) {
            $approval_status = 'menunggu_pegawai_bahagian';
            $approval_stage = 1;
            $department_officer_save_id = (int) ($draft['department_officer_user_id'] ?? $department_officer_user_id);
            $department_officer_name = $draft['department_officer_name'] ?? $department_officer_name;
            $department_officer_email = $draft['department_officer_email'] ?? $department_officer_email;
            $department_officer_status = 'menunggu';
        }
        $department_officer_revision_signature_sql = '';
        if ($is_department_officer_revision && $is_ready_to_send && $preparer_signed) {
            $revision_signature_path = $posted_document_signature_path ?: getUserSignaturePath($conn, $current_user_id);
            if ($revision_signature_path === '') {
                throw new Exception('preparer_signature_missing');
            }
            $department_officer_revision_signature_sql = "department_officer_signature_path = '" . mysqli_real_escape_string($conn, $revision_signature_path) . "', department_officer_responded_at = NOW(),";
        }
        $approval_requested_sql = ($restart_approval || !$is_ready_to_send)
            ? "department_officer_decision = 'belum_diputuskan', department_officer_requested_at = " . ($route['department_officer_requested_now'] ? "NOW()" : "NULL") . ", department_officer_approved_at = NULL, department_officer_responded_at = NULL, department_officer_signature_path = NULL, department_officer_note = NULL,"
            : "";
        $memo_preparer_head_requested_sql = ($restart_approval || !$is_ready_to_send)
            ? "memo_preparer_head_requested_at = " . (!empty($route['memo_preparer_head_requested_now']) ? "NOW()" : "NULL") . ", memo_preparer_head_responded_at = NULL, memo_preparer_head_note = NULL,"
            : "";
        $approval_update = mysqli_prepare($conn, "UPDATE letter_drafts
            SET approval_flow = ?, approval_status = ?, approval_stage = ?,
                department_officer_user_id = ?, department_officer_name = ?, department_officer_email = ?, department_officer_status = ?,
                memo_preparer_head_user_id = ?, memo_preparer_head_name = ?, memo_preparer_head_email = ?, memo_preparer_head_status = ?,
                {$approval_requested_sql} {$memo_preparer_head_requested_sql} {$department_officer_revision_signature_sql} updated_by = ?, updated_at = CURRENT_TIMESTAMP
            WHERE id = ? AND deleted_at IS NULL");
        mysqli_stmt_bind_param(
            $approval_update,
            "ssiisssisssii",
            $approval_flow,
            $approval_status,
            $approval_stage,
            $department_officer_save_id,
            $department_officer_name,
            $department_officer_email,
            $department_officer_status,
            $memo_preparer_head_save_id,
            $memo_preparer_head_name,
            $memo_preparer_head_email,
            $memo_preparer_head_status,
            $current_user_id,
            $draft_id
        );
        if (!mysqli_stmt_execute($approval_update)) {
            throw new Exception(mysqli_error($conn));
        }
        if ($is_memo) {
            if ($restart_approval || !$is_ready_to_send) {
                syncMemoDeliveryRecipients($conn, $draft_id, $approval_recipients, $is_ready_to_send && !$route['needs_department_officer']);
            }
        } elseif ($is_surat_rasmi) {
            if ($restart_approval || !$is_ready_to_send) {
                syncMemoDeliveryRecipients($conn, $draft_id, $approval_recipients, $is_ready_to_send && !$route['needs_department_officer']);
            }
        } elseif ($restart_approval || !$is_ready_to_send) {
            syncMemoApprovalRecipients($conn, $draft_id, $approval_recipients, $is_ready_to_send && !$route['needs_department_officer']);
        }

        mysqli_commit($conn);
        if ($is_department_officer_revision) {
            logActivity($conn, $current_user_id, 'finish_department_officer_revision', "Ketua Bahagian selesai membuat pindaan surat: {$ref_no} - {$subject} (Draft ID: {$draft_id})");
            header("Location: draft_letter_print.php?id={$draft_id}&support_success=revision_saved");
            exit();
        }

        logActivity($conn, $current_user_id, 'update_draft_letter', "Update draft letter: {$ref_no} - {$subject} (Draft ID: {$draft_id})");
        if ($is_ready_to_send && $restart_approval && $route['needs_department_officer'] && $support_required && $support_email) {
            sendDraftLetterSupportRequestEmail($support_email, $support_name, [
                'id' => $draft_id,
                'ref_no' => $ref_no,
                'subject' => $subject,
            ]);
        } elseif ($is_ready_to_send && $restart_approval && !$route['needs_department_officer'] && !empty($approval_recipients)) {
            sendMemoApprovalRecipientEmails($conn, $draft_id, [
                'id' => $draft_id,
                'ref_no' => $ref_no,
                'subject' => $subject,
            ]);
        }
        header("Location: draft_letter_print.php?id={$draft_id}&success=updated");
        exit();
    } catch (Exception $e) {
        mysqli_rollback($conn);

        if ($e->getMessage() === 'not_found') {
            header("Location: draft_letters.php?error=not_found");
            exit();
        }
        if ($e->getMessage() === 'unauthorized') {
            header("Location: draft_letters.php?error=unauthorized");
            exit();
        }
        if ($e->getMessage() === 'approved_locked') {
            echo "<script>alert('Surat yang telah lulus tidak boleh diubah.'); window.location='draft_letter_print.php?id={$draft_id}';</script>";
            exit();
        }
        if ($e->getMessage() === 'document_missing') {
            redirectDraftFormByDocType($doc_type, ['id' => $draft_id, 'error' => 'document_missing']);
        }
        if (in_array($e->getMessage(), ['validation', 'department_officer_required', 'department_officer_department', 'duplicate_approver', 'approval_recipient_required', 'approval_content_required', 'preparer_signature_required', 'preparer_signature_missing', 'signature_invalid', 'closing_required_before_signature', 'signatory_required', 'signatory_permission', 'distribution_recipient_required'], true)) {
            redirectDraftFormByDocType($doc_type, ['id' => $draft_id, 'error' => 'validation', 'msg' => $e->getMessage()]);
        }

        redirectDraftFormByDocType($doc_type, ['id' => $draft_id, 'error' => 'system', 'msg' => $e->getMessage()]);
    }
}

if ($action === 'delete' && isset($_GET['id'])) {
    if (!currentUserCan($conn, 'draft_letter', 'delete')) {
        echo "<script>alert('Anda tidak mempunyai kebenaran untuk memadam surat ini.'); window.location='draft_letters.php';</script>";
        exit();
    }

    $draft_id = (int) $_GET['id'];
    $draft_stmt = mysqli_prepare($conn, "SELECT id, document_id, ref_no, subject, department, created_by FROM letter_drafts WHERE id = ? AND deleted_at IS NULL LIMIT 1");
    mysqli_stmt_bind_param($draft_stmt, "i", $draft_id);
    mysqli_stmt_execute($draft_stmt);
    $draft = mysqli_fetch_assoc(mysqli_stmt_get_result($draft_stmt));

    if (!$draft) {
        header("Location: draft_letters.php?error=not_found");
        exit();
    }

    $current_user_id = (int) ($_SESSION['user_id'] ?? 0);
    if ((int) ($draft['created_by'] ?? 0) !== $current_user_id
        && !isSameDepartmentDb($conn, $draft['department'] ?? '', $user_department)) {
        header("Location: draft_letters.php?error=unauthorized");
        exit();
    }

    mysqli_begin_transaction($conn);
    try {
        $delete_stmt = mysqli_prepare($conn, "UPDATE letter_drafts SET deleted_at = NOW(), deleted_by = ? WHERE id = ? AND deleted_at IS NULL");
        mysqli_stmt_bind_param($delete_stmt, "ii", $current_user_id, $draft_id);
        if (!mysqli_stmt_execute($delete_stmt)) {
            throw new Exception(mysqli_error($conn));
        }

        $document_id = (int) ($draft['document_id'] ?? 0);
        if ($document_id > 0) {
            $document_stmt = mysqli_prepare($conn, "SELECT id, subject FROM documents WHERE id = ? AND deleted_at IS NULL LIMIT 1 FOR UPDATE");
            mysqli_stmt_bind_param($document_stmt, "i", $document_id);
            mysqli_stmt_execute($document_stmt);
            $document = mysqli_fetch_assoc(mysqli_stmt_get_result($document_stmt));

            if ($document) {
                $delete_doc_stmt = mysqli_prepare($conn, "UPDATE documents SET deleted_at = NOW(), deleted_by = ? WHERE id = ? AND deleted_at IS NULL");
                mysqli_stmt_bind_param($delete_doc_stmt, "ii", $current_user_id, $document_id);
                if (!mysqli_stmt_execute($delete_doc_stmt)) {
                    throw new Exception(mysqli_error($conn));
                }

                $delete_log = mysqli_prepare($conn, "INSERT INTO document_delete_log (document_id, document_subject, deleted_by, deleted_at, reason) VALUES (?, ?, ?, NOW(), ?)");
                if ($delete_log) {
                    $delete_reason = 'Dipadam bersama surat';
                    $document_subject = $document['subject'] ?? $draft['subject'];
                    mysqli_stmt_bind_param($delete_log, "isis", $document_id, $document_subject, $current_user_id, $delete_reason);
                    mysqli_stmt_execute($delete_log);
                }
            }
        }

        mysqli_commit($conn);
    } catch (Exception $e) {
        mysqli_rollback($conn);
        header("Location: draft_letters.php?error=delete_failed");
        exit();
    }

    logActivity($conn, $current_user_id, 'delete_draft_letter', "Delete draft letter view: {$draft['ref_no']} - {$draft['subject']} (Draft ID: {$draft_id})");
    header("Location: draft_letters.php?success=deleted");
    exit();
}

if ($action === 'delete_attachment' && isset($_GET['id'], $_GET['attachment_id'])) {
    if (!currentUserCan($conn, 'draft_letter', 'update')) {
        echo "<script>alert('Anda tidak mempunyai kebenaran untuk memadam lampiran sokongan.'); window.location='draft_letters.php';</script>";
        exit();
    }

    $draft_id = (int) $_GET['id'];
    $attachment_id = (int) $_GET['attachment_id'];
    $current_user_id = (int) ($_SESSION['user_id'] ?? 0);

    $attachment_stmt = mysqli_prepare($conn, "SELECT a.id, a.document_id, a.file_path, a.original_name,
            ld.ref_no, ld.subject, ld.doc_type, ld.department, ld.created_by
        FROM document_attachments a
        INNER JOIN letter_drafts ld ON ld.document_id = a.document_id
        WHERE ld.id = ? AND a.id = ? AND ld.deleted_at IS NULL
        LIMIT 1");
    mysqli_stmt_bind_param($attachment_stmt, "ii", $draft_id, $attachment_id);
    mysqli_stmt_execute($attachment_stmt);
    $attachment = mysqli_fetch_assoc(mysqli_stmt_get_result($attachment_stmt));

    if (!$attachment) {
        redirectDraftFormByDocType(getDraftDocumentTypeById($conn, $draft_id), ['id' => $draft_id, 'error' => 'attachment_not_found']);
    }
    $attachment_doc_type = $attachment['doc_type'] ?? 'Memo Kelulusan';

    if ((int) ($attachment['created_by'] ?? 0) !== $current_user_id
        && !isSameDepartmentDb($conn, $attachment['department'] ?? '', $user_department)) {
        redirectDraftFormByDocType($attachment_doc_type, ['id' => $draft_id, 'error' => 'unauthorized']);
    }

    mysqli_begin_transaction($conn);
    try {
        $delete_stmt = mysqli_prepare($conn, "DELETE FROM document_attachments WHERE id = ?");
        mysqli_stmt_bind_param($delete_stmt, "i", $attachment_id);
        if (!mysqli_stmt_execute($delete_stmt)) {
            throw new Exception('Gagal memadam lampiran sokongan.');
        }

        if (!syncDocumentPrimaryFilePath($conn, (int) ($attachment['document_id'] ?? 0))) {
            throw new Exception('Gagal mengemaskini lampiran utama.');
        }

        mysqli_commit($conn);
    } catch (Exception $e) {
        mysqli_rollback($conn);
        redirectDraftFormByDocType($attachment_doc_type, ['id' => $draft_id, 'error' => 'attachment_delete_failed']);
    }

    $file_path = trim((string) ($attachment['file_path'] ?? ''));
    if ($file_path !== '' && file_exists($file_path)) {
        unlink($file_path);
    }

    $attachment_name = $attachment['original_name'] ?: basename($file_path);
    logActivity($conn, $current_user_id, 'delete_draft_attachment', "Delete draft attachment: {$attachment_name} for {$attachment['ref_no']} - {$attachment['subject']} (Draft ID: {$draft_id})");
    redirectDraftFormByDocType($attachment_doc_type, ['id' => $draft_id, 'success' => 'attachment_deleted']);
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && $action === 'support') {
    $draft_id = (int) ($_POST['id'] ?? 0);
    $decision = trim((string) ($_POST['decision'] ?? ''));
    $support_note = trim((string) ($_POST['support_note'] ?? ''));
    $revision_action = trim((string) ($_POST['revision_action'] ?? ''));
    $auto_sign = isset($_POST['auto_sign']) && (string) $_POST['auto_sign'] === '1' && in_array($decision, ['disokong', 'ditolak'], true);
    $current_user_id = (int) ($_SESSION['user_id'] ?? 0);

    if ($draft_id <= 0 || !in_array($decision, ['disokong', 'ditolak', 'tandatangan'], true)) {
        redirectDraftSupportError($draft_id, 'validation');
    }
    if ($decision === 'ditolak' && $support_note === '' && !in_array($revision_action, ['return_to_preparer', 'self_edit'], true)) {
        redirectDraftSupportError($draft_id, 'note_required');
    }

    $draft_stmt = mysqli_prepare($conn, "SELECT * FROM letter_drafts WHERE id = ? AND deleted_at IS NULL LIMIT 1 FOR UPDATE");
    mysqli_begin_transaction($conn);
    mysqli_stmt_bind_param($draft_stmt, "i", $draft_id);
    mysqli_stmt_execute($draft_stmt);
    $draft = mysqli_fetch_assoc(mysqli_stmt_get_result($draft_stmt));

    if (!$draft) {
        mysqli_rollback($conn);
        header("Location: draft_letters.php?error=not_found");
        exit();
    }

    $is_surat_rasmi = strcasecmp(trim((string) ($draft['doc_type'] ?? '')), 'Surat Rasmi') === 0;
    $is_memo = strcasecmp(trim((string) ($draft['doc_type'] ?? '')), 'Memo') === 0;
    $is_memo_kelulusan = strcasecmp(trim((string) ($draft['doc_type'] ?? '')), 'Memo Kelulusan') === 0;
    $document_signature_data = trim((string) ($_POST['document_signature_data'] ?? ''));
    $posted_document_signature_path = savePostedDocumentDigitalSignature($current_user_id, $draft_id, $document_signature_data);
    $all_approval_recipients = getLetterApprovalRecipients($conn, $draft_id);
    $surat_rasmi_has_final_recipient = $is_surat_rasmi && !empty($all_approval_recipients);
    $stage = (int) ($draft['approval_stage'] ?? 1);
    $approval_status = $draft['approval_status'] ?? 'menunggu_pelulus';
    $department_officer_status = $draft['department_officer_status'] ?? '';
    $is_memo_preparer_head_review = ($is_memo || $is_surat_rasmi)
        && $stage === 1
        && (int) ($draft['memo_preparer_head_user_id'] ?? 0) === $current_user_id
        && ($draft['memo_preparer_head_status'] ?? '') === 'menunggu';
    $is_department_officer = $stage === 1
        && (int) ($draft['department_officer_user_id'] ?? 0) === $current_user_id
        && in_array($department_officer_status, ['menunggu', 'menunggu_tandatangan'], true);
    $current_support_actor_user = getApprovedUserById($conn, $current_user_id) ?: [];
    $current_support_actor_is_management = isSameDepartmentDb($conn, $current_support_actor_user['department'] ?? '', 'Pengurusan');
    $current_support_actor_is_head_officer = isHeadOfficerPosition($current_support_actor_user['position'] ?? '');
    if (
        $is_department_officer
        && !$is_memo_preparer_head_review
        && $revision_action === 'self_edit'
        && (
            !($is_memo || $is_surat_rasmi || $is_memo_kelulusan)
            || !$current_support_actor_is_head_officer
            || $current_support_actor_is_management
        )
    ) {
        $revision_action = 'return_to_preparer';
    }
    $recipient_rows = getLetterApprovalRecipients($conn, $draft_id, $current_user_id);
    $recipient_row = $recipient_rows[0] ?? null;
    $recipient_action_status = $recipient_row['status'] ?? '';
    $is_routing_recipient = $stage >= 2
        && $recipient_row
        && in_array($recipient_action_status, ['menunggu', 'menunggu_tandatangan'], true);
    if (!$is_memo_preparer_head_review && !$is_department_officer && !$is_routing_recipient) {
        mysqli_rollback($conn);
        redirectDraftSupportError($draft_id, 'unauthorized');
    }

    if (!in_array($approval_status, ['menunggu_pegawai_bahagian', 'menunggu_pelulus'], true)) {
        mysqli_rollback($conn);
        redirectDraftSupportError($draft_id, 'not_pending');
    }

    $should_email_next = false;
    try {
        $existing_department_officer_signature_path = trim((string) ($draft['department_officer_signature_path'] ?? ''));
        if ($existing_department_officer_signature_path !== '' && !is_file(__DIR__ . '/' . $existing_department_officer_signature_path)) {
            $existing_department_officer_signature_path = '';
        }
        $resolve_department_officer_signature_path = function () use ($conn, $current_user_id, $existing_department_officer_signature_path, $posted_document_signature_path) {
            return $posted_document_signature_path !== ''
                ? $posted_document_signature_path
                : ($existing_department_officer_signature_path !== ''
                ? $existing_department_officer_signature_path
                : getUserSignaturePath($conn, $current_user_id));
        };

        if ($is_memo_preparer_head_review) {
            if ($decision === 'disokong') {
                $signatory_user = getApprovedUserById($conn, (int) ($draft['department_officer_user_id'] ?? 0));
                $signatory_user_id = (int) ($signatory_user['id'] ?? 0);
                if ($signatory_user_id <= 0) {
                    throw new Exception('department_officer_required');
                }
                $next_name = $signatory_user['fullname'] ?? ($draft['department_officer_name'] ?? null);
                $next_email = $signatory_user['email'] ?? ($draft['department_officer_email'] ?? null);
                $next_status = 'menunggu_pegawai_bahagian';
                $update_stmt = mysqli_prepare($conn, "UPDATE letter_drafts
                    SET approval_status = ?, approval_stage = 1,
                        memo_preparer_head_status = 'lulus',
                        memo_preparer_head_note = ?,
                        memo_preparer_head_responded_at = NOW(),
                        department_officer_status = 'menunggu',
                        department_officer_decision = 'belum_diputuskan',
                        department_officer_note = NULL,
                        department_officer_approved_at = NULL,
                        department_officer_signature_path = NULL,
                        department_officer_requested_at = NOW(),
                        department_officer_responded_at = NULL,
                        support_user_id = ?, support_name = ?, support_email = ?,
                        support_status = 'menunggu', support_note = ?, support_responded_at = NULL,
                        updated_by = ?, updated_at = CURRENT_TIMESTAMP
                    WHERE id = ? AND deleted_at IS NULL");
                mysqli_stmt_bind_param($update_stmt, "ssisssii", $next_status, $support_note, $signatory_user_id, $next_name, $next_email, $support_note, $current_user_id, $draft_id);
                $should_email_next = true;
            } else {
                if ($revision_action === 'self_edit') {
                    $next_status = 'sedang_dipinda_ketua_bahagian';
                    $update_stmt = mysqli_prepare($conn, "UPDATE letter_drafts
                        SET approval_status = ?, approval_stage = 1,
                            memo_preparer_head_status = 'menunggu',
                            memo_preparer_head_note = ?,
                            support_status = 'menunggu', support_note = ?, support_responded_at = NULL,
                            support_user_id = ?, support_name = memo_preparer_head_name, support_email = memo_preparer_head_email,
                            updated_by = ?, updated_at = CURRENT_TIMESTAMP
                        WHERE id = ? AND deleted_at IS NULL");
                    mysqli_stmt_bind_param($update_stmt, "sssiii", $next_status, $support_note, $support_note, $current_user_id, $current_user_id, $draft_id);
                    if (!mysqli_stmt_execute($update_stmt)) {
                        throw new Exception('system');
                    }
                    mysqli_commit($conn);
                    logActivity($conn, $current_user_id, 'start_department_officer_revision', "Ketua Bahagian penyedia memilih buat pindaan sendiri: {$draft['ref_no']} - {$draft['subject']} (Draft ID: {$draft_id})");
                    header("Location: " . getDraftLetterFormPageByDocType($draft['doc_type'] ?? 'Memo') . "?id={$draft_id}&revision=department_officer");
                    exit();
                }

                $preparer_user = getApprovedUserById($conn, (int) ($draft['created_by'] ?? 0));
                $preparer_user_id = (int) ($preparer_user['id'] ?? ($draft['created_by'] ?? 0));
                $preparer_name = $preparer_user['fullname'] ?? null;
                $preparer_email = $preparer_user['email'] ?? null;
                $next_status = 'perlu_pindaan_penyedia';
                $update_stmt = mysqli_prepare($conn, "UPDATE letter_drafts
                    SET approval_status = ?, approval_stage = 1,
                        memo_preparer_head_status = 'menunggu',
                        memo_preparer_head_note = ?,
                        support_status = 'menunggu', support_note = ?, support_responded_at = NULL,
                        support_user_id = ?, support_name = ?, support_email = ?,
                        updated_by = ?, updated_at = CURRENT_TIMESTAMP
                    WHERE id = ? AND deleted_at IS NULL");
                mysqli_stmt_bind_param($update_stmt, "sssissii", $next_status, $support_note, $support_note, $preparer_user_id, $preparer_name, $preparer_email, $current_user_id, $draft_id);
                if (!mysqli_stmt_execute($update_stmt)) {
                    throw new Exception('system');
                }

                $push_title = '📝 Pindaan Memo Diperlukan';
                $push_body = "Memo \"{$draft['subject']}\" memerlukan pindaan oleh anda. Catatan: {$support_note}";
                $notif_stmt = mysqli_prepare($conn, "
                    INSERT INTO push_notifications
                    (user_id, title, body, payload_json, notification_type, is_read, created_at)
                    VALUES (?, ?, ?, ?, 'letter_revision_requested', 0, NOW())
                ");
                if ($notif_stmt) {
                    $payload_json = json_encode([
                        'draft_id' => $draft_id,
                        'type' => 'letter_revision_requested',
                        'status' => 'perlu_pindaan_penyedia',
                        'note' => $support_note,
                    ], JSON_UNESCAPED_UNICODE);
                    mysqli_stmt_bind_param($notif_stmt, 'isss', $preparer_user_id, $push_title, $push_body, $payload_json);
                    mysqli_stmt_execute($notif_stmt);
                }
                if (is_file(__DIR__ . '/includes/push_service.php')) {
                    require_once __DIR__ . '/includes/push_service.php';
                    if (function_exists('sendMainppPush')) {
                        @sendMainppPush($conn, $preparer_user_id, $push_title, $push_body, [
                            'draft_id' => (string) $draft_id,
                            'type' => 'letter_revision_requested',
                        ]);
                    }
                }

                mysqli_commit($conn);
                logActivity($conn, $current_user_id, 'request_preparer_revision', "Ketua Bahagian penyedia mohon pindaan kepada penyedia memo: {$draft['ref_no']} - {$draft['subject']} (Draft ID: {$draft_id})");
                header("Location: draft_letter_print.php?id={$draft_id}&support_success=revision_returned");
                exit();
            }
        } elseif ($is_department_officer) {
            if ($decision === 'disokong') {
                if ($department_officer_status !== 'menunggu') {
                    throw new Exception('not_pending');
                }
                if ($is_surat_rasmi && $surat_rasmi_has_final_recipient && $auto_sign) {
                    $signature_path = $resolve_department_officer_signature_path();
                    if ($signature_path === '') {
                        throw new Exception('signature_required');
                    }
                    markMemoDeliveryRecipientsDelivered($conn, $draft_id);
                    $should_email_next = false;
                    $officer_user = getApprovedUserById($conn, $current_user_id);
                    $officer_name = trim((string) ($officer_user['fullname'] ?? ($draft['department_officer_name'] ?? '')));
                    $officer_position = getDisplayPositionForUser($officer_user, $draft['department'] ?? '') ?: trim((string) ($officer_user['position'] ?? 'Ketua Pegawai'));
                    $officer_department = trim((string) ($officer_user['department'] ?? ($draft['department'] ?? '')));
                    $next_status = 'lulus';
                    $update_stmt = mysqli_prepare($conn, "UPDATE letter_drafts
                        SET approval_status = ?, approval_stage = 0,
                            department_officer_status = 'lulus',
                            department_officer_decision = 'lulus',
                            department_officer_note = ?, department_officer_approved_at = NOW(),
                            department_officer_signature_path = ?,
                            department_officer_responded_at = NOW(),
                            signatory_signature_path = ?, signatory_name = ?, signatory_position = ?, signatory_department = ?,
                            preparer_signed_at = IF(preparer_signed_at IS NULL, NOW(), preparer_signed_at),
                            support_user_id = 0, support_name = NULL, support_email = NULL,
                            support_status = 'disokong', support_note = ?, support_responded_at = NOW(),
                            updated_by = ?, updated_at = CURRENT_TIMESTAMP
                        WHERE id = ? AND deleted_at IS NULL");
                    mysqli_stmt_bind_param($update_stmt, "ssssssssii", $next_status, $support_note, $signature_path, $signature_path, $officer_name, $officer_position, $officer_department, $support_note, $current_user_id, $draft_id);
                } elseif ($is_surat_rasmi && !$surat_rasmi_has_final_recipient) {
                    $signature_path = $resolve_department_officer_signature_path();
                    if ($signature_path === '') {
                        throw new Exception('signature_required');
                    }
                    $officer_user = getApprovedUserById($conn, $current_user_id);
                    $officer_name = trim((string) ($officer_user['fullname'] ?? ($draft['department_officer_name'] ?? '')));
                    $officer_position = getDisplayPositionForUser($officer_user, $draft['department'] ?? '') ?: trim((string) ($officer_user['position'] ?? 'Ketua Pegawai'));
                    $officer_department = trim((string) ($officer_user['department'] ?? ($draft['department'] ?? '')));
                    $next_status = 'lulus';
                    $update_stmt = mysqli_prepare($conn, "UPDATE letter_drafts
                        SET approval_status = ?, approval_stage = 0,
                            department_officer_status = 'lulus',
                            department_officer_decision = 'lulus',
                            department_officer_note = ?, department_officer_approved_at = NOW(),
                            department_officer_signature_path = ?, department_officer_responded_at = NOW(),
                            signatory_signature_path = ?, signatory_name = ?, signatory_position = ?, signatory_department = ?,
                            preparer_signed_at = IF(preparer_signed_at IS NULL, NOW(), preparer_signed_at),
                            support_user_id = 0, support_name = NULL, support_email = NULL,
                            support_status = 'tidak_perlu', support_note = ?, support_responded_at = NOW(),
                            updated_by = ?, updated_at = CURRENT_TIMESTAMP
                        WHERE id = ? AND deleted_at IS NULL");
                    mysqli_stmt_bind_param($update_stmt, "ssssssssii", $next_status, $support_note, $signature_path, $signature_path, $officer_name, $officer_position, $officer_department, $support_note, $current_user_id, $draft_id);
                } elseif ($auto_sign) {
                    $signature_path = $resolve_department_officer_signature_path();
                    if ($signature_path === '') {
                        throw new Exception('signature_required');
                    }
                    $officer_user = getApprovedUserById($conn, $current_user_id);
                    $officer_name = trim((string) ($officer_user['fullname'] ?? ($draft['department_officer_name'] ?? '')));
                    $officer_position = trim((string) ($officer_user['position'] ?? 'Ketua Pegawai'));
                    $officer_department = trim((string) ($officer_user['department'] ?? ($draft['department'] ?? '')));
                    if ($is_memo) {
                        markMemoDeliveryRecipientsDelivered($conn, $draft_id);
                        $should_email_next = false;
                        $next_status = 'lulus';
                        $update_stmt = mysqli_prepare($conn, "UPDATE letter_drafts
                            SET approval_status = ?, approval_stage = 0,
                                department_officer_status = 'lulus',
                                department_officer_decision = 'lulus',
                                department_officer_note = ?, department_officer_approved_at = NOW(),
                                department_officer_signature_path = ?, department_officer_responded_at = NOW(),
                                signatory_signature_path = ?, signatory_name = ?, signatory_position = ?, signatory_department = ?,
                                preparer_signed_at = IF(preparer_signed_at IS NULL, NOW(), preparer_signed_at),
                                support_user_id = 0, support_name = NULL, support_email = NULL,
                                support_status = 'disokong', support_note = ?, support_responded_at = NOW(),
                                updated_by = ?, updated_at = CURRENT_TIMESTAMP
                            WHERE id = ? AND deleted_at IS NULL");
                        mysqli_stmt_bind_param($update_stmt, "ssssssssii", $next_status, $support_note, $signature_path, $signature_path, $officer_name, $officer_position, $officer_department, $support_note, $current_user_id, $draft_id);
                    } else {
                    activateMemoApprovalRecipients($conn, $draft_id);
                    $should_email_next = true;
                    $next_recipient_rows = getLetterApprovalRecipients($conn, $draft_id);
                    $next_recipient = $next_recipient_rows[0] ?? null;
                    if ($next_recipient) {
                        $next_status = 'menunggu_pelulus';
                        $update_stmt = mysqli_prepare($conn, "UPDATE letter_drafts
                            SET approval_status = ?, approval_stage = 2,
                                department_officer_status = 'lulus',
                                department_officer_decision = 'lulus',
                                department_officer_note = ?, department_officer_approved_at = NOW(),
                                department_officer_signature_path = ?, department_officer_responded_at = NOW(),
                                signatory_signature_path = ?, signatory_name = ?, signatory_position = ?, signatory_department = ?,
                                preparer_signed_at = IF(preparer_signed_at IS NULL, NOW(), preparer_signed_at),
                                support_user_id = ?, support_name = ?, support_email = ?,
                                support_status = 'menunggu', support_note = ?, support_responded_at = NULL,
                                updated_by = ?, updated_at = CURRENT_TIMESTAMP
                            WHERE id = ? AND deleted_at IS NULL");
                        $next_user_id = (int) ($next_recipient['user_id'] ?? 0);
                        $next_name = $next_recipient['fullname'] ?? null;
                        $next_email = $next_recipient['email'] ?? null;
                        mysqli_stmt_bind_param($update_stmt, "sssssssisssii", $next_status, $support_note, $signature_path, $signature_path, $officer_name, $officer_position, $officer_department, $next_user_id, $next_name, $next_email, $support_note, $current_user_id, $draft_id);
                    } else {
                        $should_email_next = false;
                        $next_status = 'lulus';
                        $update_stmt = mysqli_prepare($conn, "UPDATE letter_drafts
                            SET approval_status = ?, approval_stage = 0,
                                department_officer_status = 'lulus',
                                department_officer_decision = 'lulus',
                                department_officer_note = ?, department_officer_approved_at = NOW(),
                                department_officer_signature_path = ?, department_officer_responded_at = NOW(),
                                signatory_signature_path = ?, signatory_name = ?, signatory_position = ?, signatory_department = ?,
                                preparer_signed_at = IF(preparer_signed_at IS NULL, NOW(), preparer_signed_at),
                                support_user_id = 0, support_name = NULL, support_email = NULL,
                                support_status = 'disokong', support_note = ?, support_responded_at = NOW(),
                                updated_by = ?, updated_at = CURRENT_TIMESTAMP
                            WHERE id = ? AND deleted_at IS NULL");
                        mysqli_stmt_bind_param($update_stmt, "ssssssssii", $next_status, $support_note, $signature_path, $signature_path, $officer_name, $officer_position, $officer_department, $support_note, $current_user_id, $draft_id);
                    }
                    }
                } else {
                    $update_stmt = mysqli_prepare($conn, "UPDATE letter_drafts
                        SET department_officer_status = 'menunggu_tandatangan',
                            department_officer_decision = 'lulus',
                            department_officer_note = ?, department_officer_approved_at = NOW(),
                            support_note = ?, updated_by = ?, updated_at = CURRENT_TIMESTAMP
                        WHERE id = ? AND deleted_at IS NULL");
                    mysqli_stmt_bind_param($update_stmt, "ssii", $support_note, $support_note, $current_user_id, $draft_id);
                }
            } elseif ($decision === 'tandatangan') {
                if ($department_officer_status !== 'menunggu_tandatangan') {
                    throw new Exception('not_pending');
                }
                $signature_path = $resolve_department_officer_signature_path();
                if ($signature_path === '') {
                    throw new Exception('signature_required');
                }

                if (($draft['department_officer_decision'] ?? 'lulus') === 'ditolak') {
                    $preparer_user = getApprovedUserById($conn, (int) ($draft['created_by'] ?? 0));
                    $preparer_user_id = (int) ($preparer_user['id'] ?? ($draft['created_by'] ?? 0));
                    $preparer_name = $preparer_user['fullname'] ?? null;
                    $preparer_email = $preparer_user['email'] ?? null;
                    $next_status = 'ditolak';
                    $update_stmt = mysqli_prepare($conn, "UPDATE letter_drafts
                        SET approval_status = ?, department_officer_status = 'ditolak',
                            department_officer_signature_path = ?, department_officer_responded_at = NOW(),
                            support_status = 'ditolak', support_responded_at = NOW(),
                            support_user_id = ?, support_name = ?, support_email = ?,
                            updated_by = ?, updated_at = CURRENT_TIMESTAMP
                        WHERE id = ? AND deleted_at IS NULL");
                    mysqli_stmt_bind_param($update_stmt, "ssissii", $next_status, $signature_path, $preparer_user_id, $preparer_name, $preparer_email, $current_user_id, $draft_id);
                } else {
                    $officer_user = getApprovedUserById($conn, $current_user_id);
                    $officer_name = trim((string) ($officer_user['fullname'] ?? ($draft['department_officer_name'] ?? '')));
                    $officer_position = trim((string) ($officer_user['position'] ?? 'Ketua Pegawai'));
                    $officer_department = trim((string) ($officer_user['department'] ?? ($draft['department'] ?? '')));
                    if ($is_memo) {
                        markMemoDeliveryRecipientsDelivered($conn, $draft_id);
                        $should_email_next = false;
                        $next_status = 'lulus';
                        $update_stmt = mysqli_prepare($conn, "UPDATE letter_drafts
                            SET approval_status = ?, approval_stage = 0,
                                department_officer_status = 'lulus', department_officer_signature_path = ?, department_officer_responded_at = NOW(),
                                signatory_signature_path = ?, signatory_name = ?, signatory_position = ?, signatory_department = ?,
                                preparer_signed_at = IF(preparer_signed_at IS NULL, NOW(), preparer_signed_at),
                                support_user_id = 0, support_name = NULL, support_email = NULL,
                                support_status = 'disokong', support_responded_at = NOW(),
                                updated_by = ?, updated_at = CURRENT_TIMESTAMP
                            WHERE id = ? AND deleted_at IS NULL");
                        mysqli_stmt_bind_param($update_stmt, "ssssssii", $next_status, $signature_path, $signature_path, $officer_name, $officer_position, $officer_department, $current_user_id, $draft_id);
                    } else {
                    activateMemoApprovalRecipients($conn, $draft_id);
                    $should_email_next = true;
                    $next_recipient_rows = getLetterApprovalRecipients($conn, $draft_id);
                    $next_recipient = $next_recipient_rows[0] ?? null;
                    if ($next_recipient) {
                        $next_status = 'menunggu_pelulus';
                        $update_stmt = mysqli_prepare($conn, "UPDATE letter_drafts
                            SET approval_status = ?, approval_stage = 2,
                                department_officer_status = 'lulus', department_officer_signature_path = ?, department_officer_responded_at = NOW(),
                                signatory_signature_path = ?, signatory_name = ?, signatory_position = ?, signatory_department = ?,
                                preparer_signed_at = IF(preparer_signed_at IS NULL, NOW(), preparer_signed_at),
                                support_user_id = ?, support_name = ?, support_email = ?,
                                support_status = 'menunggu', support_responded_at = NULL,
                                updated_by = ?, updated_at = CURRENT_TIMESTAMP
                            WHERE id = ? AND deleted_at IS NULL");
                        $next_user_id = (int) ($next_recipient['user_id'] ?? 0);
                        $next_name = $next_recipient['fullname'] ?? null;
                        $next_email = $next_recipient['email'] ?? null;
                        mysqli_stmt_bind_param($update_stmt, "ssssssissii", $next_status, $signature_path, $signature_path, $officer_name, $officer_position, $officer_department, $next_user_id, $next_name, $next_email, $current_user_id, $draft_id);
                    } else {
                        $should_email_next = false;
                        $next_status = 'lulus';
                        $update_stmt = mysqli_prepare($conn, "UPDATE letter_drafts
                            SET approval_status = ?, approval_stage = 0,
                                department_officer_status = 'lulus', department_officer_signature_path = ?, department_officer_responded_at = NOW(),
                                signatory_signature_path = ?, signatory_name = ?, signatory_position = ?, signatory_department = ?,
                                preparer_signed_at = IF(preparer_signed_at IS NULL, NOW(), preparer_signed_at),
                                support_user_id = 0, support_name = NULL, support_email = NULL,
                                support_status = 'disokong', support_responded_at = NOW(),
                                updated_by = ?, updated_at = CURRENT_TIMESTAMP
                            WHERE id = ? AND deleted_at IS NULL");
                        mysqli_stmt_bind_param($update_stmt, "ssssssii", $next_status, $signature_path, $signature_path, $officer_name, $officer_position, $officer_department, $current_user_id, $draft_id);
                    }
                    }
                }
            } else {
                if ($department_officer_status !== 'menunggu') {
                    throw new Exception('not_pending');
                }

                if ($revision_action === 'self_edit') {
                    $next_status = 'sedang_dipinda_ketua_bahagian';
                    $update_stmt = mysqli_prepare($conn, "UPDATE letter_drafts
                        SET approval_status = ?, approval_stage = 1,
                            department_officer_status = 'menunggu',
                            department_officer_decision = 'belum_diputuskan',
                            department_officer_note = ?,
                            department_officer_approved_at = NULL,
                            department_officer_signature_path = NULL,
                            department_officer_responded_at = NULL,
                            support_status = 'menunggu', support_note = ?, support_responded_at = NULL,
                            support_user_id = ?, support_name = department_officer_name, support_email = department_officer_email,
                            updated_by = ?, updated_at = CURRENT_TIMESTAMP
                        WHERE id = ? AND deleted_at IS NULL");
                    mysqli_stmt_bind_param($update_stmt, "sssiii", $next_status, $support_note, $support_note, $current_user_id, $current_user_id, $draft_id);
                    if (!mysqli_stmt_execute($update_stmt)) {
                        throw new Exception('system');
                    }
                    mysqli_commit($conn);
                    logActivity($conn, $current_user_id, 'start_department_officer_revision', "Ketua Bahagian memilih buat pindaan sendiri: {$draft['ref_no']} - {$draft['subject']} (Draft ID: {$draft_id})");
                    header("Location: " . getDraftLetterFormPageByDocType($draft['doc_type'] ?? 'Memo Kelulusan') . "?id={$draft_id}&revision=department_officer");
                    exit();
                }

                $preparer_user = getApprovedUserById($conn, (int) ($draft['created_by'] ?? 0));
                $preparer_user_id = (int) ($preparer_user['id'] ?? ($draft['created_by'] ?? 0));
                $preparer_name = $preparer_user['fullname'] ?? null;
                $preparer_email = $preparer_user['email'] ?? null;
                $next_status = 'perlu_pindaan_penyedia';
                $update_stmt = mysqli_prepare($conn, "UPDATE letter_drafts
                    SET approval_status = ?, approval_stage = 1,
                        department_officer_status = 'menunggu',
                        department_officer_decision = 'belum_diputuskan',
                        department_officer_note = ?,
                        department_officer_approved_at = NULL,
                        department_officer_signature_path = NULL, department_officer_responded_at = NULL,
                        support_status = 'menunggu', support_note = ?, support_responded_at = NULL,
                        support_user_id = ?, support_name = ?, support_email = ?,
                        updated_by = ?, updated_at = CURRENT_TIMESTAMP
                    WHERE id = ? AND deleted_at IS NULL");
                mysqli_stmt_bind_param($update_stmt, "sssissii", $next_status, $support_note, $support_note, $preparer_user_id, $preparer_name, $preparer_email, $current_user_id, $draft_id);
                if (!mysqli_stmt_execute($update_stmt)) {
                    throw new Exception('system');
                }

                $push_title = '📝 Pindaan Surat Diperlukan';
                $push_body = "Surat/Memo \"{$draft['subject']}\" memerlukan pindaan oleh anda. Catatan: {$support_note}";
                $notif_stmt = mysqli_prepare($conn, "
                    INSERT INTO push_notifications
                    (user_id, title, body, payload_json, notification_type, is_read, created_at)
                    VALUES (?, ?, ?, ?, 'letter_revision_requested', 0, NOW())
                ");
                if ($notif_stmt) {
                    $payload_json = json_encode([
                        'draft_id' => $draft_id,
                        'type' => 'letter_revision_requested',
                        'status' => 'perlu_pindaan_penyedia',
                        'note' => $support_note,
                    ], JSON_UNESCAPED_UNICODE);
                    mysqli_stmt_bind_param($notif_stmt, 'isss', $preparer_user_id, $push_title, $push_body, $payload_json);
                    mysqli_stmt_execute($notif_stmt);
                }
                if (is_file(__DIR__ . '/includes/push_service.php')) {
                    require_once __DIR__ . '/includes/push_service.php';
                    if (function_exists('sendMainppPush')) {
                        @sendMainppPush($conn, $preparer_user_id, $push_title, $push_body, [
                            'draft_id' => (string) $draft_id,
                            'type' => 'letter_revision_requested',
                        ]);
                    }
                }

                mysqli_commit($conn);
                logActivity($conn, $current_user_id, 'request_preparer_revision', "Ketua Bahagian mohon pindaan kepada penyedia surat: {$draft['ref_no']} - {$draft['subject']} (Draft ID: {$draft_id})");
                header("Location: draft_letter_print.php?id={$draft_id}&support_success=revision_returned");
                exit();
            }
        } elseif ($is_routing_recipient) {
            if ($decision === 'disokong') {
                if ($recipient_action_status !== 'menunggu') {
                    throw new Exception('not_pending');
                }
                $signature_path = '';
                if ($auto_sign) {
                    $signature_path = $posted_document_signature_path ?: getUserSignaturePath($conn, $current_user_id);
                    if ($signature_path === '') {
                        throw new Exception('signature_required');
                    }
                    $recipient_update = mysqli_prepare($conn, "UPDATE letter_approval_recipients
                        SET status = 'lulus', decision = 'lulus', note = ?, approved_at = NOW(), signature_path = ?, responded_at = NOW()
                        WHERE id = ? AND draft_id = ?");
                } else {
                    $recipient_update = mysqli_prepare($conn, "UPDATE letter_approval_recipients
                        SET status = 'menunggu_tandatangan', decision = 'lulus', note = ?, approved_at = NOW(), responded_at = NULL
                        WHERE id = ? AND draft_id = ?");
                }
                $recipient_id = (int) $recipient_row['id'];
                if ($auto_sign) {
                    mysqli_stmt_bind_param($recipient_update, "ssii", $support_note, $signature_path, $recipient_id, $draft_id);
                } else {
                    mysqli_stmt_bind_param($recipient_update, "sii", $support_note, $recipient_id, $draft_id);
                }
            } elseif ($decision === 'tandatangan') {
                if ($recipient_action_status !== 'menunggu_tandatangan') {
                    throw new Exception('not_pending');
                }
                $signature_path = $posted_document_signature_path ?: getUserSignaturePath($conn, $current_user_id);
                if ($signature_path === '') {
                    throw new Exception('signature_required');
                }
                $final_recipient_status = (($recipient_row['decision'] ?? 'lulus') === 'ditolak') ? 'ditolak' : 'lulus';
                $recipient_update = mysqli_prepare($conn, "UPDATE letter_approval_recipients
                    SET status = ?, signature_path = ?, responded_at = NOW()
                    WHERE id = ? AND draft_id = ?");
                $recipient_id = (int) $recipient_row['id'];
                mysqli_stmt_bind_param($recipient_update, "ssii", $final_recipient_status, $signature_path, $recipient_id, $draft_id);
            } else {
                if ($revision_action === 'self_edit'
                    && $is_memo_kelulusan
                    && $current_support_actor_is_head_officer
                    && !$current_support_actor_is_management
                ) {
                    if ($recipient_action_status !== 'menunggu') {
                        throw new Exception('not_pending');
                    }
                    $next_status = 'sedang_dipinda_ketua_bahagian';
                    $revision_actor_name = $current_support_actor_user['fullname'] ?? null;
                    $revision_actor_email = $current_support_actor_user['email'] ?? null;
                    $update_stmt = mysqli_prepare($conn, "UPDATE letter_drafts
                        SET approval_status = ?, support_note = ?,
                            support_status = 'menunggu',
                            support_user_id = ?, support_name = ?, support_email = ?,
                            support_responded_at = NULL,
                            updated_by = ?, updated_at = CURRENT_TIMESTAMP
                        WHERE id = ? AND deleted_at IS NULL");
                    mysqli_stmt_bind_param(
                        $update_stmt,
                        "ssissii",
                        $next_status,
                        $support_note,
                        $current_user_id,
                        $revision_actor_name,
                        $revision_actor_email,
                        $current_user_id,
                        $draft_id
                    );
                    if (!mysqli_stmt_execute($update_stmt)) {
                        throw new Exception('system');
                    }
                    mysqli_commit($conn);
                    logActivity($conn, $current_user_id, 'start_approval_recipient_revision', "Penerima kelulusan memilih buat pindaan sendiri: {$draft['ref_no']} - {$draft['subject']} (Draft ID: {$draft_id})");
                    header("Location: " . getDraftLetterFormPageByDocType($draft['doc_type'] ?? 'Memo Kelulusan') . "?id={$draft_id}&revision=department_officer");
                    exit();
                }

                $signature_path = '';
                if ($auto_sign) {
                    $signature_path = $posted_document_signature_path ?: getUserSignaturePath($conn, $current_user_id);
                    if ($signature_path === '') {
                        throw new Exception('signature_required');
                    }
                    $recipient_update = mysqli_prepare($conn, "UPDATE letter_approval_recipients
                        SET status = 'ditolak', decision = 'ditolak', note = ?, approved_at = NOW(), signature_path = ?, responded_at = NOW()
                        WHERE id = ? AND draft_id = ?");
                } else {
                    $recipient_update = mysqli_prepare($conn, "UPDATE letter_approval_recipients
                        SET status = 'menunggu_tandatangan', decision = 'ditolak', note = ?, approved_at = NOW(), responded_at = NULL
                        WHERE id = ? AND draft_id = ?");
                }
                $recipient_id = (int) $recipient_row['id'];
                if ($auto_sign) {
                    mysqli_stmt_bind_param($recipient_update, "ssii", $support_note, $signature_path, $recipient_id, $draft_id);
                } else {
                    mysqli_stmt_bind_param($recipient_update, "sii", $support_note, $recipient_id, $draft_id);
                }
            }
            if (!mysqli_stmt_execute($recipient_update)) {
                throw new Exception('system');
            }

            if (in_array($decision, ['disokong', 'ditolak'], true) && !$auto_sign) {
                $update_stmt = mysqli_prepare($conn, "UPDATE letter_drafts
                    SET support_note = ?, updated_by = ?, updated_at = CURRENT_TIMESTAMP
                    WHERE id = ? AND deleted_at IS NULL");
                mysqli_stmt_bind_param($update_stmt, "sii", $support_note, $current_user_id, $draft_id);
                if (!mysqli_stmt_execute($update_stmt)) {
                    throw new Exception('system');
                }
                mysqli_commit($conn);
                logActivity($conn, $current_user_id, 'decide_draft_letter', "Decision {$decision} pending signature: {$draft['ref_no']} - {$draft['subject']} (Draft ID: {$draft_id})");
                $success_key = $decision === 'ditolak' ? 'rejected_pending_signature' : 'approved';
                header("Location: draft_letter_print.php?id={$draft_id}&support_success={$success_key}");
                exit();
            }

            $summary_stmt = mysqli_prepare($conn, "SELECT
                    SUM(status = 'ditolak') AS rejected_count,
                    SUM(status IN ('menunggu','menunggu_tandatangan')) AS waiting_count,
                    SUM(status = 'belum_mula') AS queued_count
                FROM letter_approval_recipients
                WHERE draft_id = ?");
            mysqli_stmt_bind_param($summary_stmt, "i", $draft_id);
            mysqli_stmt_execute($summary_stmt);
            $summary = mysqli_fetch_assoc(mysqli_stmt_get_result($summary_stmt));
            $rejected_count = (int) ($summary['rejected_count'] ?? 0);
            $waiting_count = (int) ($summary['waiting_count'] ?? 0);
            $queued_count = (int) ($summary['queued_count'] ?? 0);

            if (($decision === 'tandatangan' || $auto_sign) && $rejected_count === 0 && $waiting_count === 0 && $queued_count > 0) {
                activateMemoApprovalRecipients($conn, $draft_id);
                $should_email_next = true;
            }

            $next_recipient_rows = getLetterApprovalRecipients($conn, $draft_id);
            $next_recipient = null;
            foreach ($next_recipient_rows as $candidate) {
                if (($candidate['status'] ?? '') === 'menunggu') {
                    $next_recipient = $candidate;
                    break;
                }
            }
            $still_pending = $next_recipient !== null;
            $next_status = $rejected_count > 0 ? 'ditolak' : ($still_pending ? 'menunggu_pelulus' : 'lulus');
            $support_status = $rejected_count > 0 ? 'ditolak' : ($still_pending ? 'menunggu' : 'disokong');
            $draft_support_note = $support_note;
            if ($decision === 'tandatangan') {
                $draft_support_note = trim((string) ($recipient_row['note'] ?? ''));
            }
            if ($rejected_count > 0) {
                $preparer_user = getApprovedUserById($conn, (int) ($draft['created_by'] ?? 0));
                $next_user_id = (int) ($preparer_user['id'] ?? ($draft['created_by'] ?? 0));
                $next_name = $preparer_user['fullname'] ?? null;
                $next_email = $preparer_user['email'] ?? null;
            } else {
                $next_user_id = (int) ($next_recipient['user_id'] ?? 0);
                $next_name = $next_recipient['fullname'] ?? null;
                $next_email = $next_recipient['email'] ?? null;
            }
            $update_stmt = mysqli_prepare($conn, "UPDATE letter_drafts
                SET approval_status = ?, support_status = ?, support_note = ?,
                    support_user_id = ?, support_name = ?, support_email = ?,
                    support_responded_at = IF(? IN ('disokong','ditolak'), NOW(), NULL),
                    updated_by = ?, updated_at = CURRENT_TIMESTAMP
                WHERE id = ? AND deleted_at IS NULL");
            mysqli_stmt_bind_param($update_stmt, "sssisssii", $next_status, $support_status, $draft_support_note, $next_user_id, $next_name, $next_email, $support_status, $current_user_id, $draft_id);
        }

        if (!mysqli_stmt_execute($update_stmt)) {
            throw new Exception('system');
        }

        if ($is_surat_rasmi && $is_routing_recipient && isset($next_status) && $next_status === 'lulus' && !empty($signature_path)) {
            $final_signer_user = getApprovedUserById($conn, $current_user_id);
            $final_signer_name = trim((string) ($final_signer_user['fullname'] ?? ($draft['signatory_name'] ?? '')));
            $final_signer_position = trim((string) ($draft['signatory_position'] ?? ''));
            $final_signer_department = trim((string) ($final_signer_user['department'] ?? ($draft['signatory_department'] ?? '')));
            $final_sign_update = mysqli_prepare($conn, "UPDATE letter_drafts
                SET signatory_signature_path = ?, signatory_name = ?, signatory_position = ?, signatory_department = ?,
                    preparer_signed_at = IF(preparer_signed_at IS NULL, NOW(), preparer_signed_at)
                WHERE id = ? AND deleted_at IS NULL");
            mysqli_stmt_bind_param($final_sign_update, "ssssi", $signature_path, $final_signer_name, $final_signer_position, $final_signer_department, $draft_id);
            if (!mysqli_stmt_execute($final_sign_update)) {
                throw new Exception('system');
            }
        }

        mysqli_commit($conn);
    } catch (Exception $e) {
        mysqli_rollback($conn);
        redirectDraftSupportError($draft_id, $e->getMessage());
    }

    logActivity($conn, $current_user_id, 'support_draft_letter', "Support decision {$decision}: {$draft['ref_no']} - {$draft['subject']} (Draft ID: {$draft_id})");
    $signature_completed_now = $decision === 'tandatangan' || $auto_sign;
    if (isset($next_status) && $next_status === 'lulus') {
        notifyDraftLetterApprovedToCreator($conn, $draft_id);
    }
    if ($is_memo_preparer_head_review && $decision === 'disokong' && $should_email_next && !empty($next_email)) {
        sendDraftLetterSupportRequestEmail($next_email ?? '', $next_name ?? '', [
            'id' => $draft_id,
            'ref_no' => $draft['ref_no'] ?? '',
            'subject' => $draft['subject'] ?? '',
        ]);
    } elseif ($signature_completed_now && $is_department_officer && $should_email_next) {
        sendMemoApprovalRecipientEmails($conn, $draft_id, [
            'id' => $draft_id,
            'ref_no' => $draft['ref_no'] ?? '',
            'subject' => $draft['subject'] ?? '',
        ]);
    } elseif ($signature_completed_now && $is_routing_recipient && $should_email_next) {
        sendMemoApprovalRecipientEmails($conn, $draft_id, [
            'id' => $draft_id,
            'ref_no' => $draft['ref_no'] ?? '',
            'subject' => $draft['subject'] ?? '',
        ]);
    }
    $success_decision = $signature_completed_now ? 'tandatangan' : $decision;
    header("Location: draft_letter_print.php?id={$draft_id}&support_success={$success_decision}");
    exit();
}

if ($action === 'restore' && isset($_GET['id'])) {
    if (!currentUserCan($conn, 'deleted_item', 'restore')) {
        echo "<script>alert('Anda tidak mempunyai kebenaran untuk memulihkan data dipadam.'); window.location='deleted_items.php';</script>";
        exit();
    }

    $draft_id = (int) $_GET['id'];
    $draft_stmt = mysqli_prepare($conn, "SELECT ld.id, ld.document_id, ld.ref_no, ld.subject, ld.department,
            d.folder_id AS document_folder_id, d.ref_no AS document_ref_no, d.deleted_at AS document_deleted_at,
            f.id AS folder_exists, f.deleted_at AS folder_deleted_at
        FROM letter_drafts ld
        LEFT JOIN documents d ON d.id = ld.document_id
        LEFT JOIN folders f ON f.id = ld.folder_id
        WHERE ld.id = ? AND ld.deleted_at IS NOT NULL
        LIMIT 1");
    mysqli_stmt_bind_param($draft_stmt, "i", $draft_id);
    mysqli_stmt_execute($draft_stmt);
    $draft = mysqli_fetch_assoc(mysqli_stmt_get_result($draft_stmt));

    if (!$draft) {
        header("Location: deleted_items.php?error=draft_not_found");
        exit();
    }

    if ($role !== 'superadmin' && !isSameDepartmentDb($conn, $draft['department'] ?? '', $user_department)) {
        header("Location: deleted_items.php?error=restore_failed");
        exit();
    }

    if (empty($draft['folder_exists'])) {
        header("Location: deleted_items.php?error=folder_missing");
        exit();
    }

    if (!empty($draft['folder_deleted_at'])) {
        header("Location: deleted_items.php?error=restore_folder_first");
        exit();
    }

    mysqli_begin_transaction($conn);
    try {
        $document_id = (int) ($draft['document_id'] ?? 0);
        if ($document_id > 0 && !empty($draft['document_deleted_at'])) {
            $conflict = mysqli_prepare($conn, "SELECT id FROM documents WHERE folder_id = ? AND ref_no = ? AND deleted_at IS NULL LIMIT 1");
            $document_folder_id = (int) ($draft['document_folder_id'] ?? 0);
            $document_ref_no = trim((string) ($draft['document_ref_no'] ?? $draft['ref_no'] ?? ''));
            mysqli_stmt_bind_param($conflict, "is", $document_folder_id, $document_ref_no);
            mysqli_stmt_execute($conflict);
            $conflict_row = mysqli_fetch_assoc(mysqli_stmt_get_result($conflict));
            if ($conflict_row) {
                throw new Exception('duplicate_ref_conflict');
            }

            $restore_document_stmt = mysqli_prepare($conn, "UPDATE documents SET deleted_at = NULL, deleted_by = NULL WHERE id = ? AND deleted_at IS NOT NULL");
            mysqli_stmt_bind_param($restore_document_stmt, "i", $document_id);
            if (!mysqli_stmt_execute($restore_document_stmt)) {
                throw new Exception('restore_failed');
            }
        }

        $restore_stmt = mysqli_prepare($conn, "UPDATE letter_drafts SET deleted_at = NULL, deleted_by = NULL WHERE id = ? AND deleted_at IS NOT NULL");
        mysqli_stmt_bind_param($restore_stmt, "i", $draft_id);
        if (!mysqli_stmt_execute($restore_stmt)) {
            throw new Exception('restore_failed');
        }

        mysqli_commit($conn);
        logActivity($conn, (int) ($_SESSION['user_id'] ?? 0), 'restore_draft_letter', "Restore draft letter: {$draft['ref_no']} - {$draft['subject']} (Draft ID: {$draft_id})");
        header("Location: deleted_items.php?success=draft_restored");
        exit();
    } catch (Exception $e) {
        mysqli_rollback($conn);
        if ($e->getMessage() === 'duplicate_ref_conflict') {
            header("Location: deleted_items.php?error=duplicate_ref_conflict");
            exit();
        }
    }

    header("Location: deleted_items.php?error=restore_failed");
    exit();
}

header("Location: draft_letters.php");
exit();
