import { requireSalesOrAdmin } from '~/server/utils/auth';
import { getNocoDbConfiguration, normalizePersonName } from '~/server/utils/nocodb';
import { logAuditEvent } from '~/server/utils/audit-logger';

export default defineEventHandler(async (event) => {
  console.log('[EXPENSES] Merge duplicates request');

  let body: any;

  try {
    // Require sales or admin access
    const session = await requireSalesOrAdmin(event);
    const userId = session.user?.id || 'unknown';
    const userEmail = session.user?.email || 'unknown';

    body = await readBody(event);
    const { masterId, duplicateIds, mergeData } = body;

    if (!masterId || !duplicateIds || !Array.isArray(duplicateIds) || duplicateIds.length === 0) {
      throw createError({
        statusCode: 400,
        statusMessage: 'Invalid merge request. Master ID and duplicate IDs required.'
      });
    }

    console.log('[EXPENSES] Merging', duplicateIds.length, 'duplicates into master expense', masterId);

    // Get NocoDB configuration
    const config = getNocoDbConfiguration();
    const expenseTableId = "mxfcefkk4dqs6uq";

    // First, get all expenses involved
    const allIds = [masterId, ...duplicateIds];
    const expensesToMerge: any[] = [];
    
    for (const id of allIds) {
      try {
        const expense = await $fetch(`${config.url}/api/v2/tables/${expenseTableId}/records/${id}`, {
          headers: {
            'xc-token': config.token
          }
        });
        expensesToMerge.push(expense);
      } catch (error) {
        console.error(`[EXPENSES] Failed to fetch expense ${id}:`, error);
      }
    }

    if (expensesToMerge.length < 2) {
      throw createError({
        statusCode: 404,
        statusMessage: 'Could not find enough expenses to merge'
      });
    }

    const masterExpense = expensesToMerge.find(e => e.Id === parseInt(masterId));
    if (!masterExpense) {
      throw createError({
        statusCode: 404,
        statusMessage: 'Master expense not found'
      });
    }

    // Log the action before making changes
    await logAuditEvent(event, 'MERGE_EXPENSE_DUPLICATES', 'expense', {
      resourceId: masterId,
      changes: {
        duplicateIds,
        mergeData,
        originalExpenses: expensesToMerge
      }
    });

    // Update master expense with merged data
    if (mergeData) {
      const updateData: any = { Id: parseInt(masterId) };
      
      // Normalize payer name if provided
      if (mergeData.Payer) {
        updateData.Payer = normalizePersonName(mergeData.Payer);
      }
      
      // Copy other fields
      const allowedFields = [
        'Establishment Name',
        'Price',
        'Category',
        'Contents',
        'Time',
        'Payment Method',
        'currency',
        'Paid'
      ];
      
      allowedFields.forEach(field => {
        if (mergeData[field] !== undefined) {
          updateData[field] = mergeData[field];
        }
      });

      console.log('[EXPENSES] Updating master expense with:', updateData);

      await $fetch(`${config.url}/api/v2/tables/${expenseTableId}/records`, {
        method: 'PATCH',
        headers: {
          'xc-token': config.token,
          'Content-Type': 'application/json'
        },
        body: updateData
      });
    }

    // Delete duplicate expenses
    const deleteResults = [];
    for (const duplicateId of duplicateIds) {
      try {
        console.log('[EXPENSES] Deleting duplicate expense:', duplicateId);
        
        await $fetch(`${config.url}/api/v2/tables/${expenseTableId}/records`, {
          method: 'DELETE',
          headers: {
            'xc-token': config.token,
            'Content-Type': 'application/json'
          },
          body: { Id: parseInt(duplicateId) }
        });
        
        deleteResults.push({ id: duplicateId, success: true });
      } catch (error: any) {
        console.error('[EXPENSES] Failed to delete duplicate:', duplicateId, error);
        deleteResults.push({ 
          id: duplicateId, 
          success: false, 
          error: error.message || 'Delete failed' 
        });
      }
    }

    // Check if all deletes were successful
    const failedDeletes = deleteResults.filter(r => !r.success);
    if (failedDeletes.length > 0) {
      console.warn('[EXPENSES] Some duplicates could not be deleted:', failedDeletes);
    }

    // Log successful completion
    await logAuditEvent(event, 'MERGE_EXPENSE_DUPLICATES_COMPLETE', 'expense', {
      resourceId: masterId,
      changes: {
        deletedCount: deleteResults.filter(r => r.success).length,
        failedDeletes,
        mergeData
      },
      status: 'success'
    });

    return {
      success: true,
      data: {
        masterId,
        mergedData: mergeData,
        deletedCount: deleteResults.filter(r => r.success).length,
        deleteResults,
        message: `Successfully merged ${deleteResults.filter(r => r.success).length} duplicates into expense ${masterId}`
      }
    };

  } catch (error: any) {
    console.error('[EXPENSES] Failed to merge duplicates:', error);
    
    // Log the failure
    await logAuditEvent(event, 'MERGE_EXPENSE_DUPLICATES_FAILED', 'expense', {
      resourceId: body?.masterId || 'unknown',
      changes: {
        error: error.message || 'Unknown error',
        requestBody: body
      },
      status: 'failure',
      errorMessage: error.message || 'Unknown error'
    });
    
    if (error.statusCode) {
      throw error;
    }

    throw createError({
      statusCode: 500,
      statusMessage: 'Failed to merge duplicate expenses'
    });
  }
});
