import { requireSalesOrAdmin } from '@/server/utils/auth';
import { logAuditEvent } from '@/server/utils/audit-logger';
import { getExpenseById } from '@/server/utils/nocodb';
import { processExpenseWithCurrency } from '@/server/utils/currency';
import { uploadBuffer } from '@/server/utils/minio';
import type { Expense } from '@/utils/types';

export default defineEventHandler(async (event) => {
  await requireSalesOrAdmin(event);
  
  const body = await readBody(event);
  const { expenseIds } = body;
  
  if (!expenseIds || !Array.isArray(expenseIds) || expenseIds.length === 0) {
    throw createError({
      statusCode: 400,
      statusMessage: 'Expense IDs are required'
    });
  }
  
  console.log('[expenses/export-csv] Generating CSV for expenses:', expenseIds);
  
  try {
    // Get user info for file naming
    const userInfo = event.context.user;
    const userName = userInfo?.preferred_username || userInfo?.email || 'user';
    
    // Fetch all expenses
    const expenses: Expense[] = [];
    const failedExpenses: string[] = [];
    
    for (const id of expenseIds) {
      try {
        const expense = await getExpenseById(id.toString());
        const processedExpense = await processExpenseWithCurrency(expense);
        expenses.push(processedExpense);
      } catch (error) {
        console.error(`[expenses/export-csv] Failed to fetch expense ${id}:`, error);
        failedExpenses.push(id.toString());
      }
    }
    
    if (failedExpenses.length > 0) {
      throw createError({
        statusCode: 400,
        statusMessage: `Failed to fetch expenses: ${failedExpenses.join(', ')}`
      });
    }
    
    if (expenses.length === 0) {
      throw createError({
        statusCode: 404,
        statusMessage: 'No expenses found'
      });
    }
    
    // Sort expenses by date
    expenses.sort((a, b) => new Date(a.Time).getTime() - new Date(b.Time).getTime());
    
    // Calculate totals
    const subtotalEUR = expenses.reduce((sum, expense) => {
      if (expense.currency === 'EUR') {
        return sum + (expense.PriceNumber || 0);
      } else {
        // Convert to EUR (assuming PriceNumber is in original currency and we have EUR conversion)
        return sum + (expense.PriceNumber || 0) / (expense.ConversionRate || 1);
      }
    }, 0);
    
    const processingFee = subtotalEUR * 0.05;
    const totalWithFee = subtotalEUR + processingFee;
    
    // Generate CSV content
    const csvHeaders = [
      'Date',
      'Time',
      'Establishment',
      'Category',
      'Payment Method',
      'Payer',
      'Amount (EUR)',
      'Original Amount',
      'Currency',
      'Conversion Rate',
      'Description',
      'Receipt Count',
      'Paid Status'
    ];
    
    const csvRows = expenses.map(expense => [
      new Date(expense.Time).toLocaleDateString(),
      new Date(expense.Time).toLocaleTimeString(),
      `"${(expense['Establishment Name'] || '').replace(/"/g, '""')}"`,
      expense.Category || '',
      expense['Payment Method'] || '',
      expense.Payer || '',
      expense.currency === 'EUR' ? 
        (expense.PriceNumber || 0).toFixed(2) :
        ((expense.PriceNumber || 0) / (expense.ConversionRate || 1)).toFixed(2),
      (expense.PriceNumber || 0).toFixed(2),
      expense.currency || '',
      expense.ConversionRate || 1,
      `"${(expense.Contents || '').replace(/"/g, '""')}"`,
      expense.Receipt?.length || 0,
      expense.Paid ? 'Yes' : 'No'
    ]);
    
    // Add summary rows
    csvRows.push([]);
    csvRows.push(['SUMMARY']);
    csvRows.push(['Subtotal (EUR)', '', '', '', '', '', subtotalEUR.toFixed(2)]);
    csvRows.push(['Processing Fee (5%)', '', '', '', '', '', processingFee.toFixed(2)]);
    csvRows.push(['Total with Fee (EUR)', '', '', '', '', '', totalWithFee.toFixed(2)]);
    
    const csvContent = [
      csvHeaders.join(','),
      ...csvRows.map(row => row.join(','))
    ].join('\n');
    
    // Generate filename with date range
    const dates = expenses.map(e => new Date(e.Time));
    const startDate = new Date(Math.min(...dates.map(d => d.getTime())));
    const endDate = new Date(Math.max(...dates.map(d => d.getTime())));
    
    const formatDate = (date: Date) => date.toISOString().split('T')[0];
    const filename = `expenses_${userName}_${formatDate(startDate)}_to_${formatDate(endDate)}.csv`;
    
    // Store CSV in MinIO
    const csvBuffer = Buffer.from(csvContent, 'utf8');
    const year = new Date().getFullYear();
    const month = String(new Date().getMonth() + 1).padStart(2, '0');
    const storagePath = `expense-sheets/${year}/${month}/${filename}`;
    
    try {
      await uploadBuffer(csvBuffer, storagePath, 'text/csv');
      console.log(`[expenses/export-csv] CSV stored at: ${storagePath}`);
    } catch (error) {
      console.error('[expenses/export-csv] Failed to store CSV in MinIO:', error);
      // Continue with direct download even if storage fails
    }
    
    // Return CSV for direct download
    setHeader(event, 'Content-Type', 'text/csv');
    setHeader(event, 'Content-Disposition', `attachment; filename="${filename}"`);
    setHeader(event, 'Content-Length', csvBuffer.length);
    
    return csvContent;
    
  } catch (error: any) {
    console.error('[expenses/export-csv] Error generating CSV:', error);
    
    throw createError({
      statusCode: 500,
      statusMessage: error.message || 'Failed to generate CSV export'
    });
  }
});
