<?php
/**
 * approval_notifications.php
 * -------------------------------------------------------------------
 * Shared helper for notifying a payroll approval stage's approver(s) by
 * email. Used in two places:
 *   - cycles.php, when a cycle is first sent for approval, or manually
 *     re-sent via "Resend Reminder".
 *   - cycle_approve.php, automatically, the moment a stage is approved
 *     and the trail advances to the next stage -- so the next approver
 *     doesn't have to be manually chased down every time.
 * Kept in one place so those two call sites can't drift out of sync.
 * -------------------------------------------------------------------
 */

function buildApprovalUrl(string $relativePath): string
{
    $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
    $host = $_SERVER['HTTP_HOST'] ?? 'localhost';
    $dir = rtrim(str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'])), '/');
    return "$scheme://$host$dir/$relativePath";
}

/**
 * Resolves who should be notified for a given approval stage: everyone
 * matching the stage's role (the same model cycle_approve.php already uses
 * to decide who's ALLOWED to act on a role-based stage), or the one
 * specific user for a user-based stage.
 *
 * @return array<array{username:string, email:?string}>
 */
function resolveStageApprovers(mysqli $conn, array $stage): array
{
    $approvers = [];
    if ($stage['approver_type'] === 'role') {
        $roleStmt = $conn->prepare("SELECT username, email FROM users WHERE role = ?");
        $roleStmt->bind_param('s', $stage['approver_role']);
        $roleStmt->execute();
        $roleRes = $roleStmt->get_result();
        while ($u = $roleRes->fetch_assoc()) { $approvers[] = $u; }
        $roleStmt->close();
    } else {
        $userStmt = $conn->prepare("SELECT username, email FROM users WHERE id = ?");
        $userStmt->bind_param('i', $stage['approver_user_id']);
        $userStmt->execute();
        $u = $userStmt->get_result()->fetch_assoc();
        if ($u) { $approvers[] = $u; }
        $userStmt->close();
    }
    return $approvers;
}

/**
 * Resolves and emails a stage's approver(s) a secure link to
 * cycle_approve.php. Never throws -- a mail failure (e.g. PHPMailer not
 * installed) is reported back in the result rather than breaking whatever
 * state change the caller already made (an approval that already happened
 * shouldn't get rolled back just because the follow-up email failed to
 * send).
 *
 * @return array{sentCount:int, skippedNoEmail:int, approverCount:int, error:?string}
 */
function notifyStageApprovers(mysqli $conn, array $cycle, array $stage): array
{
    $approvers = resolveStageApprovers($conn, $stage);
    $approvalUrl = buildApprovalUrl('cycle_approve.php?cycle_id=' . (int) $cycle['id']);
    $sentCount = 0;
    $skippedNoEmail = 0;

    try {
        require_once __DIR__ . '/Mailer.php';
        $mailer = new Mailer($conn);
        $body = Mailer::approvalRequestEmailTemplate($cycle, $approvalUrl, $stage['stage_name']);
        foreach ($approvers as $approver) {
            if (empty($approver['email'])) { $skippedNoEmail++; continue; }
            $sendResult = $mailer->send($approver['email'], $approver['username'], 'Payroll Approval Requested: ' . $cycle['name'], $body);
            if ($sendResult['success']) { $sentCount++; }
        }
    } catch (Exception $e) {
        return ['sentCount' => $sentCount, 'skippedNoEmail' => $skippedNoEmail, 'approverCount' => count($approvers), 'error' => $e->getMessage()];
    }

    return ['sentCount' => $sentCount, 'skippedNoEmail' => $skippedNoEmail, 'approverCount' => count($approvers), 'error' => null];
}
