<?php

// Exit if accessed directly
if (!defined('ABSPATH')) {
    exit;
}


/**
 * Send Unsynced orders to unifed portal after success login and failed order in case of api failure.
 */
function aramex_send_all_unsynced_orders_to_unified($exclude_id = null) {
    $unsynced_orders = wc_get_orders([
        'limit'   => -1,
        'orderby' => 'ID',
        'order'   => 'ASC',
        'return'  => 'ids',
        'status'  => ['processing', 'on-hold'],

        // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
        'meta_query' => [
            [
                'key'     => '_aramex_unified_synced',
                'compare' => 'NOT EXISTS',
            ]
        ],
        'date_query' => [
            [
                'after'     => '3 months ago',
                'inclusive' => true,
            ]
        ]
    ]);

    foreach ($unsynced_orders as $order_id) {
        if ($exclude_id && $order_id == $exclude_id) {
            continue;
        }
        aramex_send_order_to_unified_api($order_id);
    }
}


/**
 * Send WooCommerce Order to Aramex Unified API
 */
function aramex_send_order_to_unified_api( $order_id ) {

    wc_get_logger()->info("Start send order: $order_id", ['source' => 'aramex_test']);

    // Avoid resending already synced orders
     if ( get_post_meta( $order_id, '_aramex_unified_synced', true ) ) {
        wc_get_logger()->info("Order already synced: $order_id", ['source' => 'aramex_test']);
        return;
    }

    // Check if JWT token exists first
    $loggedin_usertoken = sanitize_text_field( get_option( 'aramex_unified_jwt_token' ) );
    if ( empty( $loggedin_usertoken ) ) {
        wc_get_logger()->error("Aramex error: token missing", ['source' => 'aramex_test']);
        return;
    }

    wc_get_logger()->info("JWT token found for Order $order_id", ['source' => 'aramex_test']);
    
    // Decode JWT token
    $decoded_token = array_change_key_case(array_map(fn($v) => is_string($v) ? trim($v) : $v, aramex_decode_jwt_token($loggedin_usertoken)), CASE_LOWER);
    $is_logistics = ! empty( $decoded_token['is_logistics'] ) && $decoded_token['is_logistics'] == 1;
    $is_shipping  = ! empty( $decoded_token['is_shipping'] ) && $decoded_token['is_shipping'] == 1;

    // Get the order
    $order = wc_get_order( $order_id );
    if ( ! $order ) {
        return;
    }

    // Run only if product with tag Aramex-Stock exists in order
    $has_aramex_tag = false;
    foreach ( $order->get_items() as $item ) {
        $product = $item->get_product();
        
        if ( ! $product ) {
            continue; // skip if product not found
        }
        
        $product_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id();
        
        if ( has_term( 'Aramex-Stock', 'product_tag', $product_id ) ) {
            $has_aramex_tag = true;
            break;
        }
    }

    // Default response
    $response = null;

    if ( $has_aramex_tag && $is_logistics ) {
        // Logistics user prepare and send order payload
        $order_items_data = aramex_unified_prepare_order_items_data( $order );
        $payload = aramex_unified_build_order_create_payload( $order, $order_items_data );

        // WooCommerce logger
        wc_get_logger()->info("Aramex Unified Order Payload: " . wp_json_encode( $payload ), ['source' => 'aramex_test']);

        $response = aramex_unified_api_request(
            'POST',
            ARXEC_ORDER_ENDPOINT,
            $loggedin_usertoken,
            $payload
        );

        // Log the response
        wc_get_logger()->info("Aramex Unified Order PayResponseload: " . wp_json_encode( $response ), ['source' => 'aramex_test']);

    }

    // if Shipping user then create shipment
    if ($is_shipping ) {
        aramex_unified_send_create_shipment( $order_id );
    }

    // If user is logistics, check response and mark order as synced if successful
     if ( $has_aramex_tag && $is_logistics ) {
        if ( $response === false || ! is_array( $response ) ) {
            return [ 'error' => 'No response or invalid response from Unified API.' ];
        }

        // Check if API response is success before marking as synced
        if ( isset( $response['status'] ) && $response['status'] === 'fresh' && !empty( $response['id'] ) ) {
            update_post_meta( $order_id, '_aramex_unified_synced', 1 );
        }
    }
        return $response;
}


/**
 * Decode JWT without verifying signature.
 *
 * @param string $token
 * @return array|null
 */
function aramex_decode_jwt_token($token) {
    $parts = explode('.', $token);
    if (count($parts) !== 3) {
        return null;
    }

    $payload = $parts[1];
    $decoded = base64_decode(strtr($payload, '-_', '+/'));
    return json_decode($decoded, true);
}

/**
 * Permission callback for Unified API endpoints.:
 * Validate JWT token + Aramex Unified API headers
 * (x-plugin-key, x-timestamp, x-signature)
 *
 * @param WP_REST_Request $request
 * @return true|WP_Error
 */
