<?php
/*
 * stripe_event_charge_c.php — Charge event handler
 *
 * Handled event types ($event_json->type):
 *   charge.succeeded
 *
 * charge.failed is intentionally unhandled — see the comment at the dispatch below.
 */

require_once 'stripe_database.php';
require_once 'KLogger.php';

$DbObject    = new MySQLDB;
$MyLogger    = new KLogger(STRIPE_LOG_FILE_CHARGE, KLogger::DEBUG);
$MyRawLogger = STRIPE_RAW_LOGGING ? new KLogger(STRIPE_RAW_LOG_FILE_CHARGE, KLogger::DEBUG) : null;
require_once STRIPE_INIT_LOCATION;

\Stripe\Stripe::setApiKey(STRIPE_SECRET_KEY);

$Handled = false;
$Body      = @file_get_contents('php://input');
$SigHeader = $_SERVER['HTTP_STRIPE_SIGNATURE'] ?? '';

try {
    $EventJson = \Stripe\Webhook::constructEvent($Body, $SigHeader, STRIPE_WEBHOOK_SECRET_CHARGE);
} catch (\UnexpectedValueException $E) {
    $MyLogger->logDebug("Rejected request: invalid payload");
    http_response_code(400);
    exit;
} catch (\Stripe\Exception\SignatureVerificationException $E) {
    $MyLogger->logDebug("Rejected request: invalid signature");
    http_response_code(400);
    exit;
}
http_response_code(200);
if ($MyRawLogger) $MyRawLogger->logDebug("RAW_EVENT_JSON: " . $Body);
$MyLogger->logDebug("event: " . $EventJson->type);

// charge.failed is deliberately NOT handled here.  A decline at the PaymentIntent
// level produces no Charge object, so charge.failed never fires for those and
// cannot be the authoritative source for failures.  Failed invoice payments are
// recorded by stripe_event_invoice_c.php on invoice.payment_failed instead.
// Non-invoice charge failures are out of scope.
if ($EventJson->type == 'charge.succeeded') {
    $Handled = true;

    $Charge          = $EventJson->data->object;
    $CustomerID      = $Charge->customer ?? '';
    $PaymentIntentID = $Charge->payment_intent ?? '';
    $Amount          = ($Charge->amount ?? 0) / 100;
    $ChargeDate      = $Charge->created ?? time();

    // Since the Stripe "basil" release neither Charge nor PaymentIntent carries an
    // `invoice` field.  The Charge -> Invoice link now lives in the InvoicePayment
    // object, which Stripe creates when the invoice is finalized — so it resolves
    // for failed charges as well as successful ones.
    $InvoiceID = GetInvoiceIDFromPaymentIntent($PaymentIntentID);
    if ($InvoiceID !== '') {
        $MyLogger->logDebug("Resolved InvoiceID " . $InvoiceID . " from PaymentIntent " . $PaymentIntentID . " via invoice_payments");
    } else {
        $MyLogger->logDebug("No invoice_payment for PaymentIntent " . $PaymentIntentID . " — standalone charge");
    }

    // Extract card/payment method details from the charge object
    $CardType     = '';
    $CardBrand    = '';
    $CardLastFour = '';
    $CardExpMonth = 0;
    $CardExpYear  = 0;
    GetPaymentMethodFromCharge($Charge, $CardType, $CardBrand, $CardLastFour, $CardExpMonth, $CardExpYear);
    $MyLogger->logDebug("charge event - CustomerID: " . $CustomerID . " | CardBrand: " . $CardBrand . " | LastFour: " . $CardLastFour . " | Amount: " . $Amount . " | InvoiceID: " . $InvoiceID);

    $TenantID = ($CustomerID !== '') ? $DbObject->getTenantIDFromStripeID($CustomerID) : -1;

    // Update the tenant's stored card info if we got card data
    if ($CardBrand !== '' || $CardLastFour !== '') {
        $DbObject->updateTenantCardInfo($CustomerID, $CardType, $CardBrand, $CardLastFour, $CardExpMonth, $CardExpYear);
    }

    $DbObject->resumeTenantReporting($TenantID);
    $DbObject->saveChargeResult(
        $TenantID, $CustomerID, $Charge->id, $PaymentIntentID,
        $ChargeDate, $Amount, $CardType, $CardBrand, $CardLastFour,
        'Paid', $InvoiceID, ''
    );
    if ($TenantID > 0) {
        $DbObject->logUserEvent("Charge succeeded: " . $Charge->id . " amount: $" . $Amount, $TenantID);
    }

    // Update the associated invoice with ChargeDate and ChargeID
    if ($InvoiceID !== '') {
        $InvoiceNumber  = '';
        $SubscriptionID = '';
        $InvoiceDate    = date('Y-m-d H:i:s', $ChargeDate);
        $CreateDate     = date('Y-m-d H:i:s', $ChargeDate);
        $DbObject->updateStripeInvoice(
            $InvoiceNumber, $CustomerID, $SubscriptionID, $Amount,
            '', $CreateDate, $InvoiceDate, $InvoiceDate,
            $InvoiceID, $Charge->id, $Charge, $InvoiceDate
        );
    }

    $MyLogger->logDebug("event: " . $EventJson->type . " | ChargeID: " . $Charge->id . " | TenantID: " . $TenantID);
}

if ($Handled == false) {
    $MyLogger->logDebug("unhandled EVENT CONTENTS: " . print_r($EventJson, true));
}
?>
