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

export function getTools(client: QuickBooksClient) {
  return [
    {
      name: 'qbo_list_bills',
      description: 'List bills 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)',
          },
          vendorId: {
            type: 'string',
            description: 'Filter by vendor ID',
          },
          minAmount: {
            type: 'number',
            description: 'Minimum total amount',
          },
        },
      },
      handler: async (args: any) => {
        const { startPosition = 1, maxResults = 100, vendorId, minAmount } = args;
        
        let query = 'SELECT * FROM Bill';
        const conditions: string[] = [];
        
        if (vendorId) conditions.push(`VendorRef = '${vendorId}'`);
        if (minAmount !== undefined) conditions.push(`TotalAmt >= '${minAmount}'`);
        
        if (conditions.length > 0) {
          query += ' WHERE ' + conditions.join(' AND ');
        }
        
        return await client.query<Bill>(query, { startPosition, maxResults });
      },
    },
    {
      name: 'qbo_get_bill',
      description: 'Get a specific bill by ID',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Bill ID',
          },
        },
        required: ['id'],
      },
      handler: async (args: any) => {
        return await client.read<Bill>('Bill', args.id);
      },
    },
    {
      name: 'qbo_create_bill',
      description: 'Create a new bill',
      inputSchema: {
        type: 'object',
        properties: {
          vendorId: {
            type: 'string',
            description: 'Vendor reference ID',
          },
          lines: {
            type: 'array',
            description: 'Bill line items',
            items: {
              type: 'object',
              properties: {
                amount: { type: 'number' },
                description: { type: 'string' },
                accountId: { type: 'string' },
                itemId: { type: 'string' },
              },
            },
          },
          dueDate: {
            type: 'string',
            description: 'Due date (YYYY-MM-DD)',
          },
          txnDate: {
            type: 'string',
            description: 'Transaction date (YYYY-MM-DD)',
          },
        },
        required: ['vendorId', 'lines'],
      },
      handler: async (args: any) => {
        const bill: any = {
          VendorRef: { value: args.vendorId },
          Line: args.lines.map((line: any) => ({
            Amount: line.amount,
            DetailType: line.itemId ? 'ItemBasedExpenseLineDetail' : 'AccountBasedExpenseLineDetail',
            Description: line.description,
            ...(line.itemId
              ? { ItemBasedExpenseLineDetail: { ItemRef: { value: line.itemId } } }
              : { AccountBasedExpenseLineDetail: { AccountRef: { value: line.accountId } } }
            ),
          })),
        };
        
        if (args.dueDate) bill.DueDate = args.dueDate;
        if (args.txnDate) bill.TxnDate = args.txnDate;
        
        return await client.create<Bill>('Bill', bill);
      },
    },
    {
      name: 'qbo_update_bill',
      description: 'Update an existing bill (requires SyncToken)',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Bill ID',
          },
          syncToken: {
            type: 'string',
            description: 'SyncToken from the bill',
          },
          lines: {
            type: 'array',
            description: 'Updated line items',
          },
          dueDate: {
            type: 'string',
            description: 'Due date (YYYY-MM-DD)',
          },
        },
        required: ['id', 'syncToken'],
      },
      handler: async (args: any) => {
        const bill: any = {
          Id: args.id,
          SyncToken: args.syncToken,
        };
        
        if (args.lines) bill.Line = args.lines;
        if (args.dueDate) bill.DueDate = args.dueDate;
        
        return await client.update<Bill>('Bill', bill);
      },
    },
    {
      name: 'qbo_delete_bill',
      description: 'Delete a bill (requires SyncToken)',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Bill ID',
          },
          syncToken: {
            type: 'string',
            description: 'SyncToken from the bill',
          },
        },
        required: ['id', 'syncToken'],
      },
      handler: async (args: any) => {
        return await client.delete('Bill', args.id, args.syncToken);
      },
    },
    {
      name: 'qbo_list_bill_payments',
      description: 'List bill 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)',
          },
          vendorId: {
            type: 'string',
            description: 'Filter by vendor ID',
          },
        },
      },
      handler: async (args: any) => {
        const { startPosition = 1, maxResults = 100, vendorId } = args;
        
        let query = 'SELECT * FROM BillPayment';
        if (vendorId) {
          query += ` WHERE VendorRef = '${vendorId}'`;
        }
        
        return await client.query<BillPayment>(query, { startPosition, maxResults });
      },
    },
    {
      name: 'qbo_get_bill_payment',
      description: 'Get a specific bill payment by ID',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Bill payment ID',
          },
        },
        required: ['id'],
      },
      handler: async (args: any) => {
        return await client.read<BillPayment>('BillPayment', args.id);
      },
    },
    {
      name: 'qbo_create_bill_payment',
      description: 'Create a new bill payment',
      inputSchema: {
        type: 'object',
        properties: {
          vendorId: {
            type: 'string',
            description: 'Vendor reference ID',
          },
          totalAmount: {
            type: 'number',
            description: 'Total payment amount',
          },
          txnDate: {
            type: 'string',
            description: 'Transaction date (YYYY-MM-DD)',
          },
          paymentAccountId: {
            type: 'string',
            description: 'Payment account ID (bank/credit card)',
          },
          linkedBills: {
            type: 'array',
            description: 'Bills to link to this payment',
            items: {
              type: 'object',
              properties: {
                billId: { type: 'string' },
                amount: { type: 'number' },
              },
            },
          },
        },
        required: ['vendorId', 'totalAmount', 'paymentAccountId'],
      },
      handler: async (args: any) => {
        const billPayment: any = {
          VendorRef: { value: args.vendorId },
          TotalAmt: args.totalAmount,
          APAccountRef: { value: args.paymentAccountId },
        };
        
        if (args.txnDate) billPayment.TxnDate = args.txnDate;
        
        if (args.linkedBills && args.linkedBills.length > 0) {
          billPayment.Line = args.linkedBills.map((bill: any) => ({
            Amount: bill.amount,
            LinkedTxn: [{
              TxnId: bill.billId,
              TxnType: 'Bill',
            }],
          }));
        }
        
        return await client.create<BillPayment>('BillPayment', billPayment);
      },
    },
    {
      name: 'qbo_delete_bill_payment',
      description: 'Delete a bill payment (requires SyncToken)',
      inputSchema: {
        type: 'object',
        properties: {
          id: {
            type: 'string',
            description: 'Bill payment ID',
          },
          syncToken: {
            type: 'string',
            description: 'SyncToken from the bill payment',
          },
        },
        required: ['id', 'syncToken'],
      },
      handler: async (args: any) => {
        return await client.delete('BillPayment', args.id, args.syncToken);
      },
    },
  ];
}