function aramex_unified_portal_permission_check( WP_REST_Request $request ) {
    
    // Only allow POST method
    $method = strtoupper( $request->get_method() );
    if ( $method !== 'POST' ) {
        return new WP_Error(
            'rest_forbidden',
            __( 'Only POST method is allowed.', 'aramex-ecommcore' ),
            [ 'status' => 405 ] // 405 Method Not Allowed
        );
    }
    
    // Log all permission check calls
    $route = $request->get_route();
    $request_uri_log = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
    wc_get_logger()->info( 'Permission Check Called', [
        'source' => 'aramex-webhook',
        'method' => $method,
        'route' => $route,
        'request_uri' => $request_uri_log,
    ] );

    // REQUIRED CONSTANTS
    if ( ! defined( 'WOOCOM_API_SECRET' ) ) {
        wc_get_logger()->error( 'Permission Check Failed: API secret not configured', [
            'source' => 'aramex-webhook',
        ] );
        return new WP_Error(
            'rest_forbidden',
            __( 'API secret not configured.', 'aramex-ecommcore' ),
            [ 'status' => 403 ]
        );
    }

    $plugin_key = 'WOOCOM';
    $api_secret  = WOOCOM_API_SECRET;
    $allowed_time_diff = 900; // 5 minutes replay protection

    // READ HEADERS
    $auth_header  = $request->get_header( 'authorization' );
    $plugin_key   = $request->get_header( 'x-plugin-key' );
    $timestamp    = $request->get_header( 'x-timestamp' );
    $signature    = $request->get_header( 'x-signature' );

    if ( empty( $auth_header ) || empty( $plugin_key ) || empty( $timestamp ) || empty( $signature )) {
        return new WP_Error(
            'rest_forbidden',
            __( 'Missing authentication headers.', 'aramex-ecommcore' ),
            [ 'status' => 403 ]
        );
    }

    // VALIDATE PLUGIN KEY
    if ( $plugin_key !== 'WOOCOM' ) {
        return new WP_Error(
            'rest_forbidden',
            __( 'Invalid plugin key.', 'aramex-ecommcore' ),
            [ 'status' => 403 ]
        );
    }

    // VALIDATE TIMESTAMP (Replay Attack)
    if ( ! ctype_digit( (string) $timestamp ) ) {
        return new WP_Error(
            'rest_forbidden',
            __( 'Invalid timestamp.', 'aramex-ecommcore' ),
            [ 'status' => 403 ]
        );
    }

    if ( abs( time() - (int) $timestamp ) > $allowed_time_diff ) {
        return new WP_Error(
            'rest_forbidden',
            __( 'Request expired.', 'aramex-ecommcore' ),
            [ 'status' => 403 ]
        );
    }

    // BUILD STRING TO SIGN
    $method = strtoupper( $request->get_method() );
    
    // Get full path from REQUEST_URI including subdirectory and /wp-json/
    $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
    $parsed_route = wp_parse_url( $request_uri );
    $path = $parsed_route['path'] ?? $request->get_route();

    if ( in_array( $method, [ 'GET', 'DELETE' ], true ) ) {
        $params = $request->get_query_params();
        if ( ! empty( $params ) ) {
            ksort( $params ); // Sort params like OpenCart does
            $canonical_data = http_build_query( $params, '', '&', PHP_QUERY_RFC3986 );
        } else {
            $canonical_data = '';
        }
    } else {
        // Parse body and use clean JSON for signature verification (matching OpenCart)
        $body = $request->get_json_params();
        $canonical_data = ! empty( $body )
            ? json_encode( $body, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE )
            : '';
    }

    $data_hash = hash( 'sha256', $canonical_data );

    $string_to_sign = implode( '|', [
        $plugin_key,
        $timestamp,
        $method,
        $path,
        $data_hash,
    ] );
    
    $expected_signature = hash_hmac( 'sha256', $string_to_sign, $api_secret );
    
    // Log signature verification details for debugging (skip OPTIONS requests)
    if ( $method !== 'OPTIONS' ) {
        $log_data = [
            'source' => 'aramex-webhook',
            'method' => $method,
            'path' => $path,
            'plugin_key' => $plugin_key,
            'timestamp' => $timestamp,
            'canonical_data' => $canonical_data,
            'data_hash' => $data_hash,
            'string_to_sign' => $string_to_sign,
            'expected_signature' => $expected_signature,
            'provided_signature' => $signature,
            'signature_match' => hash_equals( $expected_signature, $signature ),
        ];
        
        // Add body data for POST/PUT/PATCH requests
        if ( ! in_array( $method, [ 'GET', 'DELETE' ], true ) ) {
            $raw_body = file_get_contents( 'php://input' ) ?: $request->get_body();
            $log_data['raw_body'] = $raw_body;
            $log_data['parsed_body'] = $body ?? null;
        }
        
        wc_get_logger()->info( 'Aramex Webhook Signature Verification', $log_data );
    }
    
    // Detailed logging before signature check
    $signature_check_result = hash_equals( $expected_signature, $signature );
    wc_get_logger()->info( 'Before Signature Check', [
        'source' => 'aramex-webhook',
        'expected_signature' => $expected_signature,
        'expected_signature_length' => strlen( $expected_signature ),
        'provided_signature' => $signature,
        'provided_signature_length' => strlen( $signature ),
        'signatures_equal' => $signature_check_result,
        'hash_equals_result' => $signature_check_result,
        'method' => $method,
    ] );
    
    if ( ! $signature_check_result ) {
        // Log detailed error information
        wc_get_logger()->error( 'Signature Verification Failed', [
            'source' => 'aramex-webhook',
            'expected_signature' => $expected_signature,
            'provided_signature' => $signature,
            'string_to_sign' => $string_to_sign,
            'path' => $path,
            'canonical_data' => $canonical_data,
            'data_hash' => $data_hash,
            'method' => $method,
            'timestamp' => $timestamp,
            'plugin_key' => $plugin_key,
        ] );
        
        return new WP_Error(
            'rest_forbidden',
            __( 'Invalid request signature.', 'aramex-ecommcore' ),
            [ 'status' => 403 ]
        );
    }
    
    // Log successful signature verification
    wc_get_logger()->info( 'Signature Verification Passed', [
        'source' => 'aramex-webhook',
        'method' => $method,
        'path' => $path,
    ] );

    // JWT TOKEN VALIDATION
    wc_get_logger()->info( 'Starting JWT Token Validation', [
        'source' => 'aramex-webhook',
        'method' => $method,
        'auth_header_present' => ! empty( $auth_header ),
        'auth_header_preview' => substr( $auth_header ?? '', 0, 20 ),
    ] );
    
    if ( stripos( $auth_header, 'Bearer ' ) !== 0 ) {
        wc_get_logger()->error( 'JWT Validation Failed: Invalid authorization header', [
            'source' => 'aramex-webhook',
            'auth_header' => $auth_header,
        ] );
        return new WP_Error(
            'rest_forbidden',
            __( 'Invalid authorization header.', 'aramex-ecommcore' ),
            [ 'status' => 403 ]
        );
    }

    // Basic JWT token validation - just check token exists and is decodable
    $provided_token = trim( substr( $auth_header, 7 ) );

    if ( empty( $provided_token ) ) {
        wc_get_logger()->error( 'JWT Validation Failed: Missing JWT token', [
            'source' => 'aramex-webhook',
        ] );
        return new WP_Error(
            'rest_forbidden',
            __( 'Missing JWT token.', 'aramex-ecommcore' ),
            [ 'status' => 403 ]
        );
    }

    // Verify token can be decoded (basic format validation)
    $provided_payload = aramex_decode_jwt_token( $provided_token );

    if ( ! is_array( $provided_payload ) ) {
        wc_get_logger()->error( 'JWT Validation Failed: Invalid JWT token format', [
            'source' => 'aramex-webhook',
        ] );
        return new WP_Error(
            'rest_forbidden',
            __( 'Invalid JWT token.', 'aramex-ecommcore' ),
            [ 'status' => 403 ]
        );
    }

    // ALL CHECKS PASSED
    return true;
}


