<?php
/**
 * lipalink.php — LipaLink/PesaFlux API helper
 * ─────────────────────────────────────────────
 * Include this file wherever STK push or status check is needed.
 *
 * API reference:
 *   POST http://lipalink.co.ke/api/stk_push.php
 *   GET  http://lipalink.co.ke/api/transaction_status.php?transaction_id=PFX…
 *   POST http://lipalink.co.ke/api/callback.php  ← Safaricom fires this (auto)
 *
 * STK push body:
 *   { "amount": 100, "msisdn": "254712345678",
 *     "reference": "ORDER-001", "business_id": 6 }
 *
 * STK push success response:
 *   { "success": true, "transaction_id": "PFX...", "message": "STK push sent" }
 *
 * STK push error response:
 *   { "success": false, "error": "Reason for failure" }
 *
 * Status check success response:
 *   { "success": true, "transaction_id": "PFX...", "status": "Success",
 *     "mpesa_receipt": "QHY67XXXXX", "amount": 100.00,
 *     "msisdn": "...", "reference": "...",
 *     "result_desc": "The service request is processed successfully.",
 *     "transaction_date": "2024-01-01 12:00:00" }
 *
 * Webhook payload (PesaFlux POSTs to your callback URL):
 *   { "event": "payment.success", "transaction_id": "PFX...",
 *     "mpesa_receipt": "QHY67XXXXX", "msisdn": "254...",
 *     "amount": 100.00, "reference": "ORDER-001",
 *     "business_id": 6, "status": "Success",
 *     "transaction_date": "2024-01-01 12:00:00" }
 *   → Respond HTTP 200. PesaFlux does NOT retry.
 */

if (!defined('LIPALINK_BASE')) {
    define('LIPALINK_BASE', 'http://lipalink.co.ke/api');
}

// ════════════════════════════════════════════════════════════════════
// lipalink_stk_push()
// Send an STK push prompt to a user's phone.
//
// @param string $phone       Phone in 254XXXXXXXXX format
// @param int    $amount      Amount in KES (integer)
// @param string $reference   Your internal order/reference string
// @param string $apiKey      X-Api-Key header value
// @param int    $businessId  Your LipaLink business ID (integer)
//
// @return array {
//   success: bool,
//   transaction_id: string,   // PFX... — store as checkout_request_id
//   message: string,
//   error: string             // only on failure
// }
// ════════════════════════════════════════════════════════════════════
function lipalink_stk_push($phone, $amount, $reference, $apiKey, $businessId) {
    if (empty($apiKey)) {
        return ['success' => false, 'error' => 'API key not configured.'];
    }
    if (intval($businessId) < 1) {
        return ['success' => false, 'error' => 'Business ID not configured.'];
    }

    $payload = json_encode([
        'amount'      => intval($amount),        // must be integer per API spec
        'msisdn'      => (string)$phone,         // 254712345678
        'reference'   => (string)$reference,
        'business_id' => intval($businessId),    // must be integer per API spec
    ]);

    $ch = curl_init(LIPALINK_BASE . '/stk_push.php');
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => $payload,
        CURLOPT_HTTPHEADER     => [
            'Content-Type: application/json',
            'X-Api-Key: ' . $apiKey,
        ],
        CURLOPT_TIMEOUT        => 30,
        CURLOPT_SSL_VERIFYPEER => false,
    ]);
    $resp    = curl_exec($ch);
    $curlErr = curl_error($ch);
    curl_close($ch);

    if ($curlErr) {
        return ['success' => false, 'error' => 'Connection error: ' . $curlErr];
    }

    $d = json_decode($resp, true);
    if (!is_array($d)) {
        return ['success' => false, 'error' => 'Invalid gateway response.'];
    }

    // Success: { "success": true, "transaction_id": "PFX...", "message": "..." }
    if (!empty($d['success']) && !empty($d['transaction_id'])) {
        return [
            'success'        => true,
            'transaction_id' => $d['transaction_id'],
            'message'        => $d['message'] ?? 'STK push sent. Enter your M-PESA PIN.',
        ];
    }

    // Error: { "success": false, "error": "..." }
    return [
        'success' => false,
        'error'   => $d['error'] ?? $d['message'] ?? 'STK push failed.',
    ];
}

