<?php

const WC_ORDER_ID                    = 'woocommerce_order_id';
const RAZORPAY_PAYMENT_ID            = 'razorpay_payment_id';
const RAZORPAY_ORDER_ID              = 'razorpay_order_id';
const RAZORPAY_SIGNATURE             = 'razorpay_signature';
const RAZORPAY_OFFER                 = 'razorpay_offer';

function prepayCODOrder(WP_REST_Request $request): WP_REST_Response {
    try
    {
        $payload = $request->get_params();
        $wcRazorpay = new WC_Razorpay(false);

        $orderId          = $payload[WC_ORDER_ID];
        $razorpayPaymentId = $payload[RAZORPAY_PAYMENT_ID];
        $razorpayOrderId  = $payload[RAZORPAY_ORDER_ID];
        $signature        = $payload[RAZORPAY_SIGNATURE];
        $razorpayOffer    = $payload[RAZORPAY_OFFER];

        // Validate the order exists before any further processing
        $order = wc_get_order($orderId);
        if (!$order)
        {
            return new WP_REST_Response(['code' => 'invalid_order'], 400);
        }

        // Prevent double-payment on an already-paid order
        if ($order->is_paid())
        {
            return new WP_REST_Response(['code' => 'order_already_paid'], 400);
        }

        // Validate that the Razorpay order ID in the request matches what was stored
        // when the WooCommerce order was created. The stored meta key depends on
        // whether this is a 1CC (Magic Checkout) order or a standard checkout order:
        //   1CC orders:  "razorpay_order_id_1cc{orderId}"  (WC_Razorpay::RAZORPAY_ORDER_ID_1CC)
        //   Standard:    "razorpay_order_id{orderId}"      (WC_Razorpay::RAZORPAY_ORDER_ID)
        // See WC_Razorpay::getOrderSessionKey() in woo-razorpay.php for the authoritative logic.
        $is1ccOrder = $order->get_meta('is_magic_checkout_order');
        if ($is1ccOrder === 'yes')
        {
            $sessionKey = 'razorpay_order_id_1cc' . $orderId;
        }
        else
        {
            $sessionKey = 'razorpay_order_id' . $orderId;
        }

        $storedRazorpayOrderId = $order->get_meta($sessionKey);

        if (empty($storedRazorpayOrderId))
        {
            return new WP_REST_Response(['code' => 'razorpay_order_not_found'], 400);
        }

        if ($storedRazorpayOrderId !== $razorpayOrderId)
        {
            return new WP_REST_Response(['code' => 'razorpay_order_id_mismatch'], 400);
        }

        // Verify the Razorpay payment signature using the stored order ID (not the
        // client-supplied one) to close the IDOR window.
        $attributes = array(
            RAZORPAY_ORDER_ID   => $storedRazorpayOrderId,
            RAZORPAY_PAYMENT_ID => $razorpayPaymentId,
            RAZORPAY_SIGNATURE  => $signature,
        );

        try
        {
            $api = $wcRazorpay->getRazorpayApiInstance();
            $api->utility->verifyPaymentSignature($attributes);
        }
        catch (Exception $e)
        {
            return new WP_REST_Response(["code" => 'woocommerce_order_payment_signature_verfication_failed'], 400);
        }

        if ('on-hold' != $order->get_status())
        {
            return new WP_REST_Response(['code' => 'woocommerce_order_not_in_on_hold_status'], 400);
        }

        $order->set_status('pending');
        $order->save();
        $couponInput = [];

        if (isset($payload['coupon']))
        {
            $couponKey = $payload['coupon']['code'];
            $amount = $payload['coupon']['amount'];
            $amountInRs = $amount/100;
            $couponInput[$couponKey] = $amountInRs;
        }
        if ($razorpayOffer > 0)
        {
            $razorpayOfferInRs = $razorpayOffer/100;
            $couponKey = 'Razorpay offers_'. $orderId .'(₹'. $razorpayOfferInRs .')';
            $couponInput[$couponKey] = $razorpayOfferInRs;
        }

        if (sizeof($couponInput) > 0 )
        {
            $error = bulkCouponApply($couponInput, $wcRazorpay, $order);
            if (sizeof($error) > 0 )
            {
                handleCouponFailure($couponInput, $order);

                $rzp = new WC_Razorpay();
                $trackObject = $rzp->newTrackPluginInstrumentation();
                $properties = [
                    'error' => 'Bulk coupon apply failed',
                    'log'   => $error
                ];
                $trackObject->rzpTrackDataLake('razorpay.1cc.cod.create.coupon.error', $properties);

                return new WP_REST_Response($error, 500);
            }
        }
        $order->set_payment_method($wcRazorpay->id);
        $order->set_payment_method_title($wcRazorpay->title);
        $order->payment_complete($razorpayPaymentId);
        $order->set_status("processing");
        $order->save();
        $order->add_order_note("COD Order Converted to Prepaid <br/> Razorpay payment successful <br/>Razorpay Id: $razorpayPaymentId");
        return new WP_REST_Response([], 200);
    }
    catch (Throwable $e)
    {
        $rzp = new WC_Razorpay();
        $trackObject = $rzp->newTrackPluginInstrumentation();
        $properties = [
            'error' => $e->getMessage(),
            'code'  => $e->getCode(),
            'file'  => $e->getFile(),
            'line'  => $e->getLine()
        ];
        $trackObject->rzpTrackDataLake('razorpay.1cc.cod.processing.failed', $properties);
        rzpLogError(json_encode($properties));

        return new WP_REST_Response(['message' => "woocommerce server error : " . $e->getMessage()], 500);
    }
}

function handleCouponFailure($couponInput, $order) {
    foreach($couponInput as $couponCode => $amount) {
        $order->remove_coupon($couponCode);
    }
    $order->set_status('on-hold');
    $order->save();
}

function bulkCouponApply($input, $wcRazorpay, $order) : array {
    foreach($input as $couponCode => $amount) {
        $isSuccess = createCoupon($couponCode, $amount);
        if ($isSuccess === false) {
            rzpLogError("Prepay cod create coupon error, key : " . $couponCode);
            return['code' => 'woocommerce_create_new_'. $couponCode .'_coupon_error'];
        }
        $wcRazorpay->applyCoupon($order, $couponCode, $amount);
    }
    return [];
}

function createCoupon($coupon_code, $amount) : bool {
    $coupon = array(
        'post_title' => $coupon_code,
        'post_content' => '',
        'post_status' => 'publish',
        'post_author' => 1,
        'post_type' => 'shop_coupon');

    $new_coupon_id = wp_insert_post( $coupon );

    if( $new_coupon_id === 0) {
        return false;
    }

    $input = [
        'discount_type' => 'fixed_cart',
        'coupon_amount' => $amount,
        'usage_limit' => 1,
        'minimum_amount' => $amount,
    ];

    return bulkUpdatePostMeta($new_coupon_id, $input);
}

function bulkUpdatePostMeta($id, $input): bool {
    foreach ($input as $key => $value) {
        $isSuccess = update_post_meta($id, $key, $value);
        if($isSuccess === false) {
            rzpLogError("Prepay COD create coupon : update post meta error, key : " . $key . ", value : " . $value);
            return false;
        }
    }
    return true;
}
