# Rajaongkir Integration with WooNooW SPA

This guide explains how to integrate Rajaongkir's destination selector with WooNooW's customer checkout SPA.

---

## Prerequisites

Before using this integration:

1. **Rajaongkir Plugin Installed & Active**
2. **WooCommerce Shipping Zone Configured**
   - Go to: WC → Settings → Shipping → Zones
   - Add Rajaongkir method to your Indonesia zone
3. **Valid API Key** (Check in Rajaongkir settings)
4. **Couriers Selected** (In Rajaongkir settings)

---

## Code Snippet

Add this to **Code Snippets** or **WPCodebox**:

```php
<?php
/**
 * Rajaongkir Bridge for WooNooW SPA Checkout
 * 
 * Enables searchable destination field in WooNooW checkout
 * and bridges data to Rajaongkir plugin.
 */

// ============================================================
// 1. REST API Endpoint: Search destinations via Rajaongkir API
// ============================================================
add_action('rest_api_init', function() {
    register_rest_route('woonoow/v1', '/rajaongkir/destinations', [
        'methods'             => 'GET',
        'callback'            => 'woonoow_rajaongkir_search_destinations',
        'permission_callback' => '__return_true',
        'args'                => [
            'search' => [
                'required' => false,
                'type'     => 'string',
            ],
        ],
    ]);
});

function woonoow_rajaongkir_search_destinations($request) {
    $search = sanitize_text_field($request->get_param('search') ?? '');
    
    if (strlen($search) < 3) {
        return [];
    }
    
    // Check if Rajaongkir plugin is active
    if (!class_exists('Cekongkir_API')) {
        return new WP_Error('rajaongkir_missing', 'Rajaongkir plugin not active', ['status' => 400]);
    }
    
    // Use Rajaongkir's API class for the search
    // NOTE: Method is search_destination_api() not search_destination()
    $api = Cekongkir_API::get_instance();
    $results = $api->search_destination_api($search);
    
    if (is_wp_error($results)) {
        error_log('Rajaongkir search error: ' . $results->get_error_message());
        return [];
    }
    
    if (!is_array($results)) {
        error_log('Rajaongkir search returned non-array: ' . print_r($results, true));
        return [];
    }
    
    // Format for WooNooW's SearchableSelect component
    $formatted = [];
    foreach ($results as $r) {
        $formatted[] = [
            'value' => (string) ($r['id'] ?? ''),
            'label' => $r['label'] ?? $r['text'] ?? '',
        ];
    }
    
    // Limit results
    return array_slice($formatted, 0, 50);
}

// ============================================================
// 2. Add destination field and hide redundant fields for Indonesia
//    The destination_id from Rajaongkir contains province/city/subdistrict
// ============================================================
add_filter('woocommerce_checkout_fields', function($fields) {
    // Check if Rajaongkir is active
    if (!class_exists('Cekongkir_API')) {
        return $fields;
    }
    
    // Check if store sells to Indonesia (check allowed countries)
    $allowed = WC()->countries->get_allowed_countries();
    if (!isset($allowed['ID'])) {
        return $fields;
    }
    
    // Check if Indonesia is the ONLY allowed country
    $indonesia_only = count($allowed) === 1 && isset($allowed['ID']);
    
    // If Indonesia only, hide country/state/city fields (Rajaongkir destination has all this)
    if ($indonesia_only) {
        // Hide billing fields
        if (isset($fields['billing']['billing_country'])) {
            $fields['billing']['billing_country']['type'] = 'hidden';
            $fields['billing']['billing_country']['default'] = 'ID';
            $fields['billing']['billing_country']['required'] = false;
        }
        if (isset($fields['billing']['billing_state'])) {
            $fields['billing']['billing_state']['type'] = 'hidden';
            $fields['billing']['billing_state']['required'] = false;
        }
        if (isset($fields['billing']['billing_city'])) {
            $fields['billing']['billing_city']['type'] = 'hidden';
            $fields['billing']['billing_city']['required'] = false;
        }
        if (isset($fields['billing']['billing_postcode'])) {
            $fields['billing']['billing_postcode']['type'] = 'hidden';
            $fields['billing']['billing_postcode']['required'] = false;
        }
        
        // Hide shipping fields
        if (isset($fields['shipping']['shipping_country'])) {
            $fields['shipping']['shipping_country']['type'] = 'hidden';
            $fields['shipping']['shipping_country']['default'] = 'ID';
            $fields['shipping']['shipping_country']['required'] = false;
        }
        if (isset($fields['shipping']['shipping_state'])) {
            $fields['shipping']['shipping_state']['type'] = 'hidden';
            $fields['shipping']['shipping_state']['required'] = false;
        }
        if (isset($fields['shipping']['shipping_city'])) {
            $fields['shipping']['shipping_city']['type'] = 'hidden';
            $fields['shipping']['shipping_city']['required'] = false;
        }
        if (isset($fields['shipping']['shipping_postcode'])) {
            $fields['shipping']['shipping_postcode']['type'] = 'hidden';
            $fields['shipping']['shipping_postcode']['required'] = false;
        }
    }
    
    // Destination field definition (reused for billing and shipping)
    $destination_field = [
        'type'            => 'searchable_select',
        'label'           => __('Destination (Province, City, Subdistrict)', 'woonoow'),
        'required'        => $indonesia_only, // Required if Indonesia only
        'priority'        => 85,
        'class'           => ['form-row-wide'],
        'placeholder'     => __('Search destination...', 'woonoow'),
        // WooNooW-specific: API endpoint configuration
        // NOTE: Path is relative to /wp-json/woonoow/v1
        'search_endpoint' => '/rajaongkir/destinations',
        'search_param'    => 'search',
        'min_chars'       => 3,
        // Custom attribute to indicate this is for Indonesia only
        'custom_attributes' => [
            'data-show-for-country' => 'ID',
        ],
    ];
    
    // Add to billing (used when "Ship to different address" is NOT checked)
    $fields['billing']['billing_destination_id'] = $destination_field;
    
    // Add to shipping (used when "Ship to different address" IS checked)
    $fields['shipping']['shipping_destination_id'] = $destination_field;
    
    return $fields;
}, 20); // Priority 20 to run after Rajaongkir's own filter

// ============================================================
// 3. Bridge WooNooW shipping data to Rajaongkir session
//    Sets destination_id in WC session for Rajaongkir to use
// ============================================================
add_action('woonoow/shipping/before_calculate', function($shipping, $items) {
    // Check if Rajaongkir is active
    if (!class_exists('Cekongkir_API')) {
        return;
    }
    
    // For Indonesia-only stores, always set country to ID
    $allowed = WC()->countries->get_allowed_countries();
    $indonesia_only = count($allowed) === 1 && isset($allowed['ID']);
    
    if ($indonesia_only) {
        WC()->customer->set_shipping_country('ID');
        WC()->customer->set_billing_country('ID');
    } elseif (!empty($shipping['country'])) {
        WC()->customer->set_shipping_country($shipping['country']);
        WC()->customer->set_billing_country($shipping['country']);
    }
    
    // Only process Rajaongkir for Indonesia
    $country = $shipping['country'] ?? WC()->customer->get_shipping_country();
    if ($country !== 'ID') {
        // Clear destination for non-Indonesia
        WC()->session->__unset('selected_destination_id');
        WC()->session->__unset('selected_destination_label');
        return;
    }
    
    // Get destination_id from shipping data (various possible keys)
    $destination_id = $shipping['destination_id'] 
                   ?? $shipping['shipping_destination_id']
                   ?? $shipping['billing_destination_id']
                   ?? null;
    
    if (empty($destination_id)) {
        return;
    }
    
    // Set session for Rajaongkir
    WC()->session->set('selected_destination_id', intval($destination_id));
    
    // Also set label if provided
    $label = $shipping['destination_label'] 
          ?? $shipping['shipping_destination_id_label']
          ?? $shipping['billing_destination_id_label']
          ?? '';
    if ($label) {
        WC()->session->set('selected_destination_label', sanitize_text_field($label));
    }
    
    // Clear shipping cache to force recalculation
    WC()->session->set('shipping_for_package_0', false);
    
}, 10, 2);
```

