import { QuickBooksClient } from '../clients/quickbooks.js';
import type { Invoice } from '../types/index.js';

export function getTools(client: QuickBooksClient) {
  return [
    {
      name: 'qbo_list_invoices',
      description: 'List invoices with optional filters. Returns paginated results.',
      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',
          },
          minAmount: {
            type: 'number',
            description: 'Minimum total amount',
          },
          maxAmount: {
            type: 'number',
            description: 'Maximum total amount',
          },
        },
      },
      handler: async (args: any) => {
        const { startPosition = 1, maxResults = 100, customerId, minAmount, maxAmount } = args;
        
        let query = 'SELECT * FROM Invoice';
        const conditions: string[] = [];
        
        if (customerId) conditions.push(`CustomerRef = '${customerId}'`);
        if (minAmount !== undefined) conditions.push(`TotalAmt >= '${minAmount}'`);
        if (maxAmount !== undefined) conditions.push(`TotalAmt <= '${maxAmount}'`);
        
        if (conditions.length > 0) {
          query += ' WHERE ' + conditions.join(' AND ');
        }
        
        return await client.query<Invoice>(query, { startPosition, maxResults });
      },
    },
    {
      name: 'qbo_get_invoice',
      description: 'Get a specific invoice by ID',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Invoice ID',
          },
        },
        required: ['id'],
      },
      handler: async (args: any) => {
        return await client.read<Invoice>('Invoice', args.id);
      },
    },
    {
      name: 'qbo_create_invoice',
      description: 'Create a new invoice',
      inputSchema: {
        type: 'object',
        properties: {
          customerId: {
            type: 'string',
            description: 'Customer reference ID',
          },
          lines: {
            type: 'array',
            description: 'Invoice line items',
            items: {
              type: 'object',
              properties: {
                amount: { type: 'number' },
                description: { type: 'string' },
                itemId: { type: 'string' },
                quantity: { type: 'number' },
                unitPrice: { type: 'number' },
              },
            },
          },
          dueDate: {
            type: 'string',
            description: 'Due date (YYYY-MM-DD)',
          },
          txnDate: {
            type: 'string',
            description: 'Transaction date (YYYY-MM-DD)',
          },
          emailStatus: {
            type: 'string',
            description: 'Email status (NotSet, NeedToSend, EmailSent)',
          },
          billEmail: {
            type: 'string',
            description: 'Customer email for billing',
          },
        },
        required: ['customerId', 'lines'],
      },
      handler: async (args: any) => {
        const invoice: Partial<Invoice> = {
          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.dueDate) invoice.DueDate = args.dueDate;
        if (args.txnDate) invoice.TxnDate = args.txnDate;
        if (args.emailStatus) invoice.EmailStatus = args.emailStatus;
        if (args.billEmail) invoice.BillEmail = { Address: args.billEmail };
        
        return await client.create<Invoice>('Invoice', invoice);
      },
    },
    {
      name: 'qbo_update_invoice',
      description: 'Update an existing invoice (requires SyncToken)',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Invoice ID',
          },
          syncToken: {
            type: 'string',
            description: 'SyncToken from the invoice (for optimistic locking)',
          },
          customerId: {
            type: 'string',
            description: 'Customer reference ID',
          },
          lines: {
            type: 'array',
            description: 'Invoice line items',
          },
          dueDate: {
            type: 'string',
            description: 'Due date (YYYY-MM-DD)',
          },
          emailStatus: {
            type: 'string',
            description: 'Email status',
          },
        },
        required: ['id', 'syncToken'],
      },
      handler: async (args: any) => {
        const invoice: any = {
          Id: args.id,
          SyncToken: args.syncToken,
        };
        
        if (args.customerId) invoice.CustomerRef = { value: args.customerId };
        if (args.lines) invoice.Line = args.lines;
        if (args.dueDate) invoice.DueDate = args.dueDate;
        if (args.emailStatus) invoice.EmailStatus = args.emailStatus;
        
        return await client.update<Invoice>('Invoice', invoice);
      },
    },
    {
      name: 'qbo_void_invoice',
      description: 'Void an invoice (requires SyncToken)',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Invoice ID',
          },
          syncToken: {
            type: 'string',
            description: 'SyncToken from the invoice',
          },
        },
        required: ['id', 'syncToken'],
      },
      handler: async (args: any) => {
        return await client.delete('Invoice', args.id, args.syncToken);
      },
    },
    {
      name: 'qbo_delete_invoice',
      description: 'Delete an invoice (requires SyncToken)',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Invoice ID',
          },
          syncToken: {
            type: 'string',
            description: 'SyncToken from the invoice',
          },
        },
        required: ['id', 'syncToken'],
      },
      handler: async (args: any) => {
        return await client.delete('Invoice', args.id, args.syncToken);
      },
    },
    {
      name: 'qbo_query_invoices',
      description: 'Run a custom SQL-like query on invoices',
      inputSchema: {
        type: 'object',
        properties: {
          query: {
            type: 'string',
            description: 'SQL-like query (e.g., "SELECT * FROM Invoice WHERE TotalAmt > \'100.00\'")',
          },
          startPosition: {
            type: 'number',
            description: 'Starting position (default 1)',
          },
          maxResults: {
            type: 'number',
            description: 'Maximum results (default 100)',
          },
        },
        required: ['query'],
      },
      handler: async (args: any) => {
        return await client.query<Invoice>(args.query, {
          startPosition: args.startPosition || 1,
          maxResults: args.maxResults || 100,
        });
      },
    },
  ];
}