// Register REST API endpoint for get order sync data from Unified Portal
add_action('rest_api_init', function () {
    register_rest_route('aramex', '/order-sync-data', [
        'methods'  => 'POST',
        'callback' => 'aramex_unified_portal_order_sync_data',
        'permission_callback' => 'aramex_unified_portal_permission_check',
    ]);
});

/**
 * Order sync callback.
 */
function aramex_unified_portal_order_sync_data( WP_REST_Request $request ) {
    $auth_header = $request->get_header( 'authorization' );
    if ( is_array( $auth_header ) ) {
        $auth_header = reset( $auth_header );
    }

    $provided_token = null;
    if ( is_string( $auth_header ) && stripos( $auth_header, 'Bearer ' ) === 0 ) {
        $provided_token = substr( $auth_header, 7 );
    }

    // Decode token if available (normalize keys + trim)
    $decoded_token = array_change_key_case(
        array_map( 'trim', aramex_decode_jwt_token( $provided_token ) ),
        CASE_LOWER
    );

    // Check is_logistics flag
    $is_logistics = ! empty( $decoded_token['is_logistics'] ) && $decoded_token['is_logistics'] == 1;

    if ( ! $is_logistics ) {
        return new WP_REST_Response( [
            'status'  => 'error',
            'message' => 'Unauthorized: Logistics access required',
        ], 403 );
    }

    if ( ! $decoded_token || ! isset( $decoded_token['facility'] ) ) {
        return new WP_REST_Response( [
            'status'  => 'error',
            'message' => 'Invalid or missing facility in token',
        ], 400 );
    }


    $facility   = sanitize_text_field( $decoded_token['facility'] );
    $awb        = sanitize_text_field( $request->get_param( 'AWB' ) );
    $wms_status = sanitize_text_field( $request->get_param( 'LatestStatus' ) );
    $order_id   = absint( $request->get_param( 'order_id' ) );

    $status_mapping = [
        'Created Externally'   => 'processing',
        'Allocated'            => 'processing',
        'Did Not Allocate'     => 'processing',
        'Released'             => 'processing',
        'Picked Complete'      => 'processing',
        'Pack Complete'        => 'processing',
        'Blocked'              => 'on-hold',
        'Cancelled Internally' => 'cancelled',
        'Cancelled Externally' => 'cancelled',
        'Shipped Complete'     => 'processing',
        'Delivered Accepted'   => 'completed',
        'Delivered Rejected'   => 'cancelled',
    ];

    $order = wc_get_order( $order_id );

    // Update order status based on WMS status
    if ( isset( $status_mapping[ $wms_status ] ) && $order ) {
        $order->update_status( $status_mapping[ $wms_status ] );
    }

    if ( ! empty( $awb ) ) {
        $tracking_url = $facility === ARXEC_NETHERLAND_FACILITY
            ? ARXEC_NL_TRACKING_BASE_URL . urlencode( $awb )
            : ARXEC_DEFAULT_TRACKING_BASE_URL . urlencode( $awb );

        $note_content = wp_kses_post( '<a href="' . esc_url( $tracking_url ) . '" target="_blank">Track your shipment</a>' );

        $existing_notes = wc_get_order_notes( [ 'order_id' => $order_id, 'type' => 'customer' ] );
        foreach ( $existing_notes as $note ) {
            if ( strpos( $note->content, 'Track your shipment' ) !== false ) {
                wp_delete_comment( $note->id, true );
            }
        }

        $order->add_order_note( $note_content, true );
        $order->save();
    }

    update_post_meta( $order_id, '_aramex_awb', $awb );

    return new WP_REST_Response( [
        'status'  => 'success',
        'message' => 'Order Sync and Tracking URL Updated Successfully',
    ], 200 );
}

