// Admin routes
const express = require('express');
const router = express.Router();
const { authenticateAdmin } = require('../middleware/auth');
const QuickBooksPaymentsService = require('../services/quickbooks-payments');
const QuickBooksOnlineService = require('../services/quickbooks-online');
const { auditLog } = require('../utils/logging');

// Enhanced refund endpoint with QuickBooks Online integration
router.post('/api/transactions/:transactionId/refund', authenticateAdmin, async (req, res) => {
    try {
        const { transactionId } = req.params;
        const { amount, reason } = req.body;
        
        auditLog('ADMIN_REFUND_REQUEST', { transactionId, amount, reason }, req);
        
        // Get QuickBooks tokens from global state
        const { accessToken, realmId, environment } = req.app.locals.quickbooks || {};
        
        if (!accessToken) {
            return res.status(401).json({
                success: false,
                message: 'QuickBooks not connected',
                requestId: req.requestId
            });
        }

        if (!realmId) {
            return res.status(500).json({
                success: false,
                message: 'QuickBooks company not connected. Please reconnect QuickBooks.',
                requestId: req.requestId
            });
        }

        // Initialize services
        const paymentsService = new QuickBooksPaymentsService(accessToken, environment);
        const qboService = new QuickBooksOnlineService(accessToken, realmId, environment);

        // Prepare refund data for Payments API
        // QuickBooks Payments API v4 expects simple format
        const refundData = amount && parseFloat(amount) > 0
            ? { amount: parseFloat(amount) }
            : {}; // Empty for full refund

        // Step 1: Get transaction details first to check if refund is possible
        auditLog('REFUND_DEBUG_FETCHING_TRANSACTION', { transactionId }, req);
        const transactionDetails = await paymentsService.getTransactionDetails(transactionId, req);
        
        // Log full transaction details to app.log
        // QuickBooks uses 'refundDetail' (not 'refunds') for existing refunds
        const existingRefunds = transactionDetails.data?.refundDetail || transactionDetails.data?.refunds || [];
        
        auditLog('REFUND_DEBUG_TRANSACTION_DETAILS', {
            transactionId,
            status: transactionDetails.data?.status,
            amount: transactionDetails.data?.amount,
            created: transactionDetails.data?.created,
            refundDetail: existingRefunds,
            fullData: transactionDetails.data
        }, req);
        
        // Check if transaction has already been refunded
        if (existingRefunds.length > 0) {
            const totalRefunded = existingRefunds.reduce((sum, refund) => {
                return sum + parseFloat(refund.amount || 0);
            }, 0);
            
            auditLog('REFUND_DEBUG_EXISTING_REFUNDS', {
                transactionId,
                totalRefunded,
                transactionAmount: transactionDetails.data.amount,
                existingRefunds: existingRefunds
            }, req);
            
            if (totalRefunded >= parseFloat(transactionDetails.data.amount)) {
                auditLog('REFUND_BLOCKED_ALREADY_REFUNDED', {
                    transactionId,
                    totalRefunded,
                    transactionAmount: transactionDetails.data.amount,
                    message: 'Transaction has already been fully refunded'
                }, req);
                
                return res.status(400).json({
                    success: false,
                    message: `Transaction has already been fully refunded (Refund ID: ${existingRefunds[0].id})`,
                    totalRefunded: totalRefunded,
                    transactionAmount: transactionDetails.data.amount,
                    existingRefunds: existingRefunds,
                    requestId: req.requestId
                });
            }
        }
        
        // Step 2: Process refund through Payments API
        const refundResponse = await paymentsService.processRefund(transactionId, refundData, req);
        
        if (refundResponse.status === 200 || refundResponse.status === 201) {
            auditLog('ADMIN_REFUND_SUCCESS', { 
                transactionId, 
                refundId: refundResponse.data.id,
                refundAmount: refundResponse.data.amount
            }, req);
            
            // Step 2: Create accounting entries in QuickBooks Online
            let refundReceipt = null;
            let originalSalesReceipt = null;
            
            try {
                // Find the original sales receipt
                originalSalesReceipt = await qboService.findSalesReceiptByTransactionId(transactionId);
                
                if (originalSalesReceipt) {
                    auditLog('ORIGINAL_SALES_RECEIPT_FOUND', {
                        salesReceiptId: originalSalesReceipt.Id,
                        transactionId: transactionId
                    }, req);
                    
                    // Get customer from original sales receipt
                    const customer = {
                        Id: originalSalesReceipt.CustomerRef.value,
                        DisplayName: originalSalesReceipt.CustomerRef.name
                    };
                    
                    // Create refund receipt
                    const refundReceiptData = {
                        originalTransactionId: transactionId,
                        refundId: refundResponse.data.id,
                        amount: refundResponse.data.amount,
                        reason: reason || 'Customer request'
                    };
                    
                    refundReceipt = await qboService.createRefundReceipt(
                        customer, 
                        originalSalesReceipt, 
                        refundReceiptData, 
                        req
                    );
                    
                    if (refundReceipt) {
                        auditLog('REFUND_RECEIPT_CREATED', {
                            refundReceiptId: refundReceipt.Id,
                            originalSalesReceiptId: originalSalesReceipt.Id,
                            transactionId: transactionId,
                            refundId: refundResponse.data.id
                        }, req);
                    }
                } else {
                    auditLog('ORIGINAL_SALES_RECEIPT_NOT_FOUND', {
                        transactionId: transactionId,
                        note: 'Refund processed but no accounting entry created'
                    }, req);
                }
            } catch (qboError) {
                auditLog('REFUND_RECEIPT_ERROR', {
                    error: qboError.message,
                    transactionId: transactionId,
                    refundId: refundResponse.data.id,
                    refundStillSuccessful: true
                }, req);
                
                console.error('Failed to create refund receipt in QBO, but refund was successful:', qboError.message);
            }
            
            res.json({
                success: true,
                message: 'Refund processed successfully',
                refund: {
                    id: refundResponse.data.id,
                    amount: refundResponse.data.amount,
                    status: refundResponse.data.status,
                    created: refundResponse.data.created || new Date().toISOString(),
                    originalTransactionId: transactionId
                },
                accounting: {
                    originalSalesReceipt: originalSalesReceipt ? {
                        id: originalSalesReceipt.Id,
                        docNumber: originalSalesReceipt.DocNumber
                    } : null,
                    refundReceipt: refundReceipt ? {
                        id: refundReceipt.Id,
                        docNumber: refundReceipt.DocNumber
                    } : null
                },
                requestId: req.requestId
            });
        } else {
            auditLog('ADMIN_REFUND_FAILED', { 
                transactionId, 
                status: refundResponse.status,
                error: refundResponse.data
            }, req);
            
            res.status(refundResponse.status).json({
                success: false,
                message: 'Failed to process refund',
                error: refundResponse.data,
                requestId: req.requestId
            });
        }
    } catch (error) {
        auditLog('ADMIN_REFUND_ERROR', { 
            error: error.message,
            transactionId: req.params.transactionId
        }, req);
        
        res.status(500).json({
            success: false,
            message: 'Error processing refund',
            error: error.message,
            requestId: req.requestId
        });
    }
});

