import { QuickBooksClient } from '../clients/quickbooks.js';
import type { Payment, CreditMemo } from '../types/index.js';

export function getTools(client: QuickBooksClient) {
  return [
    {
      name: 'qbo_list_payments',
      description: 'List payments with optional filters',
      inputSchema: {
        type: 'object',
        properties: {
          startPosition: {
            type: 'number',
            description: 'Starting position (1-indexed, default 1)',
          },
          maxResults: {
            type: 'number',
            description: 'Maximum results to return (max 1000, default 100)',
          },
          customerId: {
            type: 'string',
            description: 'Filter by customer ID',
          },
        },
      },
      handler: async (args: any) => {
        const { startPosition = 1, maxResults = 100, customerId } = args;
        
        let query = 'SELECT * FROM Payment';
        if (customerId) {
          query += ` WHERE CustomerRef = '${customerId}'`;
        }
        
        return await client.query<Payment>(query, { startPosition, maxResults });
      },
    },
    {
      name: 'qbo_get_payment',
      description: 'Get a specific payment by ID',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Payment ID',
          },
        },
        required: ['id'],
      },
      handler: async (args: any) => {
        return await client.read<Payment>('Payment', args.id);
      },
    },
    {
      name: 'qbo_create_payment',
      description: 'Create a new payment',
      inputSchema: {
        type: 'object',
        properties: {
          customerId: {
            type: 'string',
            description: 'Customer reference ID',
          },
          totalAmount: {
            type: 'number',
            description: 'Total payment amount',
          },
          txnDate: {
            type: 'string',
            description: 'Transaction date (YYYY-MM-DD)',
          },
          paymentMethodId: {
            type: 'string',
            description: 'Payment method reference ID',
          },
          depositToAccountId: {
            type: 'string',
            description: 'Deposit to account ID',
          },
          linkedInvoices: {
            type: 'array',
            description: 'Invoices to link to this payment',
            items: {
              type: 'object',
              properties: {
                invoiceId: { type: 'string' },
                amount: { type: 'number' },
              },
            },
          },
        },
        required: ['customerId', 'totalAmount'],
      },
      handler: async (args: any) => {
        const payment: any = {
          CustomerRef: { value: args.customerId },
          TotalAmt: args.totalAmount,
        };
        
        if (args.txnDate) payment.TxnDate = args.txnDate;
        if (args.paymentMethodId) payment.PaymentMethodRef = { value: args.paymentMethodId };
        if (args.depositToAccountId) payment.DepositToAccountRef = { value: args.depositToAccountId };
        
        if (args.linkedInvoices && args.linkedInvoices.length > 0) {
          payment.Line = args.linkedInvoices.map((inv: any) => ({
            Amount: inv.amount,
            LinkedTxn: [{
              TxnId: inv.invoiceId,
              TxnType: 'Invoice',
            }],
          }));
        }
        
        return await client.create<Payment>('Payment', payment);
      },
    },
    {
      name: 'qbo_update_payment',
      description: 'Update an existing payment (requires SyncToken)',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Payment ID',
          },
          syncToken: {
            type: 'string',
            description: 'SyncToken from the payment',
          },
          totalAmount: {
            type: 'number',
            description: 'Total payment amount',
          },
          txnDate: {
            type: 'string',
            description: 'Transaction date',
          },
        },
        required: ['id', 'syncToken'],
      },
      handler: async (args: any) => {
        const payment: any = {
          Id: args.id,
          SyncToken: args.syncToken,
        };
        
        if (args.totalAmount !== undefined) payment.TotalAmt = args.totalAmount;
        if (args.txnDate) payment.TxnDate = args.txnDate;
        
        return await client.update<Payment>('Payment', payment);
      },
    },
    {
      name: 'qbo_void_payment',
      description: 'Void a payment (requires SyncToken)',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Payment ID',
          },
          syncToken: {
            type: 'string',
            description: 'SyncToken from the payment',
          },
        },
        required: ['id', 'syncToken'],
      },
      handler: async (args: any) => {
        return await client.delete('Payment', args.id, args.syncToken);
      },
    },
    {
      name: 'qbo_delete_payment',
      description: 'Delete a payment (requires SyncToken)',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Payment ID',
          },
          syncToken: {
            type: 'string',
            description: 'SyncToken from the payment',
          },
        },
        required: ['id', 'syncToken'],
      },
      handler: async (args: any) => {
        return await client.delete('Payment', args.id, args.syncToken);
      },
    },
    {
      name: 'qbo_list_credit_memos',
      description: 'List credit memos with optional filters',
      inputSchema: {
        type: 'object',
        properties: {
          startPosition: {
            type: 'number',
            description: 'Starting position (1-indexed, default 1)',
          },
          maxResults: {
            type: 'number',
            description: 'Maximum results to return (max 1000, default 100)',
          },
          customerId: {
            type: 'string',
            description: 'Filter by customer ID',
          },
        },
      },
      handler: async (args: any) => {
        const { startPosition = 1, maxResults = 100, customerId } = args;
        
        let query = 'SELECT * FROM CreditMemo';
        if (customerId) {
          query += ` WHERE CustomerRef = '${customerId}'`;
        }
        
        return await client.query<CreditMemo>(query, { startPosition, maxResults });
      },
    },
    {
      name: 'qbo_get_credit_memo',
      description: 'Get a specific credit memo by ID',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Credit memo ID',
          },
        },
        required: ['id'],
      },
      handler: async (args: any) => {
        return await client.read<CreditMemo>('CreditMemo', args.id);
      },
    },
    {
      name: 'qbo_create_credit_memo',
      description: 'Create a new credit memo',
      inputSchema: {
        type: 'object',
        properties: {
          customerId: {
            type: 'string',
            description: 'Customer reference ID',
          },
          lines: {
            type: 'array',
            description: 'Credit memo line items',
            items: {
              type: 'object',
              properties: {
                amount: { type: 'number' },
                description: { type: 'string' },
                itemId: { type: 'string' },
                quantity: { type: 'number' },
              },
            },
          },
          txnDate: {
            type: 'string',
            description: 'Transaction date (YYYY-MM-DD)',
          },
        },
        required: ['customerId', 'lines'],
      },
      handler: async (args: any) => {
        const creditMemo: any = {
          CustomerRef: { value: args.customerId },
          Line: args.lines.map((line: any) => ({
            Amount: line.amount,
            DetailType: 'SalesItemLineDetail',
            Description: line.description,
            SalesItemLineDetail: {
              ItemRef: { value: line.itemId },
              Qty: line.quantity,
            },
          })),
        };
        
        if (args.txnDate) creditMemo.TxnDate = args.txnDate;
        
        return await client.create<CreditMemo>('CreditMemo', creditMemo);
      },
    },
  ];
}
