<?php
/**
 * ===========================================================
 * PaymentGatewayClient.php
 * ===========================================================
 * এই ফাইলটা তোমার EXISTING website-এর কোডে বসাবে (এটা payment-saas-php
 * প্রজেক্টের অংশ না, এটা তোমার অন্য website-এর জন্য)।
 *
 * ব্যবহার:
 *   require 'PaymentGatewayClient.php';
 *   $client = new PaymentGatewayClient(
 *       'https://getaway.winbigplay6.site/api',
 *       'pk_xxxxxxxxxxxxxxxx',   // Merchant Panel থেকে পাওয়া key_id
 *       'তোমার_secret_এখানে'      // Merchant Panel থেকে পাওয়া secret
 *   );
 *
 *   $result = $client->checkByTrxId('8N7A6B5C4D', 500.00);
 *   if ($result['found']) {
 *       // $result['transaction']['id'] দিয়ে claimPayment() call করো,
 *       // তারপরই order confirm করো (নিচে পুরো example আছে)
 *   }
 */

class PaymentGatewayClient
{
    private $baseUrl;
    private $apiKeyId;
    private $apiSecret;

    public function __construct($baseUrl, $apiKeyId, $apiSecret)
    {
        $this->baseUrl = rtrim($baseUrl, '/');
        $this->apiKeyId = $apiKeyId;
        $this->apiSecret = $apiSecret;
    }

    /**
     * Admin Panel-এ সেট করা live wallet number আনে — deposit page-এ
     * hardcoded নম্বরের বদলে এটা ব্যবহার করলে Admin Panel থেকে নম্বর
     * বদলালেই সব website-এ আপনাআপনি আপডেট হয়ে যাবে।
     *
     * রিটার্ন করে: ['found' => bool, 'wallet_number' => string|null]
     */
    public function getWalletNumber($provider)
    {
        $path = '/merchant/get_wallet.php?' . http_build_query(['provider' => $provider]);
        return $this->signedGet($path);
    }

    /**
     * ✅ এইটাই সবচেয়ে নির্ভরযোগ্য পদ্ধতি — কাস্টমার নিজের bKash SMS থেকে
     * TrxID আর amount দেয় (তোমার website-এর deposit form-এ), সেটা দিয়ে
     * match করে। TrxID সবসময় unique, তাই ambiguity নেই।
     *
     * রিটার্ন করে: ['found' => bool, 'transaction' => array|null, 'reason' => string|null]
     */
    public function checkByTrxId($trxId, $amount = null)
    {
        $params = ['trxid' => $trxId];
        if ($amount !== null) {
            $params['amount'] = $amount;
        }
        $path = '/merchant/check_by_trxid.php?' . http_build_query($params);
        return $this->signedGet($path);
    }

    /**
     * amount, senderNumber = কাস্টমার যে bKash নম্বর থেকে টাকা পাঠিয়েছে
     * বলছে, সেটা দিয়ে match করে। withinMinutes = কতক্ষণ আগে পর্যন্ত
     * transaction খুঁজবে (ডিফল্ট ৬০ মিনিট)।
     *
     * রিটার্ন করে: ['found' => bool, 'matches' => array]
     */
    public function checkPayment($amount, $senderNumber, $withinMinutes = 60)
    {
        $query = http_build_query([
            'amount' => $amount,
            'sender_number' => $senderNumber,
            'within_minutes' => $withinMinutes,
        ]);

        $path = '/merchant/check_payment.php?' . $query;
        return $this->signedGet($path);
    }

