<?php
/*
 * FamPay payment verification via Gmail (IMAP).
 * Use this in the checkout / status-polling file for FamPay orders,
 * the same way HDFC/Paytm status.php checks their own transaction history.
 *
 * How to use (example inside your payment status/verify file):
 *
 *   require_once 'fampay_mail_check.php';
 *   $found = fampay_check_payment($gmail, $app_password, $amount, $order_id, $utr_entered_by_user);
 *   if ($found['matched']) {
 *       // mark order SUCCESS, save $found['utr']
 *   }
 *
 * IMPORTANT: pass $conn so a single "money received" mail can never be
 * matched to more than one order (see the UTR-reuse guard below) - this
 * is what previously let one real UPI credit mark 2-3 different pending
 * orders (e.g. from a customer double/triple-tapping Pay) as SUCCESS at
 * once, since the old version only matched by amount/time and never
 * checked whether that same reference had already resolved another order.
 */

function fampay_check_payment($gmail, $app_password, $amount, $order_id, $utr_entered = null, $minutes_window = 30, $since_timestamp = null, $conn = null) {

    $result = [
        'matched' => false,
        'utr'     => null,
        'error'   => null,
    ];

    if (!function_exists('imap_open')) {
        $result['error'] = 'IMAP extension not enabled on server.';
        return $result;
    }

    $mailbox = '{imap.gmail.com:993/imap/ssl}INBOX';
    $stream  = @imap_open($mailbox, $gmail, $app_password);

    if ($stream === false) {
        $result['error'] = imap_last_error() ? imap_last_error() : 'Gmail login failed.';
        return $result;
    }

    // Only check recent mails to keep it fast.
    $cutoff = $since_timestamp !== null ? ($since_timestamp - 60) : strtotime("-{$minutes_window} minutes");
    $sinceDate = date('d-M-Y', $cutoff);
    $searchCriteria = 'FROM "famapp.in" SUBJECT "received" SINCE "' . $sinceDate . '"';
    $emailIds = imap_search($stream, $searchCriteria, SE_UID);

    if ($emailIds) {
        // Newest first
        rsort($emailIds);

        foreach ($emailIds as $uid) {

            $overview = imap_fetch_overview($stream, $uid, FT_UID);
            if (!empty($overview)) {
                $mailTime = strtotime($overview[0]->date);
                if ($mailTime < $cutoff) {
                    continue; // too old, not this transaction
                }
            }

            $body = imap_fetchbody($stream, $uid, 1.2, FT_UID);
            if (trim($body) === '') {
                $body = imap_fetchbody($stream, $uid, 1, FT_UID);
            }
            $body = quoted_printable_decode($body);
            $body = strip_tags($body);

            // Safety check: must actually be a "money received" mail, not some other
            // FamApp email. Different accounts/app versions/templates seem to word
            // this slightly differently, so check several known variants instead of
            // one exact phrase (which was likely why this worked for one account's
            // emails but silently never matched for others).
            $receivedPhrases = [
                'successfully received',
                'you have received',
                'you\'ve received',
                'payment received',
                'money received',
                'received a payment',
                'received payment',
            ];
            $looksLikeReceivedMail = false;
            foreach ($receivedPhrases as $phrase) {
                if (stripos($body, $phrase) !== false) {
                    $looksLikeReceivedMail = true;
                    break;
                }
            }
            if (!$looksLikeReceivedMail) {
                continue;
            }

            // Extract amount (₹123.00 / Rs 123 / INR 123)
            preg_match('/(?:₹|Rs\.?|INR)\s?([0-9]+(?:,[0-9]{2,3})*(?:\.[0-9]{1,2})?)/i', $body, $amtMatch);
            $mailAmount = isset($amtMatch[1]) ? (float) str_replace(',', '', $amtMatch[1]) : null;

            // Extract UTR / UPI Ref No (usually 9-22 char alphanumeric) -
            // widened to catch more wording variants since a genuine match
            // now depends entirely on finding a real reference number.
            preg_match('/(?:UTR|UPI\s?(?:Ref(?:erence)?|Txn(?:action)?)?\s?(?:No\.?|Number|ID)?|Txn(?:\s|:)?\s?(?:ID|No\.?|Ref)?|RRN|Reference\s?(?:No\.?|Number|ID)?)[:\s]*([A-Za-z0-9]{9,22})/i', $body, $utrMatch);
            $mailUtr = isset($utrMatch[1]) ? $utrMatch[1] : null;

            $amountOk = ($mailAmount !== null && abs($mailAmount - (float)$amount) < 0.01);
            $utrOk    = true;
            if (!empty($utr_entered) && $mailUtr) {
                $utrOk = (trim($utr_entered) === trim($mailUtr));
            }

            // Verification must be REAL: amount matching alone is not enough
            // proof that this specific email is this specific payment - a
            // genuine UTR/reference number extracted from the mail is
            // required too. No synthetic/placeholder reference is ever
            // generated here anymore, so an order can only be auto-marked
            // SUCCESS when we actually captured a real bank reference
            // number to back it - never on an amount coincidence alone.
            if ($amountOk && $utrOk && $mailUtr) {
                // Guard: has this exact reference already been used to mark
                // a *different* order SUCCESS? One bank credit must only
                // ever resolve one order - without this, several pending
                // orders sharing the same amount in the same time window
                // (e.g. a double-tapped Pay button) could all be matched to
                // the same single mail and all flip to SUCCESS.
                if ($conn) {
                    $chk = $conn->prepare("SELECT order_id FROM orders WHERE utr = ? AND status = 'SUCCESS' AND order_id != ? LIMIT 1");
                    $chk->bind_param("ss", $mailUtr, $order_id);
                    $chk->execute();
                    $already = $chk->get_result()->fetch_assoc();
                    $chk->close();
                    if ($already) {
                        continue; // this mail already resolved a different order - keep scanning
                    }
                }

                $result['matched'] = true;
                $result['utr']     = $mailUtr;
                break;
            }
        }
    }

    imap_close($stream);
    return $result;
}
