<?php
/****************************************************
 * includes/sms_notify.php
 * Reusable SMS helpers for voucher workflow.
 ****************************************************/

if (!defined('SMS_DEFAULT_GATEWAY')) {
    define('SMS_DEFAULT_GATEWAY', 'zamtel');    // zamtel|airtel|mtn
    define('SMS_SENDER_ID',       'KTCOUNCIL'); // up to ~11 chars
    define('ZAMTEL_API_KEY',      'ZTXd2G2ixsvLyAveXNnYghLle8EUOYQa');
    define('AIRTEL_API_KEY',      'REPLACE_ME');
    define('MTN_API_KEY',         'REPLACE_ME');
}

/* ---------- Tiny utils ---------- */

/** Zambia format helper -> returns 2609XXXXXXXX or null */
function sms_sanitize_msisdn(?string $raw): ?string {
    if (!$raw) return null;
    $digits = preg_replace('/\D+/', '', $raw);
    if ($digits === '') return null;

    // 09xxxxxxxxx -> 2609xxxxxxxxx
    if (preg_match('/^0(9\d{8})$/', $digits, $m)) {
        return '260' . $m[1];
    }
    // 9xxxxxxxxx -> 2609xxxxxxxxx
    if (preg_match('/^(9\d{8})$/', $digits, $m)) {
        return '260' . $m[1];
    }
    // already 2609xxxxxxxxx
    if (preg_match('/^2609\d{8}$/', $digits)) {
        return $digits;
    }

    // Fallback: return as-is (you can tighten if needed)
    return $digits;
}

/** Truncate to a safe SMS length */
function sms_truncate(string $msg, int $limit = 300): string {
    $msg = trim($msg);
    if (mb_strlen($msg, 'UTF-8') > $limit) {
        return mb_substr($msg, 0, $limit - 1, 'UTF-8') . '…';
    }
    return $msg;
}

/** Simple HTTP GET (Zamtel uses a path style) */
function http_simple_get(string $url): array {
    $opts = [
        'http' => [
            'method'  => 'GET',
            'timeout' => 10,
            'header'  => "Accept: application/json\r\n"
        ]
    ];
    $ctx  = stream_context_create($opts);
    $body = @file_get_contents($url, false, $ctx);
    $ok   = $body !== false;
    return ['ok'=>$ok, 'body'=>$ok ? $body : null];
}

/* ---------- Low-level sender ---------- */

function send_sms(string $to, string $message, string $gateway = SMS_DEFAULT_GATEWAY): bool
{
    $msisdn  = sms_sanitize_msisdn($to);
    $message = sms_truncate($message);
    if (!$msisdn || $message === '') return false;

    switch (strtolower($gateway)) {
        case 'zamtel':
            $url = sprintf(
                'https://bulksms.zamtel.co.zm/api/v2.1/action/send/api_key/%s/contacts/%s/senderId/%s/message/%s',
                rawurlencode(ZAMTEL_API_KEY),
                rawurlencode($msisdn),
                rawurlencode(SMS_SENDER_ID),
                rawurlencode($message)
            );
            $res = http_simple_get($url);
            return $res['ok'];

        case 'airtel':
            // TODO: implement real endpoint
            return false;

        case 'mtn':
            // TODO: implement real endpoint
            return false;

        default:
            return false;
    }
}

/* ---------- DB helpers (voucher + user) ---------- */

function sms_get_user(mysqli $conn, int $userId): ?array {
    $st = $conn->prepare("SELECT id, full_name, phone_number FROM users WHERE id=? LIMIT 1");
    $st->bind_param('i', $userId);
    $st->execute();
    $u = $st->get_result()->fetch_assoc();
    $st->close();
    if (!$u) return null;
    return [
        'id'    => (int)$u['id'],
        'name'  => $u['full_name'] ?: 'User',
        'phone' => $u['phone_number'] ?? null,
    ];
}