    /**
     * transactionId = checkPayment() থেকে পাওয়া transaction id
     * claimedBy = তোমার নিজের লেবেল, যেমন "website1" বা order id —
     *             শুধু তোমার নিজের বোঝার জন্য, সিস্টেম এটা দিয়ে কিছু করে না
     *
     * এই call atomic — একই bKash নম্বর শেয়ার করা একাধিক website একই সময়ে
     * একই transaction claim করতে চাইলে, শুধু PRATHOM caller সফল হবে।
     * claimed=false পেলে অবশ্যই order confirm কোরো না — এটা অন্য কেউ
     * (তোমার অন্য কোনো website) আগেই claim করে ফেলেছে।
     */
    public function claimPayment($transactionId, $claimedBy)
    {
        $timestamp = time();
        $nonce = bin2hex(random_bytes(16));
        $bodyArr = ['transaction_id' => $transactionId, 'claimed_by' => $claimedBy];
        $rawBody = json_encode($bodyArr);
        $payload = $timestamp . '.' . $nonce . '.' . $rawBody;
        $signature = hash_hmac('sha256', $payload, $this->apiSecret);

        $ch = curl_init($this->baseUrl . '/merchant/claim_transaction.php');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $rawBody);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'X-Api-Key: ' . $this->apiKeyId,
            'X-Timestamp: ' . $timestamp,
            'X-Nonce: ' . $nonce,
            'X-Signature: ' . $signature,
        ]);
        curl_setopt($ch, CURLOPT_TIMEOUT, 15);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

        $response = curl_exec($ch);
        curl_close($ch);

        $decoded = json_decode($response, true);
        return is_array($decoded) ? $decoded : ['claimed' => false, 'reason' => 'invalid_response'];
    }

    private function signedGet($path)
    {
        $timestamp = time();
        $nonce = bin2hex(random_bytes(16));
        $rawBody = ''; // GET request, no body
        $payload = $timestamp . '.' . $nonce . '.' . $rawBody;
        $signature = hash_hmac('sha256', $payload, $this->apiSecret);

        $ch = curl_init($this->baseUrl . $path);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'X-Api-Key: ' . $this->apiKeyId,
            'X-Timestamp: ' . $timestamp,
            'X-Nonce: ' . $nonce,
            'X-Signature: ' . $signature,
        ]);
        curl_setopt($ch, CURLOPT_TIMEOUT, 15);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curlError = curl_error($ch);
        curl_close($ch);

        if ($response === false) {
            return ['found' => false, 'error' => 'network_error', 'message' => $curlError];
        }

        $decoded = json_decode($response, true);
        if (!is_array($decoded)) {
            return ['found' => false, 'error' => 'invalid_response', 'raw' => $response];
        }

        if ($httpCode !== 200) {
            return ['found' => false, 'error' => $decoded['error'] ?? 'unknown_error', 'message' => $decoded['message'] ?? ''];
        }

        return $decoded;
    }
}

// ===========================================================
// ✅ সবচেয়ে নির্ভরযোগ্য পদ্ধতি — কাস্টমার নিজের TrxID + amount দেয়:
// ===========================================================
//
// require 'PaymentGatewayClient.php';
//
// $client = new PaymentGatewayClient(
//     'https://getaway.winbigplay6.site/api',
//     'pk_xxxxxxxxxxxxxxxx',
//     'তোমার_secret'
// );
//
// // ফর্ম থেকে কাস্টমার যা দিয়েছে:
// $trxId = $_POST['trxid'];       // যেমন "8N7A6B5C4D"
// $amount = $_POST['amount'];     // যেমন 500.00
//
// $result = $client->checkByTrxId($trxId, $amount);
//
// if ($result['found']) {
//     $txn = $result['transaction'];
//
//     // Website 1/2/3 একই bKash নম্বর শেয়ার করলে claim করে নাও:
//     $claimResult = $client->claimPayment($txn['id'], 'website1_order_123');
//
//     if ($claimResult['claimed']) {
//         // ✅ নিশ্চিন্তে order confirm করো, deposit যোগ করো
//     } else {
//         // অন্য কোনো order এটা আগেই claim করে ফেলেছে (রেয়ার কেস, একই
//         // মুহূর্তে দুইজন একই TrxID দিলে হতে পারে — কিন্তু TrxID যেহেতু
//         // কাস্টমার নিজে দেখে টাইপ করে, এটা প্র্যাকটিক্যালি প্রায় হবে না)
//     }
// } else {
//     // $result['reason'] দেখো: 'trxid_not_found' (এখনো SMS আসেনি বা ভুল
//     // TrxID), 'amount_mismatch' (amount মেলেনি), 'already_claimed'
//     if ($result['reason'] === 'trxid_not_found') {
//         // কিছুক্ষণ পর আবার চেক করার সুযোগ দাও (SMS আসতে কয়েক সেকেন্ড লাগে)
//     }
// }
