<?php
/*
|--------------------------------------------------------------------------
| Manager Approval PIN Modal / Helper
|--------------------------------------------------------------------------
| File location:
|   /rooms/includes/manager_approval_modal.php
|
| What this does:
|   - Adds secure approval PIN support using users.approval_pin_hash
|   - Validates manager/admin/owner/super-admin users
|   - Logs approvals in manager_approval_log
|   - Provides Bootstrap modal JS for buttons using .manager-approval-trigger
|
| Required button fields in the target form:
|   <input type="hidden" name="manager_approved" value="0">
|   <input type="hidden" name="manager_user_id" value="">
|   <input type="hidden" name="manager_pin" value="">
|
| Your existing buttons already use:
|   class="manager-approval-trigger"
|   data-target-form="#approvePoForm1"
|--------------------------------------------------------------------------
*/

if (!function_exists('h')) {
    function h($v): string { return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); }
}

if (!function_exists('ma_table_exists')) {
    function ma_table_exists(PDO $pdo, string $table): bool {
        $stmt = $pdo->prepare("
            SELECT COUNT(*)
            FROM information_schema.tables
            WHERE table_schema = DATABASE()
              AND table_name = :table
        ");
        $stmt->execute([':table' => $table]);
        return (int)$stmt->fetchColumn() > 0;
    }
}

if (!function_exists('ma_col_exists')) {
    function ma_col_exists(PDO $pdo, string $table, string $column): bool {
        $stmt = $pdo->prepare("
            SELECT COUNT(*)
            FROM information_schema.columns
            WHERE table_schema = DATABASE()
              AND table_name = :table
              AND column_name = :column
        ");
        $stmt->execute([':table' => $table, ':column' => $column]);
        return (int)$stmt->fetchColumn() > 0;
    }
}

if (!function_exists('ma_user_name_expr')) {
    function ma_user_name_expr(PDO $pdo, string $alias = 'u'): string {
        if (!ma_table_exists($pdo, 'users')) return "NULL";
        if (ma_col_exists($pdo, 'users', 'firstname') && ma_col_exists($pdo, 'users', 'lastname')) {
            return "TRIM(CONCAT(COALESCE({$alias}.firstname,''), ' ', COALESCE({$alias}.lastname,'')))";
        }
        if (ma_col_exists($pdo, 'users', 'name')) return "{$alias}.name";
        if (ma_col_exists($pdo, 'users', 'full_name')) return "{$alias}.full_name";
        if (ma_col_exists($pdo, 'users', 'username')) return "{$alias}.username";
        if (ma_col_exists($pdo, 'users', 'email')) return "{$alias}.email";
        return "CONCAT('User #', {$alias}.id)";
    }
}

if (!function_exists('ensure_manager_approval_schema')) {
    function ensure_manager_approval_schema(PDO $pdo): void {
        if (!ma_table_exists($pdo, 'users')) {
            throw new RuntimeException('Users table does not exist. Manager approval cannot work.');
        }

        if (!ma_col_exists($pdo, 'users', 'approval_pin_hash')) {
            $pdo->exec("ALTER TABLE users ADD COLUMN approval_pin_hash VARCHAR(255) NULL AFTER password");
        }

        if (!ma_col_exists($pdo, 'users', 'approval_pin_set_at')) {
            $pdo->exec("ALTER TABLE users ADD COLUMN approval_pin_set_at DATETIME NULL AFTER approval_pin_hash");
        }

        $pdo->exec("
            CREATE TABLE IF NOT EXISTS manager_approval_log (
                id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
                permission_key VARCHAR(120) NULL,
                action_label VARCHAR(255) NULL,
                reference_type VARCHAR(80) NULL,
                reference_id BIGINT UNSIGNED NULL,
                manager_user_id INT UNSIGNED NULL,
                requested_by INT UNSIGNED NULL,
                ip_address VARCHAR(64) NULL,
                user_agent VARCHAR(255) NULL,
                created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
                INDEX idx_manager_approval_ref (reference_type, reference_id),
                INDEX idx_manager_approval_manager (manager_user_id),
                INDEX idx_manager_approval_created (created_at)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
        ");
    }
}

if (!function_exists('manager_role_where_sql')) {
    function manager_role_where_sql(PDO $pdo, string $alias = 'u'): string {
        /*
            Supports your current integer user_role setup:
              1 = Super Admin
              2 = Admin
              3 = Manager
              9 = Owner

            Also supports role_key if your users table ever has it.
        */
        $parts = [];

        if (ma_col_exists($pdo, 'users', 'user_role')) {
            $parts[] = "{$alias}.user_role IN (1,2,3,9)";
        }

        if (ma_col_exists($pdo, 'users', 'role_key')) {
            $parts[] = "{$alias}.role_key IN ('super_admin','admin','manager','owner')";
        }

        if (!$parts) {
            // Fallback: allow active users only if no role columns exist.
            $parts[] = "1=1";
        }

        return '(' . implode(' OR ', $parts) . ')';
    }
}

if (!function_exists('manager_active_where_sql')) {
    function manager_active_where_sql(PDO $pdo, string $alias = 'u'): string {
        if (ma_col_exists($pdo, 'users', 'active')) {
            return " AND {$alias}.active = 1 ";
        }
        if (ma_col_exists($pdo, 'users', 'is_active')) {
            return " AND {$alias}.is_active = 1 ";
        }
        return "";
    }
}

if (!function_exists('get_manager_approval_users')) {
    function get_manager_approval_users(PDO $pdo): array {
        ensure_manager_approval_schema($pdo);

        $nameExpr = ma_user_name_expr($pdo, 'u');
        $roleSql = manager_role_where_sql($pdo, 'u');
        $activeSql = manager_active_where_sql($pdo, 'u');

        $stmt = $pdo->query("
            SELECT
                u.id,
                {$nameExpr} AS display_name,
                " . (ma_col_exists($pdo, 'users', 'username') ? "u.username" : "NULL AS username") . ",
                " . (ma_col_exists($pdo, 'users', 'email') ? "u.email" : "NULL AS email") . ",
                " . (ma_col_exists($pdo, 'users', 'user_role') ? "u.user_role" : "NULL AS user_role") . ",
                CASE WHEN u.approval_pin_hash IS NULL OR u.approval_pin_hash = '' THEN 0 ELSE 1 END AS has_pin
            FROM users u
            WHERE {$roleSql}
              {$activeSql}
            ORDER BY display_name ASC, u.id ASC
        ");

        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
}

if (!function_exists('set_manager_approval_pin')) {
    function set_manager_approval_pin(PDO $pdo, int $userId, string $pin): void {
        ensure_manager_approval_schema($pdo);

        $pin = trim($pin);
        if (!preg_match('/^\d{4,8}$/', $pin)) {
            throw new RuntimeException('Approval PIN must be 4 to 8 digits.');
        }

        $stmt = $pdo->prepare("SELECT id FROM users WHERE id = :id LIMIT 1");
        $stmt->execute([':id' => $userId]);

        if (!$stmt->fetchColumn()) {
            throw new RuntimeException('Manager user was not found.');
        }

        $hash = password_hash($pin, PASSWORD_DEFAULT);

        $stmt = $pdo->prepare("
            UPDATE users
            SET approval_pin_hash = :hash,
                approval_pin_set_at = NOW()
            WHERE id = :id
        ");
        $stmt->execute([
            ':hash' => $hash,
            ':id' => $userId,
        ]);
    }
}

if (!function_exists('require_manager_approval')) {
    function require_manager_approval(
        PDO $pdo,
        string $permissionKey,
        string $actionLabel,
        string $referenceType,
        int $referenceId = 0
    ): array {
        ensure_manager_approval_schema($pdo);

        $managerApproved = (string)($_POST['manager_approved'] ?? '0');
        $managerUserId = (int)($_POST['manager_user_id'] ?? 0);
        $managerPin = trim((string)($_POST['manager_pin'] ?? ($_POST['manager_password'] ?? '')));

        if ($managerApproved !== '1') {
            throw new RuntimeException('Manager approval is required.');
        }

        if ($managerUserId <= 0) {
            throw new RuntimeException('Please select the approving manager.');
        }

        if ($managerPin === '') {
            throw new RuntimeException('Please enter the manager approval PIN.');
        }

        if (!preg_match('/^\d{4,8}$/', $managerPin)) {
            throw new RuntimeException('Invalid PIN format. PIN must be 4 to 8 digits.');
        }

        $nameExpr = ma_user_name_expr($pdo, 'u');
        $roleSql = manager_role_where_sql($pdo, 'u');
        $activeSql = manager_active_where_sql($pdo, 'u');

        $stmt = $pdo->prepare("
            SELECT
                u.*,
                {$nameExpr} AS display_name
            FROM users u
            WHERE u.id = :id
              AND {$roleSql}
              {$activeSql}
            LIMIT 1
        ");
        $stmt->execute([':id' => $managerUserId]);
        $manager = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$manager) {
            throw new RuntimeException('Selected user is not an active manager/admin approver.');
        }

        if (empty($manager['approval_pin_hash'])) {
            throw new RuntimeException('This manager does not have an approval PIN set.');
        }

        if (!password_verify($managerPin, (string)$manager['approval_pin_hash'])) {
            throw new RuntimeException('Invalid manager approval PIN.');
        }

        $stmt = $pdo->prepare("
            INSERT INTO manager_approval_log
            (permission_key, action_label, reference_type, reference_id, manager_user_id, requested_by, ip_address, user_agent)
            VALUES
            (:permission_key, :action_label, :reference_type, :reference_id, :manager_user_id, :requested_by, :ip_address, :user_agent)
        ");
        $stmt->execute([
            ':permission_key' => $permissionKey,
            ':action_label' => $actionLabel,
            ':reference_type' => $referenceType,
            ':reference_id' => $referenceId > 0 ? $referenceId : null,
            ':manager_user_id' => $managerUserId,
            ':requested_by' => $_SESSION['user_id'] ?? null,
            ':ip_address' => $_SERVER['REMOTE_ADDR'] ?? null,
            ':user_agent' => substr((string)($_SERVER['HTTP_USER_AGENT'] ?? ''), 0, 255),
        ]);

        return $manager;
    }
}

/*
|--------------------------------------------------------------------------
| Optional PIN update handler
|--------------------------------------------------------------------------
| Any page that includes this file can submit:
|   action=save_manager_pin
|   manager_user_id=...
|   approval_pin=...
|   approval_pin_confirm=...
|--------------------------------------------------------------------------
*/
if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST' && ($_POST['action'] ?? '') === 'save_manager_pin') {
    try {
        if (function_exists('verify_csrf')) verify_csrf();

        if (function_exists('require_permission')) {
            require_permission($pdo, 'role_permissions', 'edit');
        }

        $managerUserId = (int)($_POST['manager_user_id'] ?? 0);
        $pin = trim((string)($_POST['approval_pin'] ?? ''));
        $confirm = trim((string)($_POST['approval_pin_confirm'] ?? ''));

        if ($managerUserId <= 0) throw new RuntimeException('Please select a manager.');
        if ($pin !== $confirm) throw new RuntimeException('PIN confirmation does not match.');

        set_manager_approval_pin($pdo, $managerUserId, $pin);

        $_SESSION['manager_approval_flash'][] = ['type' => 'success', 'message' => 'Manager approval PIN saved successfully.'];
        header('Location: ' . strtok($_SERVER['REQUEST_URI'], '?'));
        exit;
    } catch (Throwable $e) {
        $_SESSION['manager_approval_flash'][] = ['type' => 'danger', 'message' => $e->getMessage()];
        header('Location: ' . strtok($_SERVER['REQUEST_URI'], '?'));
        exit;
    }
}

/*
|--------------------------------------------------------------------------
| Render modal only once
|--------------------------------------------------------------------------
*/
if (empty($GLOBALS['manager_approval_modal_rendered'])):
    $GLOBALS['manager_approval_modal_rendered'] = true;

    $managerApprovalUsers = [];
    $managerApprovalFlash = $_SESSION['manager_approval_flash'] ?? [];
    unset($_SESSION['manager_approval_flash']);

    try {
        if (isset($pdo) && $pdo instanceof PDO) {
            $managerApprovalUsers = get_manager_approval_users($pdo);
        }
    } catch (Throwable $e) {
        $managerApprovalFlash[] = ['type' => 'warning', 'message' => 'Manager approval setup warning: ' . $e->getMessage()];
    }
?>

<?php foreach ($managerApprovalFlash as $maf): ?>
    <div class="alert alert-<?php echo h($maf['type']); ?> no-print"><?php echo h($maf['message']); ?></div>
<?php endforeach; ?>

<div class="modal fade" id="managerApprovalPinModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered">
        <div class="modal-content manager-pin-modal">
            <div class="modal-header">
                <div>
                    <h5 class="modal-title mb-0"><i class="bi bi-shield-lock me-2"></i>Manager Approval</h5>
                    <div class="small text-muted" id="managerApprovalMessage">Enter manager PIN to approve this action.</div>
                </div>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                <input type="hidden" id="managerApprovalTargetForm" value="">

                <div class="mb-3">
                    <label class="form-label">Approving Manager</label>
                    <select id="managerApprovalUserId" class="form-select">
                        <option value="">Select manager</option>
                        <?php foreach ($managerApprovalUsers as $m): ?>
                            <option value="<?php echo (int)$m['id']; ?>" <?php echo (int)$m['has_pin'] === 1 ? '' : 'disabled'; ?>>
                                <?php echo h($m['display_name'] ?: ($m['username'] ?: ('User #' . $m['id']))); ?>
                                <?php echo !empty($m['username']) ? ' • @' . h($m['username']) : ''; ?>
                                <?php echo (int)$m['has_pin'] === 1 ? '' : ' • PIN NOT SET'; ?>
                            </option>
                        <?php endforeach; ?>
                    </select>
                    <div class="form-text">Only active Super Admin, Admin, Manager or Owner users with a PIN can approve.</div>
                </div>

                <div class="mb-2">
                    <label class="form-label">Approval PIN</label>
                    <input type="password" id="managerApprovalPin" class="form-control form-control-lg text-center" inputmode="numeric" pattern="[0-9]*" maxlength="8" placeholder="••••">
                    <div class="form-text">PIN must be 4 to 8 digits.</div>
                </div>

                <?php if (!$managerApprovalUsers): ?>
                    <div class="alert alert-warning mt-3 mb-0">
                        No manager/admin approvers were found. Create an active user with role Super Admin, Admin, Manager or Owner.
                    </div>
                <?php endif; ?>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
                <button type="button" class="btn btn-success" id="managerApprovalConfirmBtn">
                    <i class="bi bi-check2-circle me-2"></i>Approve
                </button>
            </div>
        </div>
    </div>
</div>

<style>
.manager-pin-modal{border:0;border-radius:22px;overflow:hidden;box-shadow:0 24px 80px rgba(15,23,42,.28)}
.manager-pin-modal .modal-header{background:#0f172a;color:#fff;border:0}
.manager-pin-modal .modal-header .text-muted{color:rgba(255,255,255,.68)!important}
.manager-pin-modal .modal-body{background:#f8fafc}
.manager-pin-modal .form-control,
.manager-pin-modal .form-select{border-radius:14px}
.manager-pin-modal #managerApprovalPin{letter-spacing:.35rem;font-weight:900}
</style>

<script>
document.addEventListener('DOMContentLoaded', function(){
    const modalEl = document.getElementById('managerApprovalPinModal');
    const targetInput = document.getElementById('managerApprovalTargetForm');
    const messageEl = document.getElementById('managerApprovalMessage');
    const managerSelect = document.getElementById('managerApprovalUserId');
    const pinInput = document.getElementById('managerApprovalPin');
    const confirmBtn = document.getElementById('managerApprovalConfirmBtn');

    if (!modalEl || !targetInput || !managerSelect || !pinInput || !confirmBtn) return;

    let bsModal = null;
    if (window.bootstrap && window.bootstrap.Modal) {
        bsModal = new bootstrap.Modal(modalEl);
    }

    document.querySelectorAll('.manager-approval-trigger').forEach(function(btn){
        btn.addEventListener('click', function(){
            const formSelector = btn.getAttribute('data-target-form') || '';
            const msg = btn.getAttribute('data-action-message') || 'Enter manager PIN to approve this action.';

            targetInput.value = formSelector;
            messageEl.textContent = msg;
            pinInput.value = '';

            if (bsModal) bsModal.show();
            else modalEl.style.display = 'block';

            setTimeout(function(){ managerSelect.focus(); }, 250);
        });
    });

    confirmBtn.addEventListener('click', function(){
        const formSelector = targetInput.value;
        const form = formSelector ? document.querySelector(formSelector) : null;

        if (!form) {
            alert('Approval form was not found.');
            return;
        }

        const managerId = managerSelect.value || '';
        const pin = pinInput.value || '';

        if (!managerId) {
            alert('Please select the approving manager.');
            managerSelect.focus();
            return;
        }

        if (!/^\d{4,8}$/.test(pin)) {
            alert('Please enter a valid 4 to 8 digit PIN.');
            pinInput.focus();
            return;
        }

        let approvedInput = form.querySelector('input[name="manager_approved"]');
        let managerInput = form.querySelector('input[name="manager_user_id"]');
        let pinHiddenInput = form.querySelector('input[name="manager_pin"]');

        if (!approvedInput) {
            approvedInput = document.createElement('input');
            approvedInput.type = 'hidden';
            approvedInput.name = 'manager_approved';
            form.appendChild(approvedInput);
        }

        if (!managerInput) {
            managerInput = document.createElement('input');
            managerInput.type = 'hidden';
            managerInput.name = 'manager_user_id';
            form.appendChild(managerInput);
        }

        if (!pinHiddenInput) {
            pinHiddenInput = document.createElement('input');
            pinHiddenInput.type = 'hidden';
            pinHiddenInput.name = 'manager_pin';
            form.appendChild(pinHiddenInput);
        }

        approvedInput.value = '1';
        managerInput.value = managerId;
        pinHiddenInput.value = pin;

        form.submit();
    });

    pinInput.addEventListener('keyup', function(e){
        if (e.key === 'Enter') {
            confirmBtn.click();
        }
    });
});
</script>

<?php endif; ?>
