import { CloverClient } from '../clients/clover.js';
import {
  CloverOrder,
  CloverPayment,
  SalesSummary,
  RevenueByItem,
  RevenueByCategory,
  EmployeePerformance,
} from '../types/index.js';

export function createReportsTools(client: CloverClient) {
  return {
    clover_sales_summary: {
      description: 'Get sales summary report for a date range',
      inputSchema: {
        type: 'object',
        properties: {
          startDate: {
            type: 'number',
            description: 'Start date (Unix timestamp in milliseconds)',
          },
          endDate: {
            type: 'number',
            description: 'End date (Unix timestamp in milliseconds)',
          },
        },
        required: ['startDate', 'endDate'],
      },
      handler: async (args: any) => {
        // Fetch orders and payments in date range
        const orders = await client.fetchPaginated<CloverOrder>('/orders', {
          filter: `createdTime>=${args.startDate} AND createdTime<=${args.endDate}`,
          expand: 'lineItems',
        });

        const payments = await client.fetchPaginated<CloverPayment>('/payments', {
          filter: `createdTime>=${args.startDate} AND createdTime<=${args.endDate}`,
        });

        const totalSales = payments
          .filter((p) => p.result === 'SUCCESS')
          .reduce((sum, p) => sum + p.amount, 0);

        const totalRefunds = payments
          .filter((p) => p.refunds && p.refunds.length > 0)
          .reduce(
            (sum, p) =>
              sum + p.refunds!.reduce((rsum, r) => rsum + r.amount, 0),
            0
          );

        const totalTax = payments
          .filter((p) => p.result === 'SUCCESS')
          .reduce((sum, p) => sum + (p.taxAmount || 0), 0);

        const totalTips = payments
          .filter((p) => p.result === 'SUCCESS')
          .reduce((sum, p) => sum + (p.tipAmount || 0), 0);

        const summary: SalesSummary = {
          totalSales,
          totalOrders: orders.length,
          averageOrderValue: orders.length > 0 ? totalSales / orders.length : 0,
          totalRefunds,
          netSales: totalSales - totalRefunds,
          totalTax,
          totalTips,
        };

        return summary;
      },
    },

    clover_revenue_by_item: {
      description: 'Get revenue breakdown by item for a date range',
      inputSchema: {
        type: 'object',
        properties: {
          startDate: {
            type: 'number',
            description: 'Start date (Unix timestamp in milliseconds)',
          },
          endDate: {
            type: 'number',
            description: 'End date (Unix timestamp in milliseconds)',
          },
        },
        required: ['startDate', 'endDate'],
      },
      handler: async (args: any) => {
        const orders = await client.fetchPaginated<CloverOrder>('/orders', {
          filter: `createdTime>=${args.startDate} AND createdTime<=${args.endDate}`,
          expand: 'lineItems',
        });

        const itemStats = new Map<
          string,
          { name: string; quantity: number; revenue: number }
        >();

        orders.forEach((order) => {
          order.lineItems?.forEach((lineItem) => {
            const itemId = lineItem.item.id;
            const existing = itemStats.get(itemId) || {
              name: lineItem.name,
              quantity: 0,
              revenue: 0,
            };

            existing.quantity += lineItem.unitQty || 1;
            existing.revenue += lineItem.price * (lineItem.unitQty || 1);
            itemStats.set(itemId, existing);
          });
        });

        const results: RevenueByItem[] = Array.from(itemStats.entries()).map(
          ([itemId, stats]) => ({
            itemId,
            itemName: stats.name,
            quantitySold: stats.quantity,
            totalRevenue: stats.revenue,
            averagePrice: stats.revenue / stats.quantity,
          })
        );

        return { items: results, count: results.length };
      },
    },

    clover_revenue_by_category: {
      description: 'Get revenue breakdown by category for a date range',
      inputSchema: {
        type: 'object',
        properties: {
          startDate: {
            type: 'number',
            description: 'Start date (Unix timestamp in milliseconds)',
          },
          endDate: {
            type: 'number',
            description: 'End date (Unix timestamp in milliseconds)',
          },
        },
        required: ['startDate', 'endDate'],
      },
      handler: async (args: any) => {
        // Fetch items with categories
        const items = await client.fetchPaginated('/items', {
          expand: 'categories',
        });

        const orders = await client.fetchPaginated<CloverOrder>('/orders', {
          filter: `createdTime>=${args.startDate} AND createdTime<=${args.endDate}`,
          expand: 'lineItems',
        });

        // Build item-to-category map
        const itemCategories = new Map<string, any[]>();
        items.forEach((item: any) => {
          if (item.categories) {
            itemCategories.set(item.id, item.categories);
          }
        });

        const categoryStats = new Map<
          string,
          { name: string; itemCount: Set<string>; revenue: number }
        >();

        orders.forEach((order) => {
          order.lineItems?.forEach((lineItem) => {
            const categories = itemCategories.get(lineItem.item.id) || [];
            categories.forEach((cat: any) => {
              const existing = categoryStats.get(cat.id) || {
                name: cat.name,
                itemCount: new Set<string>(),
                revenue: 0,
              };

              existing.itemCount.add(lineItem.item.id);
              existing.revenue += lineItem.price * (lineItem.unitQty || 1);
              categoryStats.set(cat.id, existing);
            });
          });
        });

        const results: RevenueByCategory[] = Array.from(
          categoryStats.entries()
        ).map(([categoryId, stats]) => ({
          categoryId,
          categoryName: stats.name,
          itemCount: stats.itemCount.size,
          totalRevenue: stats.revenue,
        }));

        return { categories: results, count: results.length };
      },
    },

    clover_employee_performance: {
      description: 'Get employee performance report for a date range',
      inputSchema: {
        type: 'object',
        properties: {
          startDate: {
            type: 'number',
            description: 'Start date (Unix timestamp in milliseconds)',
          },
          endDate: {
            type: 'number',
            description: 'End date (Unix timestamp in milliseconds)',
          },
        },
        required: ['startDate', 'endDate'],
      },
      handler: async (args: any) => {
        const payments = await client.fetchPaginated<CloverPayment>('/payments', {
          filter: `createdTime>=${args.startDate} AND createdTime<=${args.endDate}`,
          expand: 'employee',
        });

        const employeeStats = new Map<
          string,
          { name: string; sales: number; orderCount: number }
        >();

        payments
          .filter((p) => p.result === 'SUCCESS')
          .forEach((payment) => {
            const empId = payment.employee.id;
            const existing = employeeStats.get(empId) || {
              name: (payment.employee as any).name || 'Unknown',
              sales: 0,
              orderCount: 0,
            };

            existing.sales += payment.amount;
            existing.orderCount += 1;
            employeeStats.set(empId, existing);
          });

        const results: EmployeePerformance[] = Array.from(
          employeeStats.entries()
        ).map(([employeeId, stats]) => ({
          employeeId,
          employeeName: stats.name,
          totalSales: stats.sales,
          orderCount: stats.orderCount,
          averageOrderValue: stats.sales / stats.orderCount,
        }));

        return { employees: results, count: results.length };
      },
    },
  };
}
