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

export function getTools(client: QuickBooksClient) {
  return [
    {
      name: 'qbo_list_estimates',
      description: 'List estimates 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 Estimate';
        if (customerId) {
          query += ` WHERE CustomerRef = '${customerId}'`;
        }
        
        return await client.query<Estimate>(query, { startPosition, maxResults });
      },
    },
    {
      name: 'qbo_get_estimate',
      description: 'Get a specific estimate by ID',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Estimate ID',
          },
        },
        required: ['id'],
      },
      handler: async (args: any) => {
        return await client.read<Estimate>('Estimate', args.id);
      },
    },
    {
      name: 'qbo_create_estimate',
      description: 'Create a new estimate',
      inputSchema: {
        type: 'object',
        properties: {
          customerId: {
            type: 'string',
            description: 'Customer reference ID',
          },
          lines: {
            type: 'array',
            description: 'Estimate line items',
            items: {
              type: 'object',
              properties: {
                amount: { type: 'number' },
                description: { type: 'string' },
                itemId: { type: 'string' },
                quantity: { type: 'number' },
                unitPrice: { type: 'number' },
              },
            },
          },
          txnDate: {
            type: 'string',
            description: 'Transaction date (YYYY-MM-DD)',
          },
          expirationDate: {
            type: 'string',
            description: 'Expiration date (YYYY-MM-DD)',
          },
        },
        required: ['customerId', 'lines'],
      },
      handler: async (args: any) => {
        const estimate: 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,
              UnitPrice: line.unitPrice,
            },
          })),
        };
        
        if (args.txnDate) estimate.TxnDate = args.txnDate;
        if (args.expirationDate) estimate.ExpirationDate = args.expirationDate;
        
        return await client.create<Estimate>('Estimate', estimate);
      },
    },
    {
      name: 'qbo_update_estimate',
      description: 'Update an existing estimate (requires SyncToken)',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Estimate ID',
          },
          syncToken: {
            type: 'string',
            description: 'SyncToken from the estimate',
          },
          lines: {
            type: 'array',
            description: 'Updated line items',
          },
          expirationDate: {
            type: 'string',
            description: 'Expiration date (YYYY-MM-DD)',
          },
        },
        required: ['id', 'syncToken'],
      },
      handler: async (args: any) => {
        const estimate: any = {
          Id: args.id,
          SyncToken: args.syncToken,
        };
        
        if (args.lines) estimate.Line = args.lines;
        if (args.expirationDate) estimate.ExpirationDate = args.expirationDate;
        
        return await client.update<Estimate>('Estimate', estimate);
      },
    },
    {
      name: 'qbo_delete_estimate',
      description: 'Delete an estimate (requires SyncToken)',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Estimate ID',
          },
          syncToken: {
            type: 'string',
            description: 'SyncToken from the estimate',
          },
        },
        required: ['id', 'syncToken'],
      },
      handler: async (args: any) => {
        return await client.delete('Estimate', args.id, args.syncToken);
      },
    },
    {
      name: 'qbo_send_estimate',
      description: 'Send an estimate via email',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Estimate ID',
          },
          email: {
            type: 'string',
            description: 'Email address to send to (optional)',
          },
        },
        required: ['id'],
      },
      handler: async (args: any) => {
        const endpoint = `estimate/${args.id}/send${args.email ? `?sendTo=${args.email}` : ''}`;
        return await client.getReport('SendInvoice', { id: args.id });
      },
    },
    {
      name: 'qbo_list_sales_receipts',
      description: 'List sales receipts 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 SalesReceipt';
        if (customerId) {
          query += ` WHERE CustomerRef = '${customerId}'`;
        }
        
        return await client.query<SalesReceipt>(query, { startPosition, maxResults });
      },
    },
    {
      name: 'qbo_get_sales_receipt',
      description: 'Get a specific sales receipt by ID',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Sales receipt ID',
          },
        },
        required: ['id'],
      },
      handler: async (args: any) => {
        return await client.read<SalesReceipt>('SalesReceipt', args.id);
      },
    },
    {
      name: 'qbo_create_sales_receipt',
      description: 'Create a new sales receipt',
      inputSchema: {
        type: 'object',
        properties: {
          customerId: {
            type: 'string',
            description: 'Customer reference ID',
          },
          lines: {
            type: 'array',
            description: 'Sales receipt 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)',
          },
          paymentMethodId: {
            type: 'string',
            description: 'Payment method reference ID',
          },
          depositToAccountId: {
            type: 'string',
            description: 'Deposit to account ID',
          },
        },
        required: ['customerId', 'lines'],
      },
      handler: async (args: any) => {
        const salesReceipt: 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) salesReceipt.TxnDate = args.txnDate;
        if (args.paymentMethodId) salesReceipt.PaymentMethodRef = { value: args.paymentMethodId };
        if (args.depositToAccountId) salesReceipt.DepositToAccountRef = { value: args.depositToAccountId };
        
        return await client.create<SalesReceipt>('SalesReceipt', salesReceipt);
      },
    },
    {
      name: 'qbo_delete_sales_receipt',
      description: 'Delete a sales receipt (requires SyncToken)',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Sales receipt ID',
          },
          syncToken: {
            type: 'string',
            description: 'SyncToken from the sales receipt',
          },
        },
        required: ['id', 'syncToken'],
      },
      handler: async (args: any) => {
        return await client.delete('SalesReceipt', args.id, args.syncToken);
      },
    },
  ];
}
