<?php
/* ============================================================================
 *  config/notify.php — send a Web Push (+ store an in-app notification) to a
 *  user, and resolve who should approve a staff request.
 * ==========================================================================*/
require_once __DIR__ . '/webpush.php';

/**
 * Push + record a notification for one user. Safe to call anywhere; never throws.
 */
function notify_user(PDO $pdo, int $userId, string $title, string $body = '', string $url = ''): void {
    if ($userId <= 0) return;
    try {
        /* in-app record */
        $pdo->prepare("INSERT INTO notifications (user_id,title,body,url,created_at) VALUES (?,?,?,?,NOW())")
            ->execute([$userId, mb_substr($title,0,180), mb_substr($body,0,255), mb_substr($url,0,255)]);
    } catch (Throwable $e) { /* table may not exist yet */ }

    try {
        $st = $pdo->prepare("SELECT id,endpoint,p256dh,auth FROM push_subscriptions WHERE user_id=?");
        $st->execute([$userId]);
        $subs = $st->fetchAll(PDO::FETCH_ASSOC);
    } catch (Throwable $e) { return; }

    /* app-icon badge = this user's unread notifications */
    $badge = 0;
    try { $bc=$pdo->prepare("SELECT COUNT(*) FROM notifications WHERE user_id=? AND is_read=0"); $bc->execute([$userId]); $badge=(int)$bc->fetchColumn(); } catch (Throwable $e) {}

    $payload = json_encode(['title'=>$title, 'body'=>$body, 'url'=>$url, 'badge'=>$badge], JSON_UNESCAPED_UNICODE);
    foreach ($subs as $s) {
        try {
            $r = webpush_send($s, $payload);
            if (!empty($r['gone'])) {
                $pdo->prepare("DELETE FROM push_subscriptions WHERE id=?")->execute([$s['id']]);
            }
        } catch (Throwable $e) { /* ignore one bad endpoint */ }
    }
}

/**
 * Notify a wallet owner (customer/staff) that money landed in their wallet.
 * Resolves the customers row -> users.id, then pushes.
 */
function notify_money_received(PDO $pdo, int $customerId, float $amount, string $from = ''): void {
    try {
        $st = $pdo->prepare("SELECT user_id FROM customers WHERE id=? LIMIT 1");
        $st->execute([$customerId]);
        $uid = (int)$st->fetchColumn();
        if (!$uid) return;
        $body = "₭ " . number_format($amount, 0) . ($from !== '' ? " from " . $from : "") . " added to your wallet.";
        notify_user($pdo, $uid, "💰 Money received", $body, "customer/dashboard.php");
    } catch (Throwable $e) {}
}

/**
 * Who approves a request from $staffUserId right now (stage 1 = their department
 * manager; if none, the Operation Manager). Returns a de-duplicated list of
 * user ids to notify when a new request is submitted.
 */
function approvers_for_staff(PDO $pdo, int $companyId, int $staffUserId): array {
    $ids = [];

    /* department manager of the staff's department */
    try {
        $st = $pdo->prepare("
            SELECT d.manager_user_id
            FROM company_staff cs
            JOIN company_departments d ON d.company_id = cs.company_id AND d.name = cs.department
            WHERE cs.user_id = ? AND cs.company_id = ? LIMIT 1");
        $st->execute([$staffUserId, $companyId]);
        $deptMgr = (int)$st->fetchColumn();
        if ($deptMgr) $ids[] = $deptMgr;
    } catch (Throwable $e) {}

    /* operation manager (final approver) */
    $opsMgr = 0;
    try {
        $st = $pdo->prepare("SELECT final_manager_id FROM company_approval_settings WHERE company_id=? LIMIT 1");
        $st->execute([$companyId]);
        $opsMgr = (int)$st->fetchColumn();
    } catch (Throwable $e) {}

    /* If no department manager is set, the request goes straight to the Ops Manager. */
    if (!$ids && $opsMgr) $ids[] = $opsMgr;

    /* also alert any active stand-in (delegate) of the dept manager / ops manager */
    $addDelegate = function($mgr) use ($pdo,$companyId,&$ids){
        if ($mgr <= 0) return;
        try {
            $st = $pdo->prepare("SELECT to_user_id FROM approval_delegates WHERE company_id=? AND from_user_id=? AND (until_date IS NULL OR until_date>=CURDATE()) LIMIT 1");
            $st->execute([$companyId,$mgr]);
            $d = (int)$st->fetchColumn(); if ($d) $ids[] = $d;
        } catch (Throwable $e) {}
    };
    $addDelegate($deptMgr ?? 0);
    $addDelegate($opsMgr);

    /* Fallback: if nothing configured at all, notify all company admins. */
    if (!$ids) {
        try {
            $st = $pdo->prepare("
                SELECT u.id FROM company_staff cs JOIN users u ON u.id=cs.user_id
                WHERE cs.company_id=? AND cs.staff_role='admin' AND u.status='active'");
            $st->execute([$companyId]);
            foreach ($st->fetchAll(PDO::FETCH_COLUMN) as $id) $ids[] = (int)$id;
        } catch (Throwable $e) {}
    }

    return array_values(array_unique(array_filter($ids)));
}