// Register REST API endpoint for get shipment sync data from Unified Portal
add_action('rest_api_init', function () {
    register_rest_route('aramex/unified', '/update-shipment', [
        'methods'  => 'POST',
        'callback' => 'aramex_unified_portal_shipment_sync_data',
        'permission_callback' => 'aramex_unified_portal_permission_check',
    ]);
});

/**
 * Shipment sync callback.
 */
function aramex_unified_portal_shipment_sync_data( WP_REST_Request $request ) {
    $auth_header = $request->get_header( 'authorization' );
    if ( is_array( $auth_header ) ) {
        $auth_header = reset( $auth_header );
    }

    $provided_token = null;
    if ( is_string( $auth_header ) && stripos( $auth_header, 'Bearer ' ) === 0 ) {
        $provided_token = substr( $auth_header, 7 );
    }

    // Decode token if available (normalize keys + trim)
    $decoded_token = array_change_key_case(
        array_map( 'trim', aramex_decode_jwt_token( $provided_token ) ),
        CASE_LOWER
    );

    // Check is_shipping flag
    $is_shipping = ! empty( $decoded_token['is_shipping'] ) && $decoded_token['is_shipping'] == 1;

    if ( ! $is_shipping ) {
        return new WP_REST_Response( [
            'status'  => 'error',
            'message' => 'Unauthorized: Shipping access required',
        ], 403 );
    }
   
    // Get and sanitize parameters
    $awb        = sanitize_text_field( $request->get_param( 'AWB' ) );
    $wms_status = sanitize_text_field( $request->get_param( 'LatestStatus' ) );
    $order_id   = absint( $request->get_param( 'order_id' ) );

    $status_mapping = [
        'pending'     => 'pending-payment',
        'created'     => 'processing',
        'in_progress' => 'processing',
        'delivered'   => 'completed',
    ];

    $order = wc_get_order( $order_id );
    
    // Update order status based on WMS status
    if ( isset( $status_mapping[ $wms_status ] ) && $order ) {
        $order->update_status( $status_mapping[ $wms_status ] );
    }

    if ( ! empty( $awb ) ) {
        $tracking_url = ARXEC_DEFAULT_TRACKING_BASE_URL . urlencode( $awb );

        $note_content = wp_kses_post( '<a href="' . esc_url( $tracking_url ) . '" target="_blank">Track your shipment</a>' );

        $existing_notes = wc_get_order_notes( [ 'order_id' => $order_id, 'type' => 'customer' ] );
        foreach ( $existing_notes as $note ) {
            if ( strpos( $note->content, 'Track your shipment' ) !== false ) {
                wp_delete_comment( $note->id, true );
            }
        }

        $order->add_order_note( $note_content, true );
        $order->save();
    }

    update_post_meta( $order_id, '_aramex_awb', $awb );

    return new WP_REST_Response( [
        'status'  => 'success',
        'message' => 'Shipment Sync and Tracking URL Updated Successfully',
    ], 200 );
}

// Manual Stock Sync
// Register REST API endpoint for stock sync data from Unified Portal.
add_action('rest_api_init', function () {
    register_rest_route('aramex/unified', '/stock-manual-sync', [
        'methods'  => 'POST',
        'callback' => 'aramex_unified_portal_handle_manual_stock_sync',
        'permission_callback' => 'aramex_unified_portal_permission_check',
    ]);
});

