import { z } from 'zod';
import { StripeClient } from '../clients/stripe.js';
import { Subscription, SubscriptionItem } from '../types/index.js';

const metadataSchema = z.record(z.string()).optional().describe('Set of key-value pairs for storing additional information');

export default [
  {
    name: 'stripe_list_subscriptions',
    description: 'List all subscriptions with optional filtering and pagination',
    inputSchema: z.object({
      limit: z.number().min(1).max(100).optional().describe('Number of subscriptions to return (1-100)'),
      starting_after: z.string().optional().describe('Cursor for pagination'),
      ending_before: z.string().optional().describe('Cursor for pagination'),
      customer: z.string().optional().describe('Filter by customer ID'),
      price: z.string().optional().describe('Filter by price ID'),
      status: z.enum(['incomplete', 'incomplete_expired', 'trialing', 'active', 'past_due', 'canceled', 'unpaid', 'paused']).optional(),
      created: z.union([
        z.number(),
        z.object({
          gt: z.number().optional(),
          gte: z.number().optional(),
          lt: z.number().optional(),
          lte: z.number().optional(),
        })
      ]).optional().describe('Filter by creation timestamp or range'),
    }),
    handler: async (client: StripeClient, args: any) => {
      return await client.list<Subscription>('/subscriptions', args);
    }
  },
  {
    name: 'stripe_get_subscription',
    description: 'Retrieve a specific subscription by ID',
    inputSchema: z.object({
      subscription_id: z.string().describe('The ID of the subscription to retrieve'),
      expand: z.array(z.string()).optional().describe('Fields to expand (e.g., ["customer", "default_payment_method"])')
    }),
    handler: async (client: StripeClient, args: any) => {
      const { subscription_id, expand } = args;
      const params = expand ? { expand } : undefined;
      return await client.retrieve<Subscription>('/subscriptions', subscription_id, params);
    }
  },
  {
    name: 'stripe_create_subscription',
    description: 'Create a new subscription',
    inputSchema: z.object({
      customer: z.string().describe('Customer ID'),
      items: z.array(z.object({
        price: z.string().describe('Price ID'),
        quantity: z.number().optional().describe('Quantity (default 1)')
      })).describe('Subscription items (products/prices)'),
      default_payment_method: z.string().optional().describe('Payment method ID to use'),
      collection_method: z.enum(['charge_automatically', 'send_invoice']).optional().describe('How to collect payment (default: charge_automatically)'),
      days_until_due: z.number().optional().describe('Days until invoice due (for send_invoice collection)'),
      description: z.string().optional(),
      metadata: metadataSchema,
      cancel_at_period_end: z.boolean().optional().describe('Cancel at the end of the current period'),
      trial_period_days: z.number().optional().describe('Number of trial days'),
      trial_end: z.number().optional().describe('Unix timestamp for trial end (overrides trial_period_days)'),
      backdate_start_date: z.number().optional().describe('Unix timestamp to backdate subscription start'),
      billing_cycle_anchor: z.number().optional().describe('Unix timestamp for billing cycle anchor'),
      proration_behavior: z.enum(['create_prorations', 'none', 'always_invoice']).optional(),
      payment_settings: z.object({
        save_default_payment_method: z.enum(['on_subscription', 'off']).optional(),
        payment_method_types: z.array(z.string()).optional()
      }).optional(),
      off_session: z.boolean().optional().describe('Whether payment is happening off-session'),
      promotion_code: z.string().optional().describe('Promotion code ID to apply'),
      automatic_tax: z.object({
        enabled: z.boolean()
      }).optional().describe('Enable automatic tax calculation')
    }),
    handler: async (client: StripeClient, args: any) => {
      return await client.create<Subscription>('/subscriptions', args, {
        idempotencyKey: client.generateIdempotencyKey()
      });
    }
  },
  {
    name: 'stripe_update_subscription',
    description: 'Update a subscription',
    inputSchema: z.object({
      subscription_id: z.string().describe('The ID of the subscription to update'),
      items: z.array(z.object({
        id: z.string().optional().describe('Subscription item ID to update'),
        price: z.string().optional().describe('New price ID'),
        quantity: z.number().optional(),
        deleted: z.boolean().optional().describe('Set to true to remove item')
      })).optional().describe('Update subscription items'),
      default_payment_method: z.string().optional(),
      description: z.string().optional(),
      metadata: metadataSchema,
      cancel_at_period_end: z.boolean().optional(),
      trial_end: z.number().optional(),
      proration_behavior: z.enum(['create_prorations', 'none', 'always_invoice']).optional(),
      billing_cycle_anchor: z.enum(['now', 'unchanged']).optional(),
      pause_collection: z.object({
        behavior: z.enum(['keep_as_draft', 'mark_uncollectible', 'void']),
        resumes_at: z.number().optional()
      }).optional().describe('Pause the subscription'),
      promotion_code: z.string().optional(),
      payment_settings: z.object({
        save_default_payment_method: z.enum(['on_subscription', 'off']).optional(),
        payment_method_types: z.array(z.string()).optional()
      }).optional()
    }),
    handler: async (client: StripeClient, args: any) => {
      const { subscription_id, ...data } = args;
      return await client.update<Subscription>('/subscriptions', subscription_id, data);
    }
  },
  {
    name: 'stripe_cancel_subscription',
    description: 'Cancel a subscription',
    inputSchema: z.object({
      subscription_id: z.string().describe('The ID of the subscription to cancel'),
      cancel_at_period_end: z.boolean().optional().describe('Cancel at end of period (default false = immediate)'),
      prorate: z.boolean().optional().describe('Whether to prorate (default true)'),
      invoice_now: z.boolean().optional().describe('Whether to invoice immediately (default false)')
    }),
    handler: async (client: StripeClient, args: any) => {
      const { subscription_id, cancel_at_period_end, ...params } = args;
      
      if (cancel_at_period_end) {
        // Update to cancel at period end
        return await client.update<Subscription>('/subscriptions', subscription_id, { cancel_at_period_end: true });
      } else {
        // Immediate cancellation
        return await client.delete<Subscription>(`/subscriptions/${subscription_id}`, params);
      }
    }
  },
  {
    name: 'stripe_resume_subscription',
    description: 'Resume a paused subscription',
    inputSchema: z.object({
      subscription_id: z.string().describe('The ID of the subscription to resume'),
      proration_behavior: z.enum(['create_prorations', 'none', 'always_invoice']).optional()
    }),
    handler: async (client: StripeClient, args: any) => {
      const { subscription_id, ...data } = args;
      return await client.update<Subscription>('/subscriptions', subscription_id, {
        ...data,
        pause_collection: null as any  // Remove pause
      });
    }
  },
  {
    name: 'stripe_list_subscription_items',
    description: 'List all items for a subscription',
    inputSchema: z.object({
      subscription: z.string().describe('Subscription ID'),
      limit: z.number().min(1).max(100).optional().describe('Number of items to return (1-100)'),
      starting_after: z.string().optional(),
      ending_before: z.string().optional()
    }),
    handler: async (client: StripeClient, args: any) => {
      return await client.list<SubscriptionItem>('/subscription_items', args);
    }
  }
];
