import { z } from 'zod';
import { StripeClient } from '../clients/stripe.js';
import { Product, 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_products',
    description: 'List all products with optional filtering and pagination',
    inputSchema: z.object({
      limit: z.number().min(1).max(100).optional().describe('Number of products to return (1-100)'),
      starting_after: z.string().optional().describe('Cursor for pagination'),
      ending_before: z.string().optional().describe('Cursor for pagination'),
      active: z.boolean().optional().describe('Filter by active status'),
      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'),
      ids: z.array(z.string()).optional().describe('Filter by product IDs'),
      shippable: z.boolean().optional().describe('Filter by shippable status'),
      type: z.enum(['service', 'good']).optional().describe('Filter by product type'),
      url: z.string().optional().describe('Filter by product URL')
    }),
    handler: async (client: StripeClient, args: any) => {
      return await client.list<Product>('/products', args);
    }
  },
  {
    name: 'stripe_get_product',
    description: 'Retrieve a specific product by ID',
    inputSchema: z.object({
      product_id: z.string().describe('The ID of the product to retrieve'),
      expand: z.array(z.string()).optional().describe('Fields to expand (e.g., ["default_price"])')
    }),
    handler: async (client: StripeClient, args: any) => {
      const { product_id, expand } = args;
      const params = expand ? { expand } : undefined;
      return await client.retrieve<Product>('/products', product_id, params);
    }
  },
  {
    name: 'stripe_create_product',
    description: 'Create a new product',
    inputSchema: z.object({
      name: z.string().describe('Product name'),
      active: z.boolean().optional().describe('Whether product is active (default true)'),
      description: z.string().optional().describe('Product description'),
      metadata: metadataSchema,
      default_price_data: z.object({
        currency: z.string(),
        unit_amount: z.number().optional().describe('Amount in cents'),
        recurring: z.object({
          interval: z.enum(['day', 'week', 'month', 'year']),
          interval_count: z.number().optional()
        }).optional()
      }).optional().describe('Create a default price inline'),
      images: z.array(z.string()).optional().describe('Array of image URLs (max 8)'),
      package_dimensions: z.object({
        height: z.number(),
        length: z.number(),
        weight: z.number(),
        width: z.number()
      }).optional().describe('Package dimensions for shipping'),
      shippable: z.boolean().optional().describe('Whether product can be shipped'),
      statement_descriptor: z.string().max(22).optional().describe('Statement descriptor'),
      tax_code: z.string().optional().describe('Tax code for automatic tax'),
      type: z.enum(['service', 'good']).optional().describe('Product type (default: service)'),
      unit_label: z.string().optional().describe('Label for units (e.g., "per seat")'),
      url: z.string().optional().describe('Product URL')
    }),
    handler: async (client: StripeClient, args: any) => {
      return await client.create<Product>('/products', args, {
        idempotencyKey: client.generateIdempotencyKey()
      });
    }
  },
  {
    name: 'stripe_update_product',
    description: 'Update an existing product',
    inputSchema: z.object({
      product_id: z.string().describe('The ID of the product to update'),
      name: z.string().optional(),
      active: z.boolean().optional(),
      description: z.string().optional(),
      metadata: metadataSchema,
      default_price: z.string().optional().describe('Set new default price ID'),
      images: z.array(z.string()).optional(),
      package_dimensions: z.object({
        height: z.number(),
        length: z.number(),
        weight: z.number(),
        width: z.number()
      }).optional(),
      shippable: z.boolean().optional(),
      statement_descriptor: z.string().max(22).optional(),
      tax_code: z.string().optional(),
      unit_label: z.string().optional(),
      url: z.string().optional()
    }),
    handler: async (client: StripeClient, args: any) => {
      const { product_id, ...data } = args;
      return await client.update<Product>('/products', product_id, data);
    }
  },
  {
    name: 'stripe_delete_product',
    description: 'Delete a product (permanently removes it)',
    inputSchema: z.object({
      product_id: z.string().describe('The ID of the product to delete')
    }),
    handler: async (client: StripeClient, args: any) => {
      return await client.remove('/products', args.product_id);
    }
  },
  {
    name: 'stripe_search_products',
    description: 'Search for products using Stripe\'s search query syntax',
    inputSchema: z.object({
      query: z.string().describe('Search query (e.g., "active:\'true\' AND name~\'premium\'" or "metadata[\'key\']:\'value\'")'),
      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<Product>>('/products/search', args);
    }
  }
];
