collab: Add support for extended Zed Pro trial (#29612)

Marshall Bowers created

This PR adds support for an extended Zed Pro trial, applied based on the
presence of the `agent-extended-trial` feature flag.

Release Notes:

- N/A

Change summary

crates/collab/src/api/billing.rs    |  3 +++
crates/collab/src/stripe_billing.rs | 24 +++++++++++++++++++++++-
2 files changed, 26 insertions(+), 1 deletion(-)

Detailed changes

crates/collab/src/api/billing.rs 🔗

@@ -380,11 +380,14 @@ async fn create_billing_subscription(
                 }
             }
 
+            let feature_flags = app.db.get_user_flags(user.id).await?;
+
             stripe_billing
                 .checkout_with_zed_pro_trial(
                     app.config.zed_pro_price_id()?,
                     customer_id,
                     &user.github_login,
+                    feature_flags,
                     &success_url,
                 )
                 .await?

crates/collab/src/stripe_billing.rs 🔗

@@ -489,16 +489,38 @@ impl StripeBilling {
         zed_pro_price_id: PriceId,
         customer_id: stripe::CustomerId,
         github_login: &str,
+        feature_flags: Vec<String>,
         success_url: &str,
     ) -> Result<String> {
+        const AGENT_EXTENDED_TRIAL_FEATURE_FLAG: &str = "agent-extended-trial";
+
+        let eligible_for_extended_trial = feature_flags
+            .iter()
+            .any(|flag| flag == AGENT_EXTENDED_TRIAL_FEATURE_FLAG);
+
+        let trial_period_days = if eligible_for_extended_trial { 60 } else { 14 };
+
+        let mut subscription_metadata = std::collections::HashMap::new();
+        if eligible_for_extended_trial {
+            subscription_metadata.insert(
+                "promo_feature_flag".to_string(),
+                AGENT_EXTENDED_TRIAL_FEATURE_FLAG.to_string(),
+            );
+        }
+
         let mut params = stripe::CreateCheckoutSession::new();
         params.subscription_data = Some(stripe::CreateCheckoutSessionSubscriptionData {
-            trial_period_days: Some(14),
+            trial_period_days: Some(trial_period_days),
             trial_settings: Some(stripe::CreateCheckoutSessionSubscriptionDataTrialSettings {
                 end_behavior: stripe::CreateCheckoutSessionSubscriptionDataTrialSettingsEndBehavior {
                     missing_payment_method: stripe::CreateCheckoutSessionSubscriptionDataTrialSettingsEndBehaviorMissingPaymentMethod::Pause,
                 }
             }),
+            metadata: if !subscription_metadata.is_empty() {
+                Some(subscription_metadata)
+            } else {
+                None
+            },
             ..Default::default()
         });
         params.mode = Some(stripe::CheckoutSessionMode::Subscription);