import { z } from 'zod';
import { StripeClient } from '../clients/stripe.js';
import { Customer, StripeList } 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_customers',
      description: 'List all customers with optional filtering and pagination',
      inputSchema: z.object({
        limit: z.number().min(1).max(100).optional().describe('Number of customers to return (1-100)'),
        starting_after: z.string().optional().describe('Cursor for pagination - ID of the last customer from previous page'),
        ending_before: z.string().optional().describe('Cursor for pagination - ID of the first customer from previous page'),
        email: z.string().optional().describe('Filter by customer email'),
        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<Customer>('/customers', args);
      }
    },
    {
      name: 'stripe_get_customer',
      description: 'Retrieve a specific customer by ID',
      inputSchema: z.object({
        customer_id: z.string().describe('The ID of the customer to retrieve'),
        expand: z.array(z.string()).optional().describe('Fields to expand (e.g., ["default_source", "subscriptions"])')
      }),
      handler: async (client: StripeClient, args: any) => {
        const { customer_id, expand } = args;
        const params = expand ? { expand } : undefined;
        return await client.retrieve<Customer>('/customers', customer_id, params);
      }
    },
    {
      name: 'stripe_create_customer',
      description: 'Create a new customer',
      inputSchema: z.object({
        email: z.string().optional().describe('Customer email address'),
        name: z.string().optional().describe('Customer full name'),
        phone: z.string().optional().describe('Customer phone number'),
        description: z.string().optional().describe('Arbitrary description'),
        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().describe('Customer mailing address'),
        metadata: metadataSchema,
        payment_method: z.string().optional().describe('ID of payment method to attach'),
        invoice_settings: z.object({
          default_payment_method: z.string().optional()
        }).optional(),
        shipping: z.object({
          name: z.string(),
          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().describe('Shipping information'),
        balance: z.number().optional().describe('Account balance in cents (can be negative)'),
        preferred_locales: z.array(z.string()).optional().describe('Preferred languages (e.g., ["en", "fr"])'),
      }),
      handler: async (client: StripeClient, args: any) => {
        return await client.create<Customer>('/customers', args, {
          idempotencyKey: client.generateIdempotencyKey()
        });
      }
    },
    {
      name: 'stripe_update_customer',
      description: 'Update an existing customer',
      inputSchema: z.object({
        customer_id: z.string().describe('The ID of the customer to update'),
        email: z.string().optional(),
        name: z.string().optional(),
        phone: z.string().optional(),
        description: 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(),
        metadata: metadataSchema,
        default_source: z.string().optional().describe('ID of payment source to set as default'),
        invoice_settings: z.object({
          default_payment_method: z.string().optional()
        }).optional(),
        shipping: z.object({
          name: z.string(),
          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(),
        balance: z.number().optional(),
        preferred_locales: z.array(z.string()).optional(),
      }),
      handler: async (client: StripeClient, args: any) => {
        const { customer_id, ...data } = args;
        return await client.update<Customer>('/customers', customer_id, data);
      }
    },
    {
      name: 'stripe_delete_customer',
      description: 'Delete a customer permanently',
      inputSchema: z.object({
        customer_id: z.string().describe('The ID of the customer to delete')
      }),
      handler: async (client: StripeClient, args: any) => {
        return await client.remove('/customers', args.customer_id);
      }
    },
    {
      name: 'stripe_search_customers',
      description: 'Search for customers using Stripe\'s search query syntax',
      inputSchema: z.object({
        query: z.string().describe('Search query (e.g., "email:\'customer@example.com\'" or "name:\'John\'")'),
        limit: z.number().min(1).max(100).optional().describe('Number of results to return (1-100)'),
        page: z.string().optional().describe('Pagination token from previous search')
      }),
      handler: async (client: StripeClient, args: any) => {
        return await client.get<StripeList<Customer>>('/customers/search', args);
      }
    }
  ];