// Void transaction endpoint
router.post('/api/transactions/:transactionId/void', authenticateAdmin, async (req, res) => {
    try {
        const { transactionId } = req.params;
        const { reason } = req.body;
        
        auditLog('ADMIN_VOID_REQUEST', { transactionId, reason }, req);
        
        // Get QuickBooks tokens from global state
        const { accessToken, realmId, environment } = req.app.locals.quickbooks || {};
        
        if (!accessToken) {
            return res.status(401).json({
                success: false,
                message: 'QuickBooks not connected',
                requestId: req.requestId
            });
        }

        // Initialize services
        const paymentsService = new QuickBooksPaymentsService(accessToken, environment);
        const qboService = new QuickBooksOnlineService(accessToken, realmId, environment);

        // Step 1: Void transaction through Payments API
        const voidResponse = await paymentsService.voidTransaction(transactionId, req);
        
        if (voidResponse.status === 200 || voidResponse.status === 201) {
            auditLog('ADMIN_VOID_SUCCESS', { 
                transactionId,
                voidedAt: new Date().toISOString()
            }, req);
            
            // Step 2: Void the sales receipt in QuickBooks Online
            let voidedSalesReceipt = null;
            
            try {
                // Find the original sales receipt
                const originalSalesReceipt = await qboService.findSalesReceiptByTransactionId(transactionId);
                
                if (originalSalesReceipt) {
                    voidedSalesReceipt = await qboService.voidSalesReceipt(originalSalesReceipt.Id, req);
                    
                    auditLog('SALES_RECEIPT_VOIDED', {
                        salesReceiptId: originalSalesReceipt.Id,
                        transactionId: transactionId
                    }, req);
                }
            } catch (qboError) {
                auditLog('VOID_SALES_RECEIPT_ERROR', {
                    error: qboError.message,
                    transactionId: transactionId,
                    voidStillSuccessful: true
                }, req);
                
                console.error('Failed to void sales receipt in QBO, but transaction was voided:', qboError.message);
            }
            
            res.json({
                success: true,
                message: 'Transaction voided successfully',
                void: {
                    transactionId: transactionId,
                    status: 'VOIDED',
                    voidedAt: new Date().toISOString(),
                    reason: reason || 'Administrative void'
                },
                accounting: {
                    salesReceiptVoided: !!voidedSalesReceipt,
                    salesReceiptId: voidedSalesReceipt?.Id || null
                },
                requestId: req.requestId
            });
        } else {
            auditLog('ADMIN_VOID_FAILED', { 
                transactionId, 
                status: voidResponse.status,
                error: voidResponse.data
            }, req);
            
            res.status(voidResponse.status).json({
                success: false,
                message: 'Failed to void transaction',
                error: voidResponse.data,
                requestId: req.requestId
            });
        }
    } catch (error) {
        auditLog('ADMIN_VOID_ERROR', { 
            error: error.message,
            transactionId: req.params.transactionId
        }, req);
        
        res.status(500).json({
            success: false,
            message: 'Error voiding transaction',
            error: error.message,
            requestId: req.requestId
        });
    }
});

module.exports = router;
