import { z } from 'zod';
import { StripeClient } from '../clients/stripe.js';
import { Charge } 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_charges',
    description: 'List all charges with optional filtering and pagination',
    inputSchema: z.object({
      limit: z.number().min(1).max(100).optional().describe('Number of charges 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'),
      payment_intent: z.string().optional().describe('Filter by payment intent 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<Charge>('/charges', args);
    }
  },
  {
    name: 'stripe_get_charge',
    description: 'Retrieve a specific charge by ID',
    inputSchema: z.object({
      charge_id: z.string().describe('The ID of the charge to retrieve'),
      expand: z.array(z.string()).optional().describe('Fields to expand (e.g., ["customer", "invoice"])')
    }),
    handler: async (client: StripeClient, args: any) => {
      const { charge_id, expand } = args;
      const params = expand ? { expand } : undefined;
      return await client.retrieve<Charge>('/charges', charge_id, params);
    }
  },
  {
    name: 'stripe_create_charge',
    description: 'Create a new charge (direct charge, not recommended - use Payment Intents instead)',
    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")'),
      source: z.string().optional().describe('Payment source ID (card token, source, or payment method)'),
      customer: z.string().optional().describe('Customer ID'),
      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().describe('Suffix for statement descriptor'),
      receipt_email: z.string().optional().describe('Email to send receipt to'),
      capture: z.boolean().optional().describe('Whether to capture immediately (default true)'),
      on_behalf_of: z.string().optional().describe('Connected account ID'),
      application_fee_amount: z.number().optional().describe('Application fee in cents')
    }),
    handler: async (client: StripeClient, args: any) => {
      return await client.create<Charge>('/charges', args, {
        idempotencyKey: client.generateIdempotencyKey()
      });
    }
  },
  {
    name: 'stripe_update_charge',
    description: 'Update a charge (limited fields can be updated)',
    inputSchema: z.object({
      charge_id: z.string().describe('The ID of the charge to update'),
      description: z.string().optional(),
      metadata: metadataSchema,
      receipt_email: z.string().optional(),
      fraud_details: z.object({
        user_report: z.enum(['fraudulent', 'safe']).optional()
      }).optional().describe('Fraud details'),
      shipping: z.object({
        name: z.string(),
        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()
        }),
        carrier: z.string().optional(),
        phone: z.string().optional(),
        tracking_number: z.string().optional()
      }).optional()
    }),
    handler: async (client: StripeClient, args: any) => {
      const { charge_id, ...data } = args;
      return await client.update<Charge>('/charges', charge_id, data);
    }
  },
  {
    name: 'stripe_capture_charge',
    description: 'Capture a previously uncaptured charge',
    inputSchema: z.object({
      charge_id: z.string().describe('The ID of the charge to capture'),
      amount: z.number().optional().describe('Amount to capture in cents (defaults to full authorized amount)'),
      receipt_email: z.string().optional().describe('Email to send receipt to'),
      statement_descriptor: z.string().max(22).optional(),
      statement_descriptor_suffix: z.string().max(22).optional()
    }),
    handler: async (client: StripeClient, args: any) => {
      const { charge_id, ...data } = args;
      return await client.post<Charge>(`/charges/${charge_id}/capture`, data);
    }
  }
];
