// Payment routes
const express = require('express');
const router = express.Router();
const rateLimit = require('../middleware/rate-limit');
const QuickBooksPaymentsService = require('../services/quickbooks-payments');
const QuickBooksOnlineService = require('../services/quickbooks-online');
const { auditLog } = require('../utils/logging');
const { 
    validateCardNumber, 
    validateExpirationDate, 
    validateCVV, 
    validateAmount,
    validateBillingAddress,
    sanitizeCardNumber,
    sanitizeString
} = require('../utils/validation');

// Payment processing endpoint
router.post('/process', rateLimit(20, 300000), async (req, res) => {
    try {
        // Handle both flat structure and nested cardDetails structure
        const { 
            amount, 
            cardNumber: flatCardNumber, 
            expirationMonth: flatExpirationMonth, 
            expirationYear: flatExpirationYear, 
            cvv: flatCvv, 
            cardholderName: flatCardholderName,
            cardDetails,
            billingAddress,
            customerInfo,
            context,
            paymentType = 'payment' // Default to 'payment' if not specified
        } = req.body;

        // Extract card data from either flat structure or cardDetails object
        const cardNumber = flatCardNumber || cardDetails?.cardNumber;
        const expirationMonth = flatExpirationMonth || cardDetails?.expirationMonth;
        const expirationYear = flatExpirationYear || cardDetails?.expirationYear;
        const cvv = flatCvv || cardDetails?.cvv;
        const cardholderName = flatCardholderName || cardDetails?.cardholderName;

        auditLog('PAYMENT_REQUEST', { 
            amount, 
            hasCardNumber: !!cardNumber,
            hasCustomerInfo: !!customerInfo,
            hasBillingAddress: !!billingAddress,
            cardNumberLength: cardNumber?.length || 0,
            hasCardDetails: !!cardDetails,
            extractedCardNumber: cardNumber ? 'present' : 'missing'
        }, req);

        // Get QuickBooks tokens from global state (you'll need to pass these in)
        const { accessToken, realmId, environment } = req.app.locals.quickbooks || {};
        
        if (!accessToken) {
            return res.status(401).json({
                success: false,
                message: 'QuickBooks not connected',
                requestId: req.requestId
            });
        }

        // Validation
        const finalAmount = parseFloat(amount);
        if (!validateAmount(finalAmount)) {
            return res.status(400).json({
                success: false,
                message: 'Invalid amount',
                requestId: req.requestId
            });
        }

        const sanitizedCardNumber = sanitizeCardNumber(cardNumber);
        
        // Enhanced card validation logging
        console.log('CARD_VALIDATION_DEBUG:', {
            originalCardNumber: cardNumber ? 'present' : 'missing',
            originalLength: cardNumber?.length || 0,
            sanitizedCardNumber: sanitizedCardNumber ? 'present' : 'missing', 
            sanitizedLength: sanitizedCardNumber?.length || 0,
            isValid: validateCardNumber(sanitizedCardNumber),
            requestId: req.requestId
        });
        
        if (!validateCardNumber(sanitizedCardNumber)) {
            auditLog('CARD_VALIDATION_FAILED', {
                originalCardNumber: cardNumber ? 'present' : 'missing',
                originalLength: cardNumber?.length || 0,
                sanitizedLength: sanitizedCardNumber?.length || 0,
                hasCardDetails: !!req.body.cardDetails
            }, req);
            
            return res.status(400).json({
                success: false,
                message: 'Invalid card number',
                requestId: req.requestId
            });
        }

        const finalExpirationMonth = parseInt(expirationMonth);
        const finalExpirationYear = parseInt(expirationYear);
        if (!validateExpirationDate(finalExpirationMonth, finalExpirationYear)) {
            return res.status(400).json({
                success: false,
                message: 'Invalid expiration date',
                requestId: req.requestId
            });
        }

        const finalCvv = cvv.toString();
        if (!validateCVV(finalCvv, sanitizedCardNumber)) {
            return res.status(400).json({
                success: false,
                message: 'Invalid CVV',
                requestId: req.requestId
            });
        }

        const finalCardholderName = sanitizeString(cardholderName, 100);
        if (!finalCardholderName) {
            return res.status(400).json({
                success: false,
                message: 'Cardholder name is required',
                requestId: req.requestId
            });
        }

        // Validate billing address if provided
        if (billingAddress) {
            const addressValidation = validateBillingAddress(billingAddress);
            if (addressValidation !== true) {
                return res.status(400).json({
                    success: false,
                    message: 'Invalid billing address: ' + addressValidation.join(', '),
                    requestId: req.requestId
                });
            }
        }

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

        // Customer creation/lookup
        let qboCustomer = null;
        if (customerInfo || billingAddress) {
            try {
                auditLog('CUSTOMER_LOOKUP_START', { 
                    hasCustomerInfo: !!customerInfo,
                    hasBillingAddress: !!billingAddress,
                    email: customerInfo?.email || billingAddress?.email
                }, req);
                
                qboCustomer = await qboService.getOrCreateCustomer(customerInfo, billingAddress);
                
                if (qboCustomer) {
                    auditLog('CUSTOMER_SUCCESS', { 
                        customerId: qboCustomer.Id,
                        displayName: qboCustomer.DisplayName,
                        isNew: !qboCustomer.MetaData?.LastUpdatedTime
                    }, req);
                } else {
                    auditLog('CUSTOMER_SKIPPED', { reason: 'insufficient_data_or_creation_failed' }, req);
                }
            } catch (error) {
                auditLog('CUSTOMER_ERROR', { 
                    error: error.message,
                    continuing: true 
                }, req);
                // Continue with payment even if customer creation fails
            }
        }
        
        // Payment request - QuickBooks Payments API v4 format
        const paymentData = {
            amount: finalAmount.toFixed(2),
            currency: 'USD',
            card: {
                number: sanitizedCardNumber,
                expMonth: finalExpirationMonth.toString().padStart(2, '0'),
                expYear: finalExpirationYear.toString(),
                cvc: finalCvv
            },
            context: {
                mobile: context?.mobile || false,
                isEcommerce: context?.isEcommerce || true
            }
        };
        
        // Add billing address if provided
        // CRITICAL: Transform address fields to QuickBooks Payments API v4 format
        // QuickBooks expects: streetAddress, region, postalCode
        // NOT: line1, state, postalCode
        if (billingAddress) {
            paymentData.card.address = {
                streetAddress: billingAddress.streetAddress || billingAddress.line1 || billingAddress.address,
                city: billingAddress.city,
                region: billingAddress.region || billingAddress.state,
                postalCode: billingAddress.postalCode || billingAddress.zipCode || billingAddress.zip,
                country: billingAddress.country
            };
        }
        
        // Add cardholder name if provided
        if (finalCardholderName) {
            paymentData.card.name = finalCardholderName;
        }

        // Process payment
        const response = await paymentsService.processPayment(paymentData, req);
        
        // Check for successful payment
        // CRITICAL FIX: QuickBooks sometimes returns HTTP 201 for declined payments
        // We must check the actual status in the response data, not just HTTP status
        const isSuccessStatus = response.status === 200 || response.status === 201;
        
        // Define all possible QuickBooks payment statuses
        const SUCCESS_STATUSES = ['CAPTURED', 'AUTHORIZED', 'SETTLED'];
        const FAILURE_STATUSES = ['DECLINED', 'FAILED', 'VOIDED'];
        const PENDING_STATUSES = ['PENDING'];
        
        const paymentStatus = response.data?.status?.toUpperCase() || '';
        const isSuccessData = SUCCESS_STATUSES.includes(paymentStatus);
        const isFailureData = FAILURE_STATUSES.includes(paymentStatus);
        const isPendingData = PENDING_STATUSES.includes(paymentStatus);
        
        // Specific status checks for better error handling
        const isDeclined = paymentStatus === 'DECLINED';
        const isFailed = paymentStatus === 'FAILED';
        const isVoided = paymentStatus === 'VOIDED';

        auditLog('PAYMENT_RESPONSE', {
            status: response.status,
            paymentStatus: paymentStatus,
            transactionId: response.data?.id,
            isSuccessStatus,
            isSuccessData,
            isFailureData,
            isPendingData,
            isDeclined,
            requestId: req.requestId
        });
        
        if (isSuccessStatus && isSuccessData) {
            auditLog('PAYMENT_SUCCESS_DETAILED', {
                transactionId: response.data.id,
                amount: response.data.amount,
                status: response.data.status,
                customer: finalCardholderName,
                httpStatus: response.status,
                fullResponse: response.data
            }, req);
            
            auditLog('PAYMENT_SUCCESS', { 
                transactionId: response.data.id, 
                amount: response.data.amount 
            }, req);
            
            // Create Sales Receipt in QuickBooks Online to link payment to customer
            let salesReceipt = null;
            if (qboCustomer) {
                try {
                    console.log('Creating sales receipt for customer:', qboCustomer.Id, 'transaction:', response.data.id, 'type:', paymentType);
                    salesReceipt = await qboService.createSalesReceipt(qboCustomer, response.data, req, paymentType);
                    auditLog('SALES_RECEIPT_CREATED', { 
                        salesReceiptId: salesReceipt?.Id,
                        customerId: qboCustomer.Id,
                        transactionId: response.data.id
                    }, req);
                    console.log('✅ Sales receipt created successfully:', salesReceipt?.Id);
                } catch (error) {
                    auditLog('SALES_RECEIPT_ERROR', { 
                        error: error.message,
                        customerId: qboCustomer.Id,
                        transactionId: response.data.id,
                        paymentStillSuccessful: true
                    }, req);
                    // Continue even if sales receipt creation fails - payment was successful
                    console.error('❌ Sales receipt creation failed but payment succeeded:', error.message);
                }
            } else {
                console.log('⚠️ No customer created, skipping sales receipt creation');
                auditLog('SALES_RECEIPT_SKIPPED', { 
                    reason: 'no_customer_created',
                    hasCustomerInfo: !!customerInfo,
                    hasBillingAddress: !!billingAddress,
                    transactionId: response.data.id
                }, req);
            }
            
            res.json({
                success: true,
                message: 'Payment processed successfully',
                // Add transaction ID at multiple levels for compatibility
                transactionId: response.data.id,
                transaction_id: response.data.id,
                id: response.data.id,
                amount: response.data.amount,
                status: response.data.status,
                transaction: {
                    id: response.data.id,
                    amount: response.data.amount,
                    status: response.data.status,
                    created: response.data.created || new Date().toISOString(),
                    card: {
                        last4: response.data.card?.number?.slice(-4) || 'N/A',
                        brand: response.data.card?.brand || 'N/A'
                    }
                },
                data: {
                    id: response.data.id,
                    amount: response.data.amount,
                    status: response.data.status
                },
                customer: qboCustomer ? {
                    id: qboCustomer.Id,
                    name: qboCustomer.DisplayName
                } : null,
                salesReceipt: salesReceipt ? {
                    id: salesReceipt.Id,
                    docNumber: salesReceipt.DocNumber
                } : null,
                requestId: req.requestId
            });
        } else {
            // CRITICAL FIX: Return proper HTTP status for different failure types
            // Map QuickBooks statuses to appropriate HTTP status codes
            let httpStatus = 400; // Default to bad request
            let message = 'Payment failed';
            
            if (isDeclined) {
                httpStatus = 402; // Payment Required
                message = 'Payment declined';
            } else if (isFailed) {
                httpStatus = 400; // Bad Request
                message = 'Payment processing failed';
            } else if (isVoided) {
                httpStatus = 410; // Gone
                message = 'Payment was voided';
            } else if (isPendingData) {
                httpStatus = 202; // Accepted (processing)
                message = 'Payment is pending';
            } else if (response.status >= 400) {
                httpStatus = response.status;
            }
            
            auditLog('PAYMENT_FAILED', { 
                status: response.status,
                paymentStatus: paymentStatus,
                httpStatus: httpStatus,
                isDeclined,
                isFailed,
                isVoided,
                isPending: isPendingData,
                error: response.data 
            }, req);
            
            res.status(httpStatus).json({
                success: false,
                message: message,
                status: paymentStatus,
                error: response.data,
                requestId: req.requestId
            });
        }
    } catch (error) {
        auditLog('PAYMENT_ERROR', { error: error.message }, req);
        res.status(500).json({
            success: false,
            message: 'Payment processing error',
            requestId: req.requestId
        });
    }
});

module.exports = router;
