import { z } from 'zod';
import { StripeClient } from '../clients/stripe.js';
import { PaymentMethod } 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_methods',
    description: 'List payment methods for a customer',
    inputSchema: z.object({
      customer: z.string().describe('Customer ID'),
      type: z.enum(['card', 'us_bank_account', 'sepa_debit', 'link']).optional().describe('Payment method type to filter by'),
      limit: z.number().min(1).max(100).optional().describe('Number of payment methods to return (1-100)'),
      starting_after: z.string().optional().describe('Cursor for pagination'),
      ending_before: z.string().optional().describe('Cursor for pagination'),
    }),
    handler: async (client: StripeClient, args: any) => {
      return await client.list<PaymentMethod>('/payment_methods', args);
    }
  },
  {
    name: 'stripe_get_payment_method',
    description: 'Retrieve a specific payment method by ID',
    inputSchema: z.object({
      payment_method_id: z.string().describe('The ID of the payment method to retrieve'),
      expand: z.array(z.string()).optional().describe('Fields to expand (e.g., ["customer"])')
    }),
    handler: async (client: StripeClient, args: any) => {
      const { payment_method_id, expand } = args;
      const params = expand ? { expand } : undefined;
      return await client.retrieve<PaymentMethod>('/payment_methods', payment_method_id, params);
    }
  },
  {
    name: 'stripe_create_payment_method',
    description: 'Create a new payment method',
    inputSchema: z.object({
      type: z.enum(['card', 'us_bank_account', 'sepa_debit']).describe('Payment method type'),
      card: z.object({
        number: z.string().optional().describe('Card number'),
        exp_month: z.number().min(1).max(12).optional().describe('Expiration month'),
        exp_year: z.number().optional().describe('Expiration year'),
        cvc: z.string().optional().describe('Card CVC'),
        token: z.string().optional().describe('Card token from Stripe.js')
      }).optional().describe('Card details (use token in production)'),
      billing_details: z.object({
        name: z.string().optional(),
        email: z.string().optional(),
        phone: z.string().optional(),
        address: z.object({
          line1: z.string().optional(),
          line2: z.string().optional(),
          city: z.string().optional(),
          state: z.string().optional(),
          postal_code: z.string().optional(),
          country: z.string().optional()
        }).optional()
      }).optional().describe('Billing details'),
      metadata: metadataSchema
    }),
    handler: async (client: StripeClient, args: any) => {
      return await client.create<PaymentMethod>('/payment_methods', args, {
        idempotencyKey: client.generateIdempotencyKey()
      });
    }
  },
  {
    name: 'stripe_update_payment_method',
    description: 'Update a payment method',
    inputSchema: z.object({
      payment_method_id: z.string().describe('The ID of the payment method to update'),
      billing_details: z.object({
        name: z.string().optional(),
        email: z.string().optional(),
        phone: z.string().optional(),
        address: z.object({
          line1: z.string().optional(),
          line2: z.string().optional(),
          city: z.string().optional(),
          state: z.string().optional(),
          postal_code: z.string().optional(),
          country: z.string().optional()
        }).optional()
      }).optional(),
      card: z.object({
        exp_month: z.number().min(1).max(12).optional(),
        exp_year: z.number().optional()
      }).optional().describe('Update card expiration'),
      metadata: metadataSchema
    }),
    handler: async (client: StripeClient, args: any) => {
      const { payment_method_id, ...data } = args;
      return await client.update<PaymentMethod>('/payment_methods', payment_method_id, data);
    }
  },
  {
    name: 'stripe_attach_payment_method',
    description: 'Attach a payment method to a customer',
    inputSchema: z.object({
      payment_method_id: z.string().describe('The ID of the payment method to attach'),
      customer: z.string().describe('Customer ID to attach to')
    }),
    handler: async (client: StripeClient, args: any) => {
      const { payment_method_id, customer } = args;
      return await client.post<PaymentMethod>(`/payment_methods/${payment_method_id}/attach`, { customer });
    }
  },
  {
    name: 'stripe_detach_payment_method',
    description: 'Detach a payment method from a customer',
    inputSchema: z.object({
      payment_method_id: z.string().describe('The ID of the payment method to detach')
    }),
    handler: async (client: StripeClient, args: any) => {
      return await client.post<PaymentMethod>(`/payment_methods/${args.payment_method_id}/detach`, {});
    }
  }
];