---

## Testing

### 1. Test the API Endpoint

After adding the snippet:
```
GET /wp-json/woonoow/v1/rajaongkir/destinations?search=bandung
```

Should return:
```json
[
  {"value": "1234", "label": "Jawa Barat, Bandung, Kota"},
  ...
]
```

### 2. Test Checkout Flow

1. Add product to cart
2. Go to SPA checkout: `/store/checkout`
3. Set country to Indonesia
4. "Destination" field should appear
5. Type 2+ characters to search
6. Select a destination
7. Rajaongkir rates should appear

---

## Troubleshooting

### API returns empty?

Check `debug.log` for errors:
```php
// Added logging in the search function
error_log('Rajaongkir search error: ...');
```

Common issues:
- Invalid Rajaongkir API key
- Rajaongkir plugin not active
- API quota exceeded

### Field not appearing?

1. Ensure snippet is active
2. Check if store sells to Indonesia
3. Check browser console for JS errors

### Rajaongkir rates not showing?

1. Check session is set:
```php
add_action('woonoow/shipping/before_calculate', function($shipping) {
    error_log('Shipping data: ' . print_r($shipping, true));
}, 5);
```

2. Check Rajaongkir is enabled in shipping zone

---

## Known Limitations

1. **Field visibility**: Currently field always shows for checkout. Future improvement: hide in React when country ≠ ID.

2. **Session timing**: Must select destination before calculating shipping.

---

## Related Documentation

- [SHIPPING_INTEGRATION.md](SHIPPING_INTEGRATION.md) - General shipping patterns
- [HOOKS_REGISTRY.md](HOOKS_REGISTRY.md) - WooNooW hooks reference