// ════════════════════════════════════════════════════════════════════
// lipalink_check_status()
// Poll the LipaLink transaction status API.
//
// @param string $transactionId  The PFX... transaction_id returned by stk_push
// @param string $apiKey         X-Api-Key header value
//
// @return array {
//   success: bool,
//   status: string,            // "Success" | "Failed" | "Pending" | "Cancelled"
//   mpesa_receipt: string,
//   amount: float,
//   msisdn: string,
//   reference: string,
//   result_desc: string,
//   transaction_date: string,
//   error: string              // only on failure
// }
// ════════════════════════════════════════════════════════════════════
function lipalink_check_status($transactionId, $apiKey) {
    if (empty($transactionId) || empty($apiKey)) {
        return ['success' => false, 'status' => 'unknown', 'error' => 'Missing params'];
    }

    $url = LIPALINK_BASE . '/transaction_status.php?transaction_id=' . urlencode($transactionId);
    $ch  = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER     => ['X-Api-Key: ' . $apiKey],
        CURLOPT_TIMEOUT        => 10,
        CURLOPT_SSL_VERIFYPEER => false,
    ]);
    $resp    = curl_exec($ch);
    $curlErr = curl_error($ch);
    curl_close($ch);

    if ($curlErr || !$resp) {
        return ['success' => false, 'status' => 'unknown', 'error' => 'Connection error'];
    }

    $d = json_decode($resp, true);
    if (!is_array($d)) {
        return ['success' => false, 'status' => 'unknown', 'error' => 'Invalid response'];
    }
    return $d;
}

// ════════════════════════════════════════════════════════════════════
// lipalink_parse_webhook()
// Parse and validate the webhook payload PesaFlux POSTs to callback.
//
// @param string $rawInput  file_get_contents('php://input')
//
// @return array {
//   valid:           bool,
//   is_success:      bool,
//   is_failure:      bool,
//   event:           string,
//   transaction_id:  string,   // PFX...
//   mpesa_receipt:   string,
//   amount:          float,
//   msisdn:          string,
//   reference:       string,   // the reference you sent in stk_push
//   status:          string,
//   business_id:     int,
//   transaction_date:string,
// }
// ════════════════════════════════════════════════════════════════════
function lipalink_parse_webhook($rawInput) {
    $data = json_decode($rawInput, true);
    if (!is_array($data)) {
        return ['valid' => false];
    }

    $event  = $data['event']  ?? '';
    $status = strtolower($data['status'] ?? '');

    // PesaFlux success: event=payment.success AND status=Success
    $isSuccess = ($event === 'payment.success' && $status === 'success');
    // PesaFlux failure: any other terminal event
    $isFailure = (!$isSuccess && in_array($event, [
        'payment.failed', 'payment.cancelled', 'payment.timeout'
    ]));

    return [
        'valid'            => true,
        'is_success'       => $isSuccess,
        'is_failure'       => $isFailure,
        'event'            => $event,
        'transaction_id'   => trim($data['transaction_id']  ?? ''),  // PFX...
        'mpesa_receipt'    => $data['mpesa_receipt']   ?? null,
        'amount'           => floatval($data['amount'] ?? 0),
        'msisdn'           => $data['msisdn']          ?? '',
        'reference'        => trim($data['reference']  ?? ''),  // our ref
        'status'           => $data['status']          ?? '',
        'business_id'      => intval($data['business_id'] ?? 0),
        'transaction_date' => $data['transaction_date'] ?? '',
    ];
}

// ════════════════════════════════════════════════════════════════════
// lipalink_format_phone()
// Normalise any Kenyan phone number to 254XXXXXXXXX format.
// ════════════════════════════════════════════════════════════════════
function lipalink_format_phone($phone) {
    $phone = preg_replace('/\D/', '', $phone);
    if (strlen($phone) === 10 && $phone[0] === '0') {
        $phone = '254' . substr($phone, 1);
    } elseif (strlen($phone) === 9) {
        $phone = '254' . $phone;
    }
    return $phone;
}

// ════════════════════════════════════════════════════════════════════
// lipalink_valid_phone()
// Returns true if phone is a valid Kenyan 254XXXXXXXXX number.
// ════════════════════════════════════════════════════════════════════
function lipalink_valid_phone($phone) {
    return (bool) preg_match('/^254[17]\d{8}$/', $phone);
}