function aramex_unified_portal_handle_manual_stock_sync( WP_REST_Request $request ) {

    // Get and validate JSON body
    $auth_header = $request->get_header( 'authorization' );
    if ( is_array( $auth_header ) ) {
        $auth_header = reset( $auth_header );
    }

    $provided_token = null;
    if ( is_string( $auth_header ) && stripos( $auth_header, 'Bearer ' ) === 0 ) {
        $provided_token = substr( $auth_header, 7 );
    }

    // Decode token if available (normalize keys + trim)
    $decoded_token = array_change_key_case(
        array_map( 'trim', aramex_decode_jwt_token( $provided_token ) ),
        CASE_LOWER
    );

    // Check is_logistics flag
    $is_logistics = ! empty( $decoded_token['is_logistics'] ) && $decoded_token['is_logistics'] == 1;

    if ( ! $is_logistics ) {
        return new WP_REST_Response( [
            'status'  => 'error',
            'message' => 'Unauthorized: Logistics access required',
        ], 403 );
    }

    if ( ! $decoded_token || ! isset( $decoded_token['facility'] ) ) {
        return new WP_REST_Response( [
            'status'  => 'error',
            'message' => 'Invalid or missing facility in token',
        ], 400 );
    }

    $data  = $request->get_json_params();
    $lines = $data['Lines'] ?? [];

    if ( empty( $lines ) || ! is_array( $lines ) ) {
        return new WP_REST_Response([
            'status'  => 'error',
            'message' => 'Missing or invalid Lines data',
        ], 400);
    }

    // Aggregate quantities by SKU
    $sku_quantities = [];
    foreach ( $lines as $line ) {
        $sku = sanitize_text_field( $line['SKU'] ?? '' );
        $qty = intval( $line['QtyAvailable'] ?? 0 );

        if ( empty( $sku ) ) {
            continue;
        }

        if ( $qty < 0 ) {
            $qty = 0;
        }

        if ( ! isset( $sku_quantities[$sku] ) ) {
            $sku_quantities[$sku] = 0;
        }
        $sku_quantities[$sku] += $qty; // SUM of Same SKU Qty
    }

    $received_skus     = [];
    $matched_parents   = [];

    //Process aggregated SKUs
    foreach ( $sku_quantities as $sku => $qty ) {
        $product_id = wc_get_product_id_by_sku( $sku );
        if ( ! $product_id ) {
            continue;
        }

        update_post_meta( $product_id, '_stock', $qty );
        update_post_meta( $product_id, '_stock_status', $qty > 0 ? 'instock' : 'outofstock' );

        $product = wc_get_product( $product_id );

        // parent product
        $parent_id      = $product->is_type('variation') ? $product->get_parent_id() : $product_id;
        $parent_product = wc_get_product( $parent_id );
        $parent_sku     = $parent_product ? $parent_product->get_sku() : $sku;

        // Track parent SKU and matched parent ID
        if ( $parent_sku ) {
            $received_skus[] = $parent_sku;
        }

        if ( $parent_id ) {
            $matched_parents[ $parent_id ] = true;

            // Always tag parent with Aramex-Stock
            wp_set_post_terms( $parent_id, [ ARXEC_STOCK_TAG ], 'product_tag', true );
        }
    }

    // Remove Aramex tag and mark outofstock if tagged SKU is missing from API
    $args = [
        'post_type'      => [ 'product', 'product_variation' ],
        'posts_per_page' => -1,
        'post_status'    => 'publish',
        
        // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
        'tax_query'      => [
            [
                'taxonomy' => 'product_tag',
                'field'    => 'name',
                'terms'    => [ ARXEC_STOCK_TAG ],
            ],
        ],

        // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
        'meta_query'     => [
            [
                'key'     => '_sku',
                'compare' => 'EXISTS',
            ],
        ],
        'fields' => 'ids',
    ];

    $tagged_products = get_posts( $args );

    foreach ( $tagged_products as $post_id ) {
        $sku = get_post_meta( $post_id, '_sku', true );

        if ( $sku && ! in_array( $sku, $received_skus, true ) ) {
            update_post_meta( $post_id, '_stock', 0 );
            update_post_meta( $post_id, '_stock_status', 'outofstock' );

            wp_remove_object_terms( $post_id, ARXEC_STOCK_TAG, 'product_tag' );
        }
    }

    // Remove tag from parent products (with no SKU) if none of their variations matched
    // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
    $parent_products_with_tag = get_posts([
        'post_type'      => 'product',
        'posts_per_page' => -1,
        'post_status'    => 'publish',

        // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
        'tax_query'      => [
            [
                'taxonomy' => 'product_tag',
                'field'    => 'name',
                'terms'    => [ ARXEC_STOCK_TAG ],
            ],
        ],
        'fields' => 'ids',
    ]);

    foreach ( $parent_products_with_tag as $parent_id ) {
        if ( ! isset( $matched_parents[ $parent_id ] ) ) {

            // Parent had tag, but none of its variations matched
            wp_remove_object_terms( $parent_id, ARXEC_STOCK_TAG, 'product_tag' );
            update_post_meta( $parent_id, '_stock', 0 );
            update_post_meta( $parent_id, '_stock_status', 'outofstock' );

            // Mark variations SKU out of stock if not existing in API
            $variation_ids = get_posts([
                'post_type'      => 'product_variation',
                'post_status'    => 'publish',
                'posts_per_page' => -1,
                'post_parent'    => $parent_id,
                'fields'         => 'ids',
            ]);

            foreach ( $variation_ids as $variation_id ) {
                update_post_meta( $variation_id, '_stock', 0 );
                update_post_meta( $variation_id, '_stock_status', 'outofstock' );
            }
        }
    }

    return new WP_REST_Response([
        'status'       => 'success',
        'message'      => 'Manual Stock Sync Completed Successfully',
        'updated_skus' => $received_skus,
    ], 200);
}

// Webbook Stock Sync
// Register API Endpoint for Stock Sync from Unified Portal
add_action('rest_api_init', function () {
    register_rest_route('aramex/unified', '/stock-webhook-sync', [
        'methods'  => 'POST',
        'callback' => 'aramex_unified_portal_handle_webhook_stock_sync',
        'permission_callback' => 'aramex_unified_portal_permission_check',
    ]);
});

/**
 * Handle Aramex Webhook Stock Sync
 */
