# Shipping Addon Integration Research

## Problem Statement
Indonesian shipping plugins (Biteship, Woongkir, etc.) have complex requirements:
1. **Origin address** - configured in wp-admin
2. **Subdistrict field** - custom checkout field
3. **Real-time API calls** - during cart/checkout
4. **Custom field injection** - modify checkout form

**Question:** How can WooNooW SPA accommodate these plugins without breaking their functionality?

---

## How WooCommerce Shipping Addons Work

### Standard WooCommerce Pattern
```php
class My_Shipping_Method extends WC_Shipping_Method {
    public function calculate_shipping($package = array()) {
        // 1. Get settings from $this->get_option()
        // 2. Calculate rates based on package
        // 3. Call $this->add_rate($rate)
    }
}
```

**Key Points:**
- ✅ Extends `WC_Shipping_Method`
- ✅ Uses WooCommerce hooks: `woocommerce_shipping_init`, `woocommerce_shipping_methods`
- ✅ Settings stored in `wp_options` table
- ✅ Rates calculated during `calculate_shipping()`

---

## Indonesian Shipping Plugins (Biteship, Woongkir, etc.)

### How They Differ from Standard Plugins

#### 1. **Custom Checkout Fields**
```php
// They add custom fields to checkout
add_filter('woocommerce_checkout_fields', function($fields) {
    $fields['billing']['billing_subdistrict'] = array(
        'type' => 'select',
        'label' => 'Subdistrict',
        'required' => true,
        'options' => get_subdistricts() // API call
    );
    return $fields;
});
```

#### 2. **Origin Configuration**
- Stored in plugin settings (wp-admin)
- Used for API calls to calculate distance/cost
- Not exposed in standard WooCommerce shipping settings

#### 3. **Real-time API Calls**
```php
public function calculate_shipping($package) {
    // Get origin from plugin settings
    $origin = get_option('biteship_origin_subdistrict_id');
    
    // Get destination from checkout field
    $destination = $package['destination']['subdistrict_id'];
    
    // Call external API
    $rates = biteship_api_get_rates($origin, $destination, $weight);
    
    foreach ($rates as $rate) {
        $this->add_rate($rate);
    }
}
```

#### 4. **AJAX Updates**
```javascript
// Update shipping when subdistrict changes
jQuery('#billing_subdistrict').on('change', function() {
    jQuery('body').trigger('update_checkout');
});
```

---

## Why Indonesian Plugins Are Complex

### 1. **Geographic Complexity**
- Indonesia has **34 provinces**, **514 cities**, **7,000+ subdistricts**
- Shipping cost varies by subdistrict (not just city)
- Standard WooCommerce only has: Country → State → City → Postcode

