# Dodo Payments Plan Change & Cancellation Fix

## Summary

Fixed the subscription management system to properly handle plan changes and cancellations using the correct Dodo Payments API endpoints.

## Issues Fixed

### 1. **Paid-to-Paid Plan Changes**
- **Problem**: When users switched between paid plans (e.g., Starter → Professional), the app was creating a new checkout session instead of using Dodo's Change Plan API
- **Solution**: Implemented `changeDodoSubscriptionPlan()` function that uses `POST /subscriptions/{subscription_id}/change-plan` with `difference_immediately` proration mode
- **Behavior**: 
  - Upgrades: Charges the price difference for the current billing period
  - Downgrades: Applies remaining value as credit to future renewals
  - No service interruption during the change

### 2. **Paid-to-Free Downgrades**
- **Problem**: Downgrading to the free "Hobby" plan wasn't properly cancelling the Dodo subscription
- **Solution**: Enhanced the logic to call `cancelDodoSubscription()` when switching from a paid plan to hobby
- **Behavior**: Subscription is cancelled with Dodo, user downgraded to free tier immediately

### 3. **Cancel Button**
- **Problem**: Cancel button was calling general account update endpoint which may not have properly cancelled the Dodo subscription
- **Solution**: Already uses dedicated `/api/subscription/cancel` endpoint which properly calls `cancelDodoSubscription()`
- **Behavior**: Cancels subscription at Dodo and marks billing status as cancelled

## Technical Implementation

### Server-Side Changes (`server.js`)

#### 1. New Function: `changeDodoSubscriptionPlan()`
```javascript
async function changeDodoSubscriptionPlan(user, newPlan, billingCycle, currency)
```
- Uses Dodo's official Change Plan API endpoint
- Handles proration automatically
- Proper error handling and logging
- Updates subscription product while maintaining continuity

#### 2. Updated: `handleAccountSettingsUpdate()`
Enhanced to handle three scenarios:
- **Paid → Paid**: Calls `changeDodoSubscriptionPlan()` with Dodo API
- **Paid → Free**: Calls `cancelDodoSubscription()` and downgrades to hobby
- **Free → Paid**: Returns error requiring checkout flow (correct behavior)

### Frontend Changes (`settings.html`)

#### Updated: `saveAccount()` Function
Completely restructured to handle different plan change scenarios:

1. **Paid-to-Paid Changes**: 
   - Calls `/api/account` which uses Change Plan API
   - Shows appropriate confirmation with proration explanation
   - Immediate update without checkout

2. **Paid-to-Free Downgrades**:
   - Warns user about feature loss
   - Cancels subscription via `/api/account`
   - Immediate downgrade

3. **Free-to-Paid Upgrades**:
   - Redirects to checkout flow (correct)
   - Uses `/api/subscription/checkout`

4. **Other Settings**:
   - Simple account updates (email, currency)

## Dodo Payments API Integration

### Change Plan API
**Endpoint**: `POST /subscriptions/{subscription_id}/change-plan`

**Request Body**:
```json
{
  "product_id": "prod_xxx",
  "quantity": 1,
  "proration_billing_mode": "difference_immediately"
}
```

**Proration Mode**: `difference_immediately`
- **Upgrades**: Immediate charge for price difference
- **Downgrades**: Credit applied to subscription for future renewals
- **Benefits**: Simple, fair billing without complex proration calculations

### Cancel Subscription API
**Endpoints Used**:
1. `DELETE /subscriptions/{subscription_id}` (immediate cancellation)
2. `PATCH /subscriptions/{subscription_id}` with `cancel_at_next_billing_date: true` (fallback)

The implementation tries immediate cancellation first, then falls back to end-of-period cancellation if needed.

## User Experience Improvements

### Clear Messaging
- Upgrade messages explain immediate charges
- Downgrade messages explain credit application
- Free plan changes warn about feature loss

### Seamless Transitions
- Paid-to-paid changes happen instantly without checkout
- No service interruption during plan changes
- Proper proration handled by Dodo

### Confirmation Dialogs
- All plan changes require explicit confirmation
- Different messages for upgrades vs downgrades
- Warning icons for cancellations and downgrades

## Testing Checklist

- [ ] **Upgrade** (Starter → Professional): Verify immediate charge for difference
- [ ] **Downgrade** (Professional → Starter): Verify credit applied to account
- [ ] **Cancel** (any paid → hobby): Verify Dodo subscription cancelled
- [ ] **Free to Paid** (hobby → starter): Verify checkout flow triggered
- [ ] **Cancel Button**: Verify subscription cancelled at Dodo
- [ ] **Webhook Handling**: Verify `subscription.plan_changed` webhook updates user plan

## Environment Variables Required

All existing Dodo environment variables remain the same:
- `DODO_PAYMENTS_API_KEY`
- `DODO_PAYMENTS_ENV` (test/live)
- Subscription product IDs for each plan/cycle/currency combination

## API Endpoints Modified

### `POST /api/account`
Now handles three plan change scenarios differently:
1. Paid→Paid: Uses Change Plan API
2. Paid→Free: Cancels subscription
3. Free→Paid: Returns error requiring checkout

### `POST /api/subscription/cancel`
Already working correctly - cancels Dodo subscription properly

## Webhook Events

The system now properly responds to:
- `subscription.plan_changed`: Confirms plan change succeeded
- `subscription.canceled`: Confirms cancellation
- `payment.succeeded`: Confirms upgrade payment
- `subscription.on_hold`: Handles failed plan change payments

## Documentation References

- [Dodo Subscription Upgrade & Downgrade Guide](https://docs.dodopayments.com/developer-resources/subscription-upgrade-downgrade)
- [Change Plan API Reference](https://docs.dodopayments.com/api-reference/subscriptions/change-plan)
- [Update Subscription API](https://docs.dodopayments.com/api-reference/subscriptions/patch-subscriptions)

## Notes

- The `difference_immediately` proration mode is ideal for most SaaS applications
- Credits from downgrades are automatically applied by Dodo to future renewals
- The Change Plan API uses existing payment method - no new payment collection needed
- All plan changes are logged for audit purposes