function aramex_unified_portal_handle_webhook_stock_sync( WP_REST_Request $request ) {
    $auth_header = $request->get_header( 'authorization' );
    if ( is_array( $auth_header ) ) {
        $auth_header = reset( $auth_header );
    }

    $provided_token = null;
    if ( is_string( $auth_header ) && stripos( $auth_header, 'Bearer ' ) === 0 ) {
        $provided_token = substr( $auth_header, 7 );
    }

    // Decode token if available
    $decoded_token = array_change_key_case(
        array_map( 'trim', aramex_decode_jwt_token( $provided_token ) ),
        CASE_LOWER
    );

    // Check is_logistics flag
    $is_logistics = ! empty( $decoded_token['is_logistics'] ) && $decoded_token['is_logistics'] == 1;

    if ( ! $is_logistics ) {
        return new WP_REST_Response( [
            'status'  => 'error',
            'message' => 'Unauthorized: Logistics access required',
        ], 403 );
    }

    if ( ! $decoded_token || ! isset( $decoded_token['facility'] ) ) {
        return new WP_REST_Response( [
            'status'  => 'error',
            'message' => 'Invalid or missing facility in token',
        ], 400 );
    }
    
    $data = $request->get_json_params();

    if ( json_last_error() !== JSON_ERROR_NONE ) {
        wp_send_json_error([ 'message' => 'Invalid JSON format' ], 400);
    }

    if ( ! isset( $data['Lines'] ) || ! is_array( $data['Lines'] ) ) {
        wp_send_json_error([ 'message' => 'Invalid payload structure' ], 400);
    }

    //Aggregate quantities by SKU
    $sku_quantities = [];
    foreach ( $data['Lines'] as $line ) {
        if ( empty( $line['SKU'] ) || ! isset( $line['QtyAvailable'] ) ) {
            continue;
        }

        $sku = sanitize_text_field( $line['SKU'] );
        $qty = max( 0, intval( $line['QtyAvailable'] ) );

        if ( ! isset( $sku_quantities[ $sku ] ) ) {
            $sku_quantities[ $sku ] = 0;
        }
        $sku_quantities[ $sku ] += $qty; //SUM of Same SKU Qty
    }

    $parent_ids_to_update = [];

    //Update Products with SUM qty
    foreach ( $sku_quantities as $sku => $qty_available ) {
        $product_id = wc_get_product_id_by_sku( $sku );
        if ( ! $product_id ) {
            wc_get_logger()->warning("SKU Not Found in WooCommerce: $sku", ['source' => 'aramex-stock-sync']);
            continue;
        }

        $product = wc_get_product( $product_id );
        if ( ! $product ) {
            continue;
        }

        // Update stock with SUM qty
        update_post_meta( $product_id, '_stock', $qty_available );
        update_post_meta( $product_id, '_stock_status', $qty_available > 0 ? 'instock' : 'outofstock' );

        if ( $product->is_type('variation') ) {
            wc_get_logger()->info("Stock Updated (SUM) for Variation SKU: $sku, Qty: $qty_available", ['source' => 'aramex-stock-sync']);
            $parent_id = wp_get_post_parent_id( $product_id );
            if ( $parent_id ) {
                $parent_ids_to_update[] = $parent_id;
            }
        } elseif ( $product->is_type('simple') ) {
            wc_get_logger()->info("Stock Updated (SUM) for Simple SKU: $sku, Qty: $qty_available", ['source' => 'aramex-stock-sync']);
        } else {
            wc_get_logger()->info("Ignored product type for SKU: $sku", ['source' => 'aramex-stock-sync']);
        }
    }

    // Update Parent Products
    foreach ( array_unique($parent_ids_to_update) as $parent_id ) {
        $parent_product = wc_get_product( $parent_id );
        if ( ! $parent_product ) {
            wc_get_logger()->error("Parent product not found for ID: $parent_id", ['source' => 'aramex-stock-sync']);
            continue;
        }

        $parent_sku = $parent_product->get_sku();
        if ( empty( $parent_sku ) ) {
            wc_get_logger()->warning("Parent SKU missing for ID: $parent_id", ['source' => 'aramex-stock-sync']);
            continue;
        }

        // Get SUM qty for parent SKU
        $parent_qty = isset( $sku_quantities[$parent_sku] ) ? $sku_quantities[$parent_sku] : 0;

        if ( $parent_qty > 0 ) {
            update_post_meta( $parent_id, '_stock', $parent_qty );
            update_post_meta( $parent_id, '_stock_status', 'instock' );
            wc_get_logger()->info("Stock Updated (SUM) for Parent SKU: $parent_sku, ID: $parent_id, Qty: $parent_qty", ['source' => 'aramex-stock-sync']);
        } else {
            update_post_meta( $parent_id, '_stock', 0 );
            update_post_meta( $parent_id, '_stock_status', 'outofstock' );
            wc_get_logger()->info("Parent SKU: $parent_sku marked out of stock (Qty: 0)", ['source' => 'aramex-stock-sync']);
        }
    }

    wp_send_json_success([ 'message' => 'Webhook Stock Sync Updated Successfully' ]);
}


// Webbook For getting Aramex Token From UP.
// Register API Endpoint for aramex-token
add_action('rest_api_init', function () {
    register_rest_route('aramex/unified', '/auth-jwt-token', [
        'methods'  => 'POST',
        'callback' => 'aramex_unified_portal_get_jwt_token',
        // This endpoint is intentionally public because  its First time login so we dont have stored token yet and Aramex sends a fixed webhook payload.
        // It does NOT expose any sensitive data or modify WordPress content directly.
        'permission_callback' => '__return_true',
    ]);
});