/** Returns array: voucher core info + computed amount (max of debit/credit) */
function sms_get_voucher_core(mysqli $conn, int $voucherId): ?array {
    $st = $conn->prepare("
        SELECT id, voucher_no, payee, voucher_date, bank_account_name, bank_account_no,
               COALESCE(total_debit,0)  AS td,
               COALESCE(total_credit,0) AS tc,
               status,
               prepared_by_user_id, checked_by_user_id, authorized_by_user_id, approved_by_user_id
          FROM vouchers WHERE id=? LIMIT 1
    ");
    $st->bind_param('i', $voucherId);
    $st->execute();
    $v = $st->get_result()->fetch_assoc();
    $st->close();
    if (!$v) return null;

    $amt = max((float)$v['td'], (float)$v['tc']);
    return [
        'id'      => (int)$v['id'],
        'no'      => (string)$v['voucher_no'], // <-- voucher number
        'payee'   => (string)$v['payee'],
        'date'    => (string)$v['voucher_date'],
        'bank'    => (string)$v['bank_account_name'],
        'bank_no' => (string)$v['bank_account_no'],
        'amount'  => $amt,
        'status'  => (string)$v['status'],
        'prepared_by_user_id'   => (int)$v['prepared_by_user_id'],
        'checked_by_user_id'    => (int)$v['checked_by_user_id'],
        'authorized_by_user_id' => (int)$v['authorized_by_user_id'],
        'approved_by_user_id'   => (int)$v['approved_by_user_id'],
    ];
}

function sms_money(float $n): string {
    return 'K ' . number_format($n, 2);
}

/* ---------- High-level notifications ---------- */

/** Notify an assignee they need to CHECK the voucher. */
function notify_assign_check(mysqli $conn, int $voucherId, int $assigneeUserId, string $gateway = SMS_DEFAULT_GATEWAY): bool {
    $v = sms_get_voucher_core($conn, $voucherId);
    $u = sms_get_user($conn, $assigneeUserId);
    if (!$v || !$u || !$u['phone']) return false;

    // Use voucher number in reference, not id
    $msg = "Voucher {$v['no']} for {$v['payee']} (".sms_money($v['amount']).") is awaiting your CHECK. Ref: {$v['no']}.";
    return send_sms($u['phone'], $msg, $gateway);
}

/** Notify an assignee they need to AUTHORIZE the voucher. */
function notify_assign_authorize(mysqli $conn, int $voucherId, int $assigneeUserId, string $gateway = SMS_DEFAULT_GATEWAY): bool {
    $v = sms_get_voucher_core($conn, $voucherId);
    $u = sms_get_user($conn, $assigneeUserId);
    if (!$v || !$u || !$u['phone']) return false;

    $msg = "Voucher {$v['no']} ({$v['payee']}, ".sms_money($v['amount']).") requires your AUTHORIZATION. Ref: {$v['no']}.";
    return send_sms($u['phone'], $msg, $gateway);
}

/** Notify an assignee they need to APPROVE the voucher. */
function notify_assign_approve(mysqli $conn, int $voucherId, int $assigneeUserId, string $gateway = SMS_DEFAULT_GATEWAY): bool {
    $v = sms_get_voucher_core($conn, $voucherId);
    $u = sms_get_user($conn, $assigneeUserId);
    if (!$v || !$u || !$u['phone']) return false;

    $msg = "Voucher {$v['no']} ({$v['payee']}, ".sms_money($v['amount']).") requires your APPROVAL. Ref: {$v['no']}.";
    return send_sms($u['phone'], $msg, $gateway);
}

/**
 * Notify the PREPARED_BY user that a voucher has been Approved / Not Approved.
 * $status should be your label (e.g., 'Approved' or 'Not Approved').
 * $reason optional short note for rejections.
 */
function notify_prepared_status(mysqli $conn, int $voucherId, string $status, ?string $reason = null, string $gateway = SMS_DEFAULT_GATEWAY): bool {
    $v = sms_get_voucher_core($conn, $voucherId);
    if (!$v) return false;

    $prepId = (int)$v['prepared_by_user_id'];
    $u = $prepId ? sms_get_user($conn, $prepId) : null;
    if (!$u || !$u['phone']) return false;

    $note = ($reason && trim($reason) !== '') ? " Reason: ".trim($reason) : '';
    $msg  = "Voucher {$v['no']} ({$v['payee']}, ".sms_money($v['amount']).") status: {$status}.{$note} Ref: {$v['no']}.";
    return send_sms($u['phone'], sms_truncate($msg), $gateway);
}

/* ---------- Convenience: choose next notifier by role label ---------- */
/** $roleKey: 'CHECKED_BY'|'AUTHORISED_BY'|'APPROVED_BY' */
function notify_next_by_role(mysqli $conn, int $voucherId, string $roleKey, int $assigneeUserId, string $gateway = SMS_DEFAULT_GATEWAY): bool {
    switch ($roleKey) {
        case 'CHECKED_BY':     return notify_assign_check($conn, $voucherId, $assigneeUserId, $gateway);
        case 'AUTHORISED_BY':  return notify_assign_authorize($conn, $voucherId, $assigneeUserId, $gateway);
        case 'APPROVED_BY':    return notify_assign_approve($conn, $voucherId, $assigneeUserId, $gateway);
        default: return false;
    }
}
