import { z } from 'zod';
import { StripeClient } from '../clients/stripe.js';
import { PaymentIntent } 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_payment_intents',
    description: 'List all payment intents with optional filtering and pagination',
    inputSchema: z.object({
      limit: z.number().min(1).max(100).optional().describe('Number of payment intents 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'),
      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<PaymentIntent>('/payment_intents', args);
    }
  },
  {
    name: 'stripe_get_payment_intent',
    description: 'Retrieve a specific payment intent by ID',
    inputSchema: z.object({
      payment_intent_id: z.string().describe('The ID of the payment intent to retrieve'),
      expand: z.array(z.string()).optional().describe('Fields to expand (e.g., ["customer", "payment_method"])')
    }),
    handler: async (client: StripeClient, args: any) => {
      const { payment_intent_id, expand } = args;
      const params = expand ? { expand } : undefined;
      return await client.retrieve<PaymentIntent>('/payment_intents', payment_intent_id, params);
    }
  },
  {
    name: 'stripe_create_payment_intent',
    description: 'Create a new payment intent',
    inputSchema: z.object({
      amount: z.number().positive().describe('Amount in cents (e.g., 1000 = $10.00)'),
      currency: z.string().describe('Three-letter ISO currency code (e.g., "usd")'),
      customer: z.string().optional().describe('Customer ID'),
      payment_method: z.string().optional().describe('Payment method ID'),
      payment_method_types: z.array(z.string()).optional().describe('Payment method types to accept (e.g., ["card"])'),
      description: z.string().optional().describe('Arbitrary description'),
      metadata: metadataSchema,
      statement_descriptor: z.string().max(22).optional().describe('Statement descriptor (max 22 chars)'),
      statement_descriptor_suffix: z.string().max(22).optional(),
      receipt_email: z.string().optional().describe('Email to send receipt to'),
      capture_method: z.enum(['automatic', 'manual']).optional().describe('When to capture funds (default: automatic)'),
      confirmation_method: z.enum(['automatic', 'manual']).optional().describe('How to confirm (default: automatic)'),
      confirm: z.boolean().optional().describe('Whether to confirm immediately'),
      setup_future_usage: z.enum(['on_session', 'off_session']).optional().describe('Save for future use'),
      automatic_payment_methods: z.object({
        enabled: z.boolean()
      }).optional().describe('Enable automatic payment methods'),
      on_behalf_of: z.string().optional().describe('Connected account ID'),
      application_fee_amount: z.number().optional().describe('Application fee in cents'),
      transfer_data: z.object({
        destination: z.string(),
        amount: z.number().optional()
      }).optional().describe('Transfer to connected account'),
      return_url: z.string().optional().describe('URL to redirect customer after payment (for certain payment methods)')
    }),
    handler: async (client: StripeClient, args: any) => {
      return await client.create<PaymentIntent>('/payment_intents', args, {
        idempotencyKey: client.generateIdempotencyKey()
      });
    }
  },
  {
    name: 'stripe_update_payment_intent',
    description: 'Update a payment intent',
    inputSchema: z.object({
      payment_intent_id: z.string().describe('The ID of the payment intent to update'),
      amount: z.number().positive().optional().describe('Amount in cents'),
      currency: z.string().optional(),
      customer: z.string().optional(),
      payment_method: z.string().optional(),
      description: z.string().optional(),
      metadata: metadataSchema,
      statement_descriptor: z.string().max(22).optional(),
      statement_descriptor_suffix: z.string().max(22).optional(),
      receipt_email: z.string().optional(),
      setup_future_usage: z.enum(['on_session', 'off_session']).optional(),
      payment_method_types: z.array(z.string()).optional()
    }),
    handler: async (client: StripeClient, args: any) => {
      const { payment_intent_id, ...data } = args;
      return await client.update<PaymentIntent>('/payment_intents', payment_intent_id, data);
    }
  },
  {
    name: 'stripe_confirm_payment_intent',
    description: 'Confirm a payment intent',
    inputSchema: z.object({
      payment_intent_id: z.string().describe('The ID of the payment intent to confirm'),
      payment_method: z.string().optional().describe('Payment method ID to use'),
      return_url: z.string().optional().describe('URL to redirect customer after payment'),
      receipt_email: z.string().optional()
    }),
    handler: async (client: StripeClient, args: any) => {
      const { payment_intent_id, ...data } = args;
      return await client.post<PaymentIntent>(`/payment_intents/${payment_intent_id}/confirm`, data);
    }
  },
  {
    name: 'stripe_cancel_payment_intent',
    description: 'Cancel a payment intent',
    inputSchema: z.object({
      payment_intent_id: z.string().describe('The ID of the payment intent to cancel'),
      cancellation_reason: z.enum(['duplicate', 'fraudulent', 'requested_by_customer', 'abandoned']).optional()
    }),
    handler: async (client: StripeClient, args: any) => {
      const { payment_intent_id, ...data } = args;
      return await client.post<PaymentIntent>(`/payment_intents/${payment_intent_id}/cancel`, data);
    }
  },
  {
    name: 'stripe_capture_payment_intent',
    description: 'Capture a payment intent (for manual capture)',
    inputSchema: z.object({
      payment_intent_id: z.string().describe('The ID of the payment intent to capture'),
      amount_to_capture: z.number().optional().describe('Amount to capture in cents (defaults to full authorized amount)')
    }),
    handler: async (client: StripeClient, args: any) => {
      const { payment_intent_id, ...data } = args;
      return await client.post<PaymentIntent>(`/payment_intents/${payment_intent_id}/capture`, data);
    }
  }
];