/**
 * Handle Aramex Webhook Stock Sync (After Redirect to UP now this webhook will get token from UP and store in WP)
 */
function aramex_unified_portal_get_jwt_token( WP_REST_Request $request ) {
    $data = $request->get_json_params();

    if ( json_last_error() !== JSON_ERROR_NONE ) {
        wp_send_json_error([ 'message' => 'Invalid JSON format' ], 400);
    }

    if ( ! isset( $data['token'] ) || empty( $data['token'] ) ) {
        wp_send_json_error([ 'message' => 'Missing token in payload' ], 400);
    }

    $new_token = sanitize_text_field( $data['token'] );
    
    // Store the jwt token from unified portal
    update_option( 'aramex_unified_jwt_token', $new_token );

    // After saving the new token, trigger sync for all unsynced unsend orders
    if (function_exists('aramex_send_all_unsynced_orders_to_unified')) {
        aramex_send_all_unsynced_orders_to_unified();
    }

    // Return success msgage
    wp_send_json_success([ 'message' => 'JWT Token Updated Successfully' ]);
    
}

// Webhook to get Config settings of Rate Calculator from Unified Portal
add_action('rest_api_init', function () {
    register_rest_route('aramex/unified', '/get-rate-calculator-config', [
        'methods'  => 'POST',
        'callback' => 'aramex_unified_portal_handle_rate_calculator_config',
        'permission_callback' => 'aramex_unified_portal_permission_check',
    ]);
});

/**
 * Handle Aramex Webhook for Rate Calculator Config
 */
function aramex_unified_portal_handle_rate_calculator_config( WP_REST_Request $request ) {
    $auth_header = $request->get_header( 'authorization' );
    if ( is_array( $auth_header ) ) {
        $auth_header = reset( $auth_header );
    }

    $provided_token = null;
    if ( is_string( $auth_header ) && stripos( $auth_header, 'Bearer ' ) === 0 ) {
        $provided_token = substr( $auth_header, 7 );
    }

    // Decode token if available
    $decoded_token = array_change_key_case(
        array_map( 'trim', aramex_decode_jwt_token( $provided_token ) ),
        CASE_LOWER
    );

    // Check is_shipping flag
    $is_shipping = ! empty( $decoded_token['is_shipping'] ) && $decoded_token['is_shipping'] == 1;

    if ( ! $is_shipping ) {
        return new WP_REST_Response( [
            'status'  => 'error',
            'message' => 'Unauthorized: Shipping access required',
        ], 403 );
    }
    
    $data = $request->get_json_params();

    if ( json_last_error() !== JSON_ERROR_NONE ) {
        wp_send_json_error([ 'message' => 'Invalid JSON format' ], 400);
    }

    // Sanitize and save the rate calculator configuartion to wp_options
    update_option('arxec_enable_plugin_rate_calculator', (int) $data['enable_plugin_rate_calculator']);
    update_option('arxec_enable_rate_calculator_on_cart', (int) $data['enable_rate_calculator_on_cart']);
    update_option('arxec_enable_rate_calculator_on_product_detail', (int) $data['enable_rate_calculator_on_product_detail']);
    update_option('arxec_enable_rate_calculator_on_checkout', (int) $data['enable_rate_calculator_on_checkout']);

    wp_send_json_success([ 'message' => 'Rate Calculator Config Saved Successfully' ]);
}

/**
 * Cancel WooCommerce Order in Aramex Unified API
 */
function aramex_unified_send_cancel_or_update_to_wms( $order_id, $create_after_cancelling = 0 ) {

    // Check if JWT token exists first
    $loggedin_usertoken = sanitize_text_field( get_option( 'aramex_unified_jwt_token' ) );
    if ( empty( $loggedin_usertoken ) || ! function_exists( 'wc_get_order' ) ) {
        return [ 'error' => 'User not logged in or WooCommerce missing.' ];
    }

    // Decode JWT token to check is_logistics flag
    $decoded_token = array_change_key_case(array_map(fn($v) => is_string($v) ? trim($v) : $v, aramex_decode_jwt_token($loggedin_usertoken)), CASE_LOWER);
    $is_logistics = ! empty( $decoded_token['is_logistics'] ) && $decoded_token['is_logistics'] == 1;
    
    $order = wc_get_order( $order_id );
    if ( ! $order ) {
        return [ 'error' => 'Invalid order' ];
    }

    // Run only if product with tag Aramex-Stock exists in order
    $has_aramex_tag = false;
    foreach ( $order->get_items() as $item ) {
        $product = $item->get_product();
        
        if ( ! $product ) {
            continue; // skip if product not found
        }

        $product_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id();
        
        if ( has_term( 'Aramex-Stock', 'product_tag', $product_id ) ) {
            $has_aramex_tag = true;
            break;
        }
    }

    if ( ! $has_aramex_tag ) {
        return [ 'error' => "No 'Aramex-Stock' tag in order products." ];
    }

    // Prepare payload only if user is logistics
    if ( $is_logistics ) {
        // Prepare cancellation payload
        $order_items_data = aramex_unified_prepare_order_items_data( $order );
        $payload = aramex_unified_build_order_cancel_payload( $order, $order_items_data, $create_after_cancelling );

        // Send to Aramex Unified Cancel API
        $response = aramex_unified_api_request(
            'PATCH',
            ARXEC_ORDER_UPDATE_ENDPOINT,
            $loggedin_usertoken,
            $payload
        );


        if ( is_wp_error( $response ) || ! is_array( $response ) ) {
            return [ 'error' => 'Aramex Cancel API failed' ];
        }

        return $response;
    } else {
    return [ 'error' => 'Logistics not enabled' ];
    }
}