### 2. **Multiple Couriers**
- Each courier has different rates per subdistrict
- Real-time API calls required (can't pre-calculate)
- Some couriers don't serve all subdistricts

### 3. **Origin-Destination Pairing**
- Cost depends on **origin subdistrict** + **destination subdistrict**
- Origin must be configured in admin
- Destination selected at checkout

---

## How WooNooW SPA Should Handle This

### ✅ **What WooNooW SHOULD Do**

#### 1. **Display Methods Correctly**
```typescript
// Our current approach is CORRECT
const { data: zones } = useQuery({
    queryKey: ['shipping-zones'],
    queryFn: () => api.get('/settings/shipping/zones')
});
```
- ✅ Fetch zones from WooCommerce API
- ✅ Display all methods (including Biteship, Woongkir)
- ✅ Show enable/disable toggle
- ✅ Link to WooCommerce settings for advanced config

#### 2. **Expose Basic Settings Only**
```typescript
// Show only common settings
- Display Name (title)
- Cost (if applicable)
- Min Amount (if applicable)
```
- ✅ Don't try to show ALL settings
- ✅ Complex settings → "Edit in WooCommerce" button

#### 3. **Respect Plugin Behavior**
- ✅ Don't interfere with checkout field injection
- ✅ Don't modify `calculate_shipping()` logic
- ✅ Let plugins handle their own API calls

---

### ❌ **What WooNooW SHOULD NOT Do**

#### 1. **Don't Try to Manage Custom Fields**
```typescript
// ❌ DON'T DO THIS
const subdistrictField = {
    type: 'select',
    options: await fetchSubdistricts()
};
```
- ❌ Subdistrict fields are managed by shipping plugins
- ❌ They inject fields via WooCommerce hooks
- ❌ WooNooW SPA doesn't control checkout page

#### 2. **Don't Try to Calculate Rates**
```typescript
// ❌ DON'T DO THIS
const rate = await biteshipAPI.getRates(origin, destination);
```
- ❌ Rate calculation is plugin-specific
- ❌ Requires API keys, origin config, etc.
- ❌ Should happen during checkout, not in admin

#### 3. **Don't Try to Show All Settings**
```typescript
// ❌ DON'T DO THIS
<Input label="Origin Subdistrict ID" />
<Input label="API Key" />
<Input label="Courier Selection" />
```
- ❌ Too complex for simplified UI
- ❌ Each plugin has different settings
- ❌ Better to link to WooCommerce settings

---

## Comparison: Global vs Indonesian Shipping

### Global Shipping Plugins (ShipStation, EasyPost, etc.)

**Characteristics:**
- ✅ Standard address fields (Country, State, City, Postcode)
- ✅ Pre-calculated rates or simple API calls
- ✅ No custom checkout fields needed
- ✅ Settings fit in standard WooCommerce UI

**Example: Flat Rate**
```php
public function calculate_shipping($package) {
    $rate = array(
        'label' => $this->title,
        'cost' => $this->get_option('cost')
    );
    $this->add_rate($rate);
}
```

### Indonesian Shipping Plugins (Biteship, Woongkir, etc.)

**Characteristics:**
- ⚠️ Custom address fields (Province, City, District, **Subdistrict**)
- ⚠️ Real-time API calls with origin-destination pairing
- ⚠️ Custom checkout field injection
- ⚠️ Complex settings (API keys, origin config, courier selection)

**Example: Biteship**
```php
public function calculate_shipping($package) {
    $origin_id = get_option('biteship_origin_subdistrict_id');
    $dest_id = $package['destination']['subdistrict_id'];
    
    $response = wp_remote_post('https://api.biteship.com/v1/rates', array(
        'headers' => array('Authorization' => 'Bearer ' . $api_key),
        'body' => json_encode(array(
            'origin_area_id' => $origin_id,
            'destination_area_id' => $dest_id,
            'couriers' => $this->get_option('couriers'),
            'items' => $package['contents']
        ))
    ));
    
    $rates = json_decode($response['body'])->pricing;
    foreach ($rates as $rate) {
        $this->add_rate(array(
            'label' => $rate->courier_name . ' - ' . $rate->courier_service_name,
            'cost' => $rate->price
        ));
    }
}
```

---

## Recommendations for WooNooW SPA

### ✅ **Current Approach is CORRECT**

Our simplified UI is perfect for:
1. **Standard shipping methods** (Flat Rate, Free Shipping, Local Pickup)
2. **Simple third-party plugins** (basic rate calculators)
3. **Non-tech users** who just want to enable/disable methods

### ✅ **For Complex Plugins (Biteship, Woongkir)**

**Strategy: "View-Only + Link to WooCommerce"**

```typescript
// In the accordion, show:
<AccordionItem>
  <AccordionTrigger>
    🚚 Biteship - JNE REG [On]
    Rp 15,000 (calculated at checkout)
  </AccordionTrigger>
  <AccordionContent>
    <Alert>
      This is a complex shipping method with advanced settings.
      <Button asChild>
        <a href={wcAdminUrl + '/admin.php?page=biteship-settings'}>
          Configure in WooCommerce
        </a>
      </Button>
    </Alert>
    
    {/* Only show basic toggle */}
    <ToggleField 
      label="Enable/Disable"
      value={method.enabled}
      onChange={handleToggle}
    />
  </AccordionContent>
</AccordionItem>
```

### ✅ **Detection Logic**

```typescript
// Detect if method is complex
const isComplexMethod = (method: ShippingMethod) => {
  const complexPlugins = [
    'biteship',
    'woongkir',
    'anteraja',
    'shipper',
    // Add more as needed
  ];
  
  return complexPlugins.some(plugin => 
    method.id.includes(plugin)
  );
};

// Render accordingly
{isComplexMethod(method) ? (
  <ComplexMethodView method={method} />
) : (
  <SimpleMethodView method={method} />
)}
```

---

## Testing Strategy

### ✅ **What to Test in WooNooW SPA**

1. **Method Display**
   - ✅ Biteship methods appear in zone list
   - ✅ Enable/disable toggle works
   - ✅ Method name displays correctly

2. **Settings Link**
   - ✅ "Edit in WooCommerce" button works
   - ✅ Opens correct settings page

3. **Don't Break Checkout**
   - ✅ Subdistrict field still appears
   - ✅ Rates calculate correctly
   - ✅ AJAX updates work

### ❌ **What NOT to Test in WooNooW SPA**

1. ❌ Rate calculation accuracy
2. ❌ API integration
3. ❌ Subdistrict field functionality
4. ❌ Origin configuration

**These are the shipping plugin's responsibility!**

---

## Conclusion

### **WooNooW SPA's Role:**
✅ **Simplified management** for standard shipping methods  
✅ **View-only + link** for complex plugins  
✅ **Don't interfere** with plugin functionality  

### **Shipping Plugin's Role:**
✅ Handle complex settings (origin, API keys, etc.)  
✅ Inject custom checkout fields  
✅ Calculate rates via API  
✅ Manage courier selection  

### **Result:**
✅ Non-tech users can enable/disable methods easily  
✅ Complex configuration stays in WooCommerce admin  
✅ No functionality is lost  
✅ Best of both worlds! 🎯

---

## Implementation Plan

### Phase 1: Detection (Current)
- [x] Display all methods from WooCommerce API
- [x] Show enable/disable toggle
- [x] Show basic settings (title, cost, min_amount)

### Phase 2: Complex Method Handling (Next)
- [ ] Detect complex shipping plugins
- [ ] Show different UI for complex methods
- [ ] Add "Configure in WooCommerce" button
- [ ] Hide settings form for complex methods

### Phase 3: Documentation (Final)
- [ ] Add help text explaining complex methods
- [ ] Link to plugin documentation
- [ ] Add troubleshooting guide

---

**Last Updated:** Nov 9, 2025  
**Status:** Research Complete ✅