/**
 * Create Shipment for WooCommerce Order in Aramex Unified API
 */
function aramex_unified_send_create_shipment( $order_id ) {

    // JWT token check
    $loggedin_usertoken = sanitize_text_field( get_option( 'aramex_unified_jwt_token' ) );
    if ( empty( $loggedin_usertoken ) || ! function_exists( 'wc_get_order' ) ) {
        return [ 'error' => 'User not logged in or WooCommerce missing.' ];
    }

    // Decode JWT token to check is_logistics flag
    $decoded_token = array_change_key_case(array_map('trim', aramex_decode_jwt_token($loggedin_usertoken)), CASE_LOWER);

    $is_shipping  = ! empty( $decoded_token['is_shipping'] ) && $decoded_token['is_shipping'] == 1;

    $order = wc_get_order( $order_id );
    if ( ! $order ) {
        return [ 'error' => 'Invalid order' ];
    }

    // Check if shipment already created
    if ( get_post_meta( $order_id, '_aramex_shipment_created', true ) ) {
        return [ 'skipped' => 'Shipment already created for this order' ];
    }
    
    // Check if there are any shippable items (i.e., not tagged as Aramex-Stock)
    if( $is_shipping ){
        $order_items_data = aramex_unified_order_shipment_items_data( $order );

        if ( empty( $order_items_data ) ) {
            return [ 'skipped' => 'All items are Aramex-Stock tagged. No shipment needed.' ];
        }
    
        // Prepare shipment payload
        $payload = aramex_unified_build_create_shipment_payload( $order, $order_items_data );

        // WooCommerce logger setup
        $logger  = class_exists( 'WC_Logger' ) ? wc_get_logger() : null;
        $context = array( 'source' => 'aramex-ecommcore' );
        if ( $logger ) {
            $logger->info( "Aramex Create Shipment Payload (#$order_id): " . wp_json_encode( $payload ), $context );
        }

        // Send request to Unified Portal Shipment API
        $response = aramex_unified_api_request(
            'POST',
            ARXEC_ORDER_CREATE_SHIPMENT,
            $loggedin_usertoken,
            $payload
        );

        if ( $logger ) {
            $logger->info( "Aramex Create Shipment API Response (#$order_id): " . wp_json_encode( $response ), $context );
        }
        
        if ( is_wp_error( $response ) || ! is_array( $response ) ) {
            return [ 'error' => 'Aramex Shipment API failed' ];
        }
         
        if ( isset( $response['id'] ) && ! empty( $response['id'] ) ) {
            update_post_meta( $order_id, '_aramex_shipment_created', 1 );
        }
    } else {
        return [ 'skipped' => 'User does not have shipping permissions.' ];
    }
    return $response;
}


/**
 * Cancel Shipment for WooCommerce Order in Aramex Unified API
 */
function aramex_unified_send_cancel_shipment( $order_id ) {

    // JWT token check
    $loggedin_usertoken = sanitize_text_field( get_option( 'aramex_unified_jwt_token' ) );
    if ( empty( $loggedin_usertoken ) || ! function_exists( 'wc_get_order' ) ) {
        return [ 'error' => 'User not logged in or WooCommerce missing.' ];
    }

    // Decode JWT token to check is_logistics flag
    $decoded_token = array_change_key_case(array_map('trim', aramex_decode_jwt_token($loggedin_usertoken)), CASE_LOWER);

    $is_shipping  = ! empty( $decoded_token['is_shipping'] ) && $decoded_token['is_shipping'] == 1;

    $order = wc_get_order( $order_id );
    if ( ! $order ) {
        return [ 'error' => 'Invalid order' ];
    }
    
    // Check if shipment already cancelled
    if ( get_post_meta( $order_id, '_aramex_shipment_cancelled', true ) ) {
        return [ 'skipped' => 'Shipment already cancelled for this order' ];
    }

    // Check if there are any shippable items (i.e., not tagged as Aramex-Stock)
    if( $is_shipping ){
        $order_items_data = aramex_unified_order_shipment_items_data( $order );
        $payload = aramex_unified_build_create_shipment_payload( $order, $order_items_data, 'cancel');

        // Send request to Unified Portal Shipment API
        $response = aramex_unified_api_request(
            'POST',
            ARXEC_ORDER_CREATE_SHIPMENT,
            $loggedin_usertoken,
            $payload
        );

        if ( is_wp_error( $response ) || ! is_array( $response ) ) {
            return [ 'error' => 'Aramex Shipment API failed' ];
        }

        if ( isset( $response['id'] ) && ! empty( $response['id'] ) ) {
            update_post_meta( $order_id, '_aramex_shipment_cancelled', 1 );
        }
    } else {
        return [ 'skipped' => 'User does not have shipping permissions.' ];
    }
    return $response;
}