<?php

namespace App\Http\Controllers;

use App\Models\Sale;
use App\Models\SaleItem;
use App\Models\Payment;
use App\Models\PaymentMethod;
use App\Models\Product;
use App\Models\Customer;
use App\Models\MpesaTransaction;
use App\Models\HoldSale;
use App\Models\UnifiedNumberSequence;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Carbon\Carbon;

class PaymentController extends Controller
{
    // ==================== MAIN PAYMENT PROCESSING ====================
    
    /**
     * Process payment from POS (main method) - Fixed unified numbering
     */
    public function process(Request $request)
    {
        DB::beginTransaction();
        
        try {
            Log::info('🚀 Payment request received:', $request->all());
            
            // ========== CRITICAL: Generate unified number FIRST ==========
            // Check if unified number was provided in request
            $unifiedNumber = $request->input('unified_number');
            
            if (!$unifiedNumber) {
                // Generate new unified number
                $unifiedNumber = $this->generateUnifiedNumber();
                Log::info('🔄 Generated new unified number:', ['unified_number' => $unifiedNumber]);
            } else {
                Log::info('📥 Using provided unified number:', ['unified_number' => $unifiedNumber]);
            }
            
            // Use unified number for both invoice and receipt numbers
            $invoiceNumber = $unifiedNumber;
            $receiptNumber = $unifiedNumber;
            
            Log::info('🎯 Setting invoice/receipt numbers:', [
                'unified' => $unifiedNumber,
                'invoice' => $invoiceNumber,
                'receipt' => $receiptNumber
            ]);
            
            // Validate the request
            $validated = $this->validatePaymentRequest($request);
            
            // Get customer and their VAT status
            $customer = null;
            $customerVatStatus = 'vatable'; // default
            $isExempted = false;
            $isZeroRated = false;
            
            if (!empty($validated['customer_id'])) {
                $customer = Customer::find($validated['customer_id']);
                if ($customer) {
                    $customerVatStatus = $customer->vat_status ?? 'vatable';
                    $isExempted = $customerVatStatus === 'exempted';
                    $isZeroRated = $customerVatStatus === 'zero_rated';
                }
            }
            
            // Override with provided VAT status if present
            if (!empty($validated['customer_vat_status'])) {
                $customerVatStatus = $validated['customer_vat_status'];
                $isExempted = $customerVatStatus === 'exempted';
                $isZeroRated = $customerVatStatus === 'zero_rated';
            }
            
            Log::info('👤 Customer VAT status:', [
                'customer_id' => $validated['customer_id'] ?? null,
                'vat_status' => $customerVatStatus,
                'is_exempted' => $isExempted,
                'is_zero_rated' => $isZeroRated
            ]);
            
            // Calculate totals with customer VAT status
            $result = $this->calculateCartTotals($validated['cart'], $customer);
            
            Log::info('💰 VAT Calculation results:', [
                'subtotal' => $result['subtotal'],
                'tax_total' => $result['taxTotal'],
                'grand_total' => $result['subtotal'] + $result['taxTotal'],
                'customer_vat_status' => $customerVatStatus
            ]);
            
            // Use provided totals if available, otherwise use calculated ones
            $subtotal = $validated['subtotal'] ?? $result['subtotal'];
            $taxTotal = $validated['vat_amount'] ?? $result['taxTotal'];
            $taxableAmount = $validated['taxable_amount'] ?? $result['taxableAmount'];
            $nonTaxableAmount = $validated['non_taxable_amount'] ?? $result['nonTaxableAmount'];
            $exemptedAmount = $result['exemptedAmount'] ?? 0;
            $zeroRatedAmount = $result['zeroRatedAmount'] ?? 0;
            
            // Apply discount
            $discount = $validated['discount'] ?? 0;
            $discountedSubtotal = max(0, $subtotal - $discount);
            
            // Calculate grand total
            $grandTotal = $discountedSubtotal + $taxTotal;
            
            // Validate amount matches calculated total (with tolerance)
            $this->validateAmount($validated['amount'], $grandTotal, 0.01); // 0.01 tolerance
            
            // Get current user (cashier)
            $user = auth()->user();
            
            // Determine payment status
            $paymentStatus = 'paid';
            if ($validated['payment_method'] === 'credit') {
                $paymentStatus = 'partial';
            }
            
            // Get payment method from database if exists
            $paymentMethod = PaymentMethod::where('code', $validated['payment_method'])->first();
            $paymentMethodId = $paymentMethod ? $paymentMethod->id : null;
            
            // Calculate method-specific amounts
            $cashReceived = $validated['cash_received'] ?? $grandTotal;
            $changeAmount = $validated['change'] ?? max(0, $cashReceived - $grandTotal);
            
            // For non-cash payments, cash_received should be 0
            if ($validated['payment_method'] !== 'cash') {
                $cashReceived = 0;
                $changeAmount = 0;
            }
            
            // ========== CRITICAL: Create sale record WITH unified number ==========
            $saleData = [
                'unified_number' => $unifiedNumber, // Store the unified number
                'invoice_no' => $invoiceNumber,
                'receipt_no' => $receiptNumber,
                'customer_id' => $validated['customer_id'] ?? null,
                'user_id' => $user->id,
                'subtotal' => $subtotal,
                'tax_total' => $taxTotal,
                'discount' => $discount,
                'grand_total' => $grandTotal,
                'status' => 'completed',
                'payment_status' => $paymentStatus,
                'is_vat_applied' => !$isExempted, // VAT not applied for exempted customers
                'zero_rated' => $isZeroRated,
                'payment_method' => $validated['payment_method'],
                'transaction_id' => $validated['mpesa_transaction_id'] ?? $this->generateTransactionId(),
                'cash_received' => $cashReceived,
                'customer_change' => $changeAmount,
                'notes' => $validated['notes'] ?? null,
                'sale_date' => Carbon::now(),
                
                // Enhanced VAT breakdown fields
                'vat_amount' => $taxTotal,
                'vat_rate' => $result['effectiveVatRate'] ?? 16,
                'taxable_amount' => $taxableAmount,
                'non_taxable_amount' => $nonTaxableAmount,
                'zero_rated_amount' => $zeroRatedAmount,
                'exempted_amount' => $exemptedAmount,
                'customer_vat_status' => $customerVatStatus,
                'vat_by_rate' => json_encode($result['vatByRate'] ?? []),
                'etims_status' => 'pending',
            ];
            
            // Add other payment method amounts
            switch ($validated['payment_method']) {
                case 'mpesa':
                    $saleData['mpesa_received'] = $grandTotal;
                    $saleData['mpesa_phone'] = $validated['mpesa_phone'] ?? null;
                    $saleData['mpesa_transaction_id'] = $validated['mpesa_transaction_id'] ?? null;
                    break;
                case 'card':
                    $saleData['card_received'] = $grandTotal;
                    break;
                case 'bank':
                    $saleData['bank_received'] = $grandTotal;
                    break;
                case 'credit':
                    $saleData['credit_amount'] = $grandTotal;
                    break;
            }
            
            Log::info('💾 Creating sale record with unified number:', [
                'unified_number' => $unifiedNumber,
                'invoice_no' => $invoiceNumber,
                'receipt_no' => $receiptNumber,
                'grand_total' => $grandTotal
            ]);
            
            $sale = Sale::create($saleData);
            
            if (!$sale) {
                throw new \Exception('Failed to create sale record');
            }
            
            Log::info('✅ Sale record created:', [
                'sale_id' => $sale->id,
                'unified_number' => $sale->unified_number,
                'invoice_no' => $sale->invoice_no,
                'receipt_no' => $sale->receipt_no
            ]);
            
            // Create sale items with VAT details
            foreach ($result['items'] as $itemData) {
                $product = $itemData['product'];
                
                SaleItem::create([
                    'sale_id' => $sale->id,
                    'product_id' => $product->id,
                    'qty' => $itemData['qty'],
                    'price' => $itemData['price_with_tax'] ?? $itemData['price'],
                    'price_ex_tax' => $itemData['price_ex_tax'],
                    'tax_rate' => $itemData['tax_rate'],
                    'tax_amount' => $itemData['tax_amount'],
                    'tax' => $itemData['tax_amount'],
                    'total' => $itemData['total'],
                    'vat_status' => $itemData['vat_status'] ?? ($itemData['tax_rate'] > 0 ? 'vatable' : 'non_vatable'),
                    'vat_applied' => $itemData['vat_applied'] ?? ($itemData['tax_rate'] > 0),
                ]);
                
                // Update product stock
                if ($product->track_inventory) {
                    $product->decrement('stock', $itemData['qty']);
                    
                    // Update stock status
                    if ($product->stock <= 0) {
                        $product->stock_status = 'out_of_stock';
                    } elseif ($product->stock <= $product->minimum_stock) {
                        $product->stock_status = 'low_stock';
                        Log::warning('⚠️ Low stock alert for product:', [
                            'product_id' => $product->id,
                            'product_name' => $product->name,
                            'current_stock' => $product->stock,
                            'minimum_stock' => $product->minimum_stock
                        ]);
                    } else {
                        $product->stock_status = 'in_stock';
                    }
                    
                    $product->save();
                }
            }
            
            // Create payment record
            $paymentMethod = PaymentMethod::where('code', $validated['payment_method'])->first();
            $paymentMethodId = $paymentMethod ? $paymentMethod->id : null;

            $payment = Payment::create([
                'sale_id' => $sale->id,
                'payment_method_id' => $paymentMethodId,
                'amount' => $grandTotal,
                'reference' => $this->generatePaymentReference($validated['payment_method']),
                'status' => 'completed',
                'meta' => $this->getPaymentDetails($validated),
                'paid_at' => Carbon::now(),
                'received_by' => $user->id,
                'notes' => $validated['notes'] ?? null,
            ]);
            
            // Handle method-specific records
            $this->handlePaymentMethodRecords($validated['payment_method'], $sale, $validated, $payment);
            
            // Update customer if exists
            if (!empty($validated['customer_id'])) {
                $this->updateCustomerPurchase($validated['customer_id'], $grandTotal);
            }
            
            // Delete hold sale if exists
            if (!empty($validated['hold_sale_id'])) {
                HoldSale::where('id', $validated['hold_sale_id'])->delete();
            }
            
            DB::commit();
            
            Log::info('✅ Payment processed successfully', [
                'sale_id' => $sale->id,
                'unified_number' => $sale->unified_number,
                'invoice_no' => $invoiceNumber,
                'receipt_no' => $receiptNumber,
                'grand_total' => $grandTotal,
                'vat_total' => $taxTotal,
                'customer_vat_status' => $customerVatStatus
            ]);
            
            return response()->json([
                'success' => true,
                'message' => 'Payment processed successfully',
                'unified_number' => $unifiedNumber,
                'invoice_no' => $invoiceNumber,
                'receipt_no' => $receiptNumber,
                'sale' => [
                    'id' => $sale->id,
                    'unified_number' => $sale->unified_number,
                    'invoice_no' => $sale->invoice_no,
                    'receipt_no' => $sale->receipt_no,
                    'grand_total' => $grandTotal,
                    'vat_amount' => $taxTotal,
                    'date' => $sale->created_at->format('Y-m-d H:i:s'),
                    'customer_vat_status' => $customerVatStatus,
                    'vat_details' => [
                        'taxable_amount' => $taxableAmount,
                        'non_taxable_amount' => $nonTaxableAmount,
                        'exempted_amount' => $exemptedAmount,
                        'zero_rated_amount' => $zeroRatedAmount,
                        'vat_by_rate' => $result['vatByRate'] ?? []
                    ]
                ],
                'payment' => [
                    'method' => $sale->payment_method,
                    'transaction_id' => $sale->transaction_id,
                ],
                'receipt_data' => $this->generateReceiptData($sale),
            ]);
            
        } catch (\Illuminate\Validation\ValidationException $e) {
            DB::rollBack();
            Log::error('❌ Payment validation error:', $e->errors());
            return response()->json([
                'success' => false,
                'message' => 'Validation failed',
                'errors' => $e->errors(),
            ], 422);
            
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('❌ Payment processing error:', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
                'request_data' => $request->all()
            ]);
            
            return response()->json([
                'success' => false,
                'message' => 'Payment failed: ' . $e->getMessage(),
                'error' => config('app.debug') ? $e->getMessage() : 'Internal server error',
                'unified_number' => $unifiedNumber ?? null,
            ], 500);
        }
    }
    
    // ==================== UNIFIED NUMBER GENERATION ====================
    
    /**
     * Generate unified number for invoice and receipt
     */
    private function generateUnifiedNumber(): string
    {
        $date = now()->format('Ymd');
        $type = 'invoice_receipt';
        
        // Use database sequence for atomic increment
        DB::beginTransaction();
        
        try {
            // Try to get existing sequence for today
            $sequence = UnifiedNumberSequence::where('date', now()->toDateString())
                ->where('type', $type)
                ->lockForUpdate()
                ->first();
            
            if (!$sequence) {
                // Create new sequence for today
                $sequence = UnifiedNumberSequence::create([
                    'date' => now()->toDateString(),
                    'type' => $type,
                    'last_number' => 0,
                    'prefix' => 'INVRCP',
                    'format' => '{prefix}-{date}-{number:4}'
                ]);
            }
            
            // Increment the sequence
            $sequence->last_number += 1;
            $sequence->save();
            
            DB::commit();
            
            // Generate the unified number
            $counter = $sequence->last_number;
            $unifiedNumber = 'INVRCP-' . $date . '-' . str_pad($counter, 4, '0', STR_PAD_LEFT);
            
            Log::info('🔄 Generated unified number via sequence:', [
                'unified_number' => $unifiedNumber,
                'date' => $date,
                'counter' => $counter
            ]);
            
            return $unifiedNumber;
            
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('❌ Unified number generation failed:', ['error' => $e->getMessage()]);
            
            // Fallback: Check existing sales for today
            $lastSale = Sale::whereDate('created_at', today())
                ->orderBy('id', 'desc')
                ->first();
            
            $counter = 1;
            
            if ($lastSale && $lastSale->unified_number) {
                // Extract counter from unified number
                preg_match('/INVRCP-' . $date . '-(\d{4})/', $lastSale->unified_number, $matches);
                if ($matches && isset($matches[1])) {
                    $counter = intval($matches[1]) + 1;
                }
            }
            
            $unifiedNumber = 'INVRCP-' . $date . '-' . str_pad($counter, 4, '0', STR_PAD_LEFT);
            
            Log::info('🔄 Generated fallback unified number:', [
                'unified_number' => $unifiedNumber,
                'date' => $date,
                'counter' => $counter
            ]);
            
            return $unifiedNumber;
        }
    }
    
    /**
     * API endpoint to get unified number (for frontend)
     */
    public function getUnifiedNumber(Request $request)
    {
        try {
            $unifiedNumber = $this->generateUnifiedNumber();
            
            return response()->json([
                'success' => true,
                'unified_number' => $unifiedNumber,
                'invoice_no' => $unifiedNumber,
                'receipt_no' => $unifiedNumber,
                'date' => now()->format('Y-m-d'),
                'timestamp' => now()->toISOString()
            ]);
        } catch (\Exception $e) {
            Log::error('❌ Failed to generate unified number:', ['error' => $e->getMessage()]);
            return response()->json([
                'success' => false,
                'message' => 'Failed to generate unified number',
                'error' => config('app.debug') ? $e->getMessage() : 'Internal error'
            ], 500);
        }
    }
    
    /**
     * Generate receipt number (legacy method, now uses unified number)
     */
    private function generateReceiptNumber(): string
    {
        return $this->generateUnifiedNumber();
    }
    
    /**
     * Generate invoice number (legacy method, now uses unified number)
     */
    private function generateInvoiceNumber(): string
    {
        return $this->generateUnifiedNumber();
    }
    
    /**
     * Generate transaction ID
     */
    private function generateTransactionId(): string
    {
        return 'TXN-' . now()->format('Ymd') . '-' . str_pad(rand(1, 9999), 4, '0', STR_PAD_LEFT);
    }
    
    // ==================== RECEIPT GENERATION ====================
    
    /**
     * Show receipt by unified number (FIXED)
     */
    public function showReceipt($identifier)
    {
        try {
            Log::info('🖨️ Receipt requested:', ['identifier' => $identifier]);
            
            // Try to find sale by any identifier
            $sale = Sale::with(['items.product', 'customer', 'user', 'payment'])
                ->where('unified_number', $identifier)
                ->orWhere('invoice_no', $identifier)
                ->orWhere('receipt_no', $identifier)
                ->when(is_numeric($identifier), function($query) use ($identifier) {
                    return $query->orWhere('id', $identifier);
                })
                ->first();
            
            if (!$sale) {
                Log::warning('❌ Sale not found for receipt:', ['identifier' => $identifier]);
                
                // Check if it's a test receipt
                if (strpos($identifier, 'TEST-') === 0 || strpos($identifier, 'PREVIEW-') === 0) {
                    Log::info('📋 Generating test receipt for:', ['identifier' => $identifier]);
                    return view('pos.receipts.receipt', ['data' => $this->generateTestReceiptData($identifier)]);
                }
                
                // Check if we have cached receipt data
                $cachedData = $this->getCachedReceiptData($identifier);
                if ($cachedData) {
                    Log::info('📋 Using cached receipt data for:', ['identifier' => $identifier]);
                    return view('pos.receipts.receipt', ['data' => $cachedData]);
                }
                
                return response()->view('errors.404', [
                    'message' => 'Receipt not found: ' . $identifier . '. Unified number may not have been saved to database.'
                ], 404);
            }
            
            Log::info('✅ Found sale for receipt:', [
                'sale_id' => $sale->id,
                'unified_number' => $sale->unified_number,
                'invoice_no' => $sale->invoice_no,
                'receipt_no' => $sale->receipt_no
            ]);
            
            $receiptData = $this->generateReceiptData($sale);
            
            // Cache receipt data for future use
            $this->cacheReceiptData($sale->unified_number, $receiptData);
            
            return view('pos.receipts.receipt', ['data' => $receiptData]);
            
        } catch (\Exception $e) {
            Log::error('❌ Receipt generation error:', [
                'identifier' => $identifier,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            
            return response()->view('errors.500', [
                'message' => 'Error generating receipt: ' . $e->getMessage()
            ], 500);
        }
    }
    
    /**
     * Generate test receipt data
     */
    private function generateTestReceiptData($identifier): array
    {
        return [
            'unified_number' => $identifier,
            'invoice_no' => $identifier,
            'receipt_no' => $identifier,
            'date' => now()->format('Y-m-d'),
            'time' => now()->format('H:i:s'),
            'customer' => [
                'name' => 'Test Customer',
                'phone' => '0712345678',
                'vat_status' => 'vatable',
            ],
            'items' => [
                [
                    'name' => 'Test Product 1',
                    'quantity' => 1,
                    'unit_price' => 100,
                    'total' => 100,
                    'tax_rate' => 16,
                    'tax_amount' => 16,
                    'is_vatable' => true,
                ]
            ],
            'totals' => [
                'subtotal' => 100,
                'discount' => 0,
                'vat_amount' => 16,
                'grand_total' => 116,
            ],
            'payment' => [
                'method' => 'cash',
                'amount_paid' => 200,
                'cash_received' => 200,
                'change' => 84,
            ],
            'store' => [
                'name' => config('app.name', 'Kenyan Supermarket'),
                'address' => config('app.address', 'Nairobi CBD'),
                'phone' => config('app.phone', '0700 000 000'),
                'pin' => config('app.pin', 'P051234567N'),
            ],
            'cashier' => 'Test Cashier',
            'autoprint' => request()->has('autoprint'),
            'notes' => ['This is a test receipt. No actual sale was recorded.']
        ];
    }
    
    /**
     * Cache receipt data for temporary access
     */
    private function cacheReceiptData($identifier, $data)
    {
        $cacheKey = 'receipt_' . md5($identifier);
        \Cache::put($cacheKey, $data, now()->addMinutes(30));
    }
    
    /**
     * Get cached receipt data
     */
    private function getCachedReceiptData($identifier)
    {
        $cacheKey = 'receipt_' . md5($identifier);
        return \Cache::get($cacheKey);
    }
    
    // ==================== ENHANCED HELPER METHODS ====================
    
    /**
     * Enhanced VAT calculation for cart items with customer status
     */
    private function calculateCartTotals(array $cartItems, $customer = null): array
    {
        $subtotal = 0;
        $taxTotal = 0;
        $items = [];
        $hasVatApplied = false;
        $taxableAmount = 0;
        $nonTaxableAmount = 0;
        $exemptedAmount = 0;
        $zeroRatedAmount = 0;
        $vatByRate = [];
        
        // Determine customer VAT status
        $customerVatStatus = $customer ? ($customer->vat_status ?? 'vatable') : 'vatable';
        $isExempted = $customerVatStatus === 'exempted';
        $isZeroRated = $customerVatStatus === 'zero_rated';
        $isVatable = $customerVatStatus === 'vatable';
        
        Log::info('🧮 Calculating cart totals:', [
            'customer_vat_status' => $customerVatStatus,
            'is_exempted' => $isExempted,
            'is_zero_rated' => $isZeroRated,
            'cart_count' => count($cartItems)
        ]);
        
        foreach ($cartItems as $cartItem) {
            // Extract data with multiple fallbacks
            $productId = $cartItem['product_id'] ?? $cartItem['id'] ?? 0;
            $product = Product::with('tax')->find($productId);
            
            if (!$product) {
                throw new \Exception("Product not found: {$productId}");
            }
            
            $quantity = $cartItem['qty'] ?? $cartItem['quantity'] ?? 1;
            $price = $cartItem['price'] ?? $product->sale_price;
            
            // Use price_ex_tax if available, otherwise use price
            $itemPriceExTax = $cartItem['price_ex_tax'] ?? $price;
            $itemTotalExTax = $itemPriceExTax * $quantity;
            
            $itemTaxAmount = 0;
            $itemTaxRate = 0;
            $isProductVatable = false;
            $vatType = 'none';
            $vatStatus = 'non_vatable';
            $vatApplied = false;
            
            // Check if product is VATable
            if (isset($cartItem['is_vatable'])) {
                $isProductVatable = $cartItem['is_vatable'];
            } elseif (isset($cartItem['has_vat'])) {
                $isProductVatable = $cartItem['has_vat'];
            } else {
                $isProductVatable = $product->has_vat || $product->is_vatable || ($product->tax && $product->tax->rate > 0);
            }
            
            // Get tax rate
            if (isset($cartItem['tax_rate'])) {
                $itemTaxRate = $cartItem['tax_rate'];
            } elseif ($product->tax) {
                $itemTaxRate = $product->tax->rate;
            } elseif ($product->tax_rate) {
                $itemTaxRate = $product->tax_rate;
            } else {
                $itemTaxRate = 0;
            }
            
            // Apply customer VAT status
            if ($isExempted) {
                // VAT exempted customer - no VAT on any items
                $itemTaxAmount = 0;
                $itemTaxRate = 0;
                $vatType = 'exempted';
                $vatStatus = 'exempted';
                $vatApplied = false;
                $exemptedAmount += $itemTotalExTax;
                $nonTaxableAmount += $itemTotalExTax;
                
            } elseif ($isZeroRated) {
                // Zero-rated customer - items are taxable but at 0% rate
                $itemTaxAmount = 0;
                $itemTaxRate = 0;
                $vatType = 'zero_rated';
                $vatStatus = 'zero_rated';
                $vatApplied = true; // Still considered taxable
                $zeroRatedAmount += $itemTotalExTax;
                $taxableAmount += $itemTotalExTax;
                
                // Track in zero-rated category
                if (!isset($vatByRate['zero_rated'])) {
                    $vatByRate['zero_rated'] = [
                        'rate' => 0,
                        'taxable_amount' => 0,
                        'tax_amount' => 0,
                        'type' => 'zero_rated'
                    ];
                }
                $vatByRate['zero_rated']['taxable_amount'] += $itemTotalExTax;
                
            } elseif ($isVatable && $isProductVatable && $itemTaxRate > 0) {
                // VATable customer with VATable product
                $itemTaxAmount = ($itemTotalExTax * $itemTaxRate / 100);
                $hasVatApplied = true;
                $vatType = 'standard';
                $vatStatus = 'vatable';
                $vatApplied = true;
                $taxableAmount += $itemTotalExTax;
                $taxTotal += $itemTaxAmount;
                
                // Group by VAT rate
                if (!isset($vatByRate[$itemTaxRate])) {
                    $vatByRate[$itemTaxRate] = [
                        'rate' => $itemTaxRate,
                        'taxable_amount' => 0,
                        'tax_amount' => 0,
                        'type' => 'standard'
                    ];
                }
                $vatByRate[$itemTaxRate]['taxable_amount'] += $itemTotalExTax;
                $vatByRate[$itemTaxRate]['tax_amount'] += $itemTaxAmount;
                
            } else {
                // Non-VATable product OR non-VATable customer
                $itemTaxAmount = 0;
                $itemTaxRate = 0;
                $vatType = 'none';
                $vatStatus = 'non_vatable';
                $vatApplied = false;
                $nonTaxableAmount += $itemTotalExTax;
            }
            
            $itemTotal = $itemTotalExTax + $itemTaxAmount;
            $itemPriceWithTax = $itemTotal / $quantity;
            
            $items[] = [
                'product' => $product,
                'quantity' => $quantity,
                'qty' => $quantity,
                'price' => $itemPriceWithTax,
                'price_ex_tax' => $itemPriceExTax,
                'price_with_tax' => $itemPriceWithTax,
                'total' => $itemTotal,
                'tax_rate' => $itemTaxRate,
                'tax_amount' => $itemTaxAmount,
                'is_vatable' => $isProductVatable,
                'vat_type' => $vatType,
                'vat_status' => $vatStatus,
                'vat_applied' => $vatApplied,
                'customer_vat_status' => $customerVatStatus,
            ];
            
            $subtotal += $itemTotalExTax;
        }
        
        // Calculate effective VAT rate (weighted average)
        $effectiveVatRate = $taxableAmount > 0 ? ($taxTotal / $taxableAmount) * 100 : 0;
        
        return [
            'items' => $items,
            'subtotal' => round($subtotal, 2),
            'taxTotal' => round($taxTotal, 2),
            'hasVatApplied' => $hasVatApplied,
            'taxableAmount' => round($taxableAmount, 2),
            'nonTaxableAmount' => round($nonTaxableAmount, 2),
            'exemptedAmount' => round($exemptedAmount, 2),
            'zeroRatedAmount' => round($zeroRatedAmount, 2),
            'customerVatStatus' => $customerVatStatus,
            'isVatable' => $isVatable,
            'isZeroRated' => $isZeroRated,
            'isExempted' => $isExempted,
            'effectiveVatRate' => round($effectiveVatRate, 2),
            'vatByRate' => $vatByRate
        ];
    }
    
    /**
     * Enhanced validatePaymentRequest with VAT fields
     */
    private function validatePaymentRequest(Request $request): array
    {
        $validator = Validator::make($request->all(), [
            'payment_method' => 'required|string|in:cash,mpesa,card,credit,multiple,bank',
            'amount' => 'required|numeric|min:0.01',
            'cart' => 'required|array|min:1',
            'cart.*.product_id' => 'required|exists:products,id',
            'cart.*.quantity' => 'nullable|integer|min:1',
            'cart.*.qty' => 'nullable|integer|min:1',
            'cart.*.price' => 'required|numeric|min:0',
            'cart.*.price_ex_tax' => 'nullable|numeric|min:0',
            'cart.*.tax_rate' => 'nullable|numeric|min:0|max:100',
            'cart.*.is_vatable' => 'nullable|boolean',
            'cart.*.has_vat' => 'nullable|boolean',
            'customer_id' => 'nullable|exists:customers,id',
            'customer_vat_status' => 'nullable|in:vatable,exempted,zero_rated',
            'discount' => 'nullable|numeric|min:0',
            'notes' => 'nullable|string|max:500',
            'subtotal' => 'nullable|numeric|min:0',
            'vat_amount' => 'nullable|numeric|min:0',
            'vat_rate' => 'nullable|numeric|min:0|max:100',
            'taxable_amount' => 'nullable|numeric|min:0',
            'non_taxable_amount' => 'nullable|numeric|min:0',
            'exempted_amount' => 'nullable|numeric|min:0',
            'zero_rated_amount' => 'nullable|numeric|min:0',
            'cash_received' => 'nullable|required_if:payment_method,cash|numeric|min:0',
            'change' => 'nullable|numeric|min:0',
            'mpesa_phone' => 'nullable|required_if:payment_method,mpesa|string|size:9',
            'mpesa_transaction_id' => 'nullable|string|max:100',
            'mpesa_receipt_no' => 'nullable|string|max:100',
            'card_number' => 'nullable|required_if:payment_method,card|string|size:16',
            'card_holder' => 'nullable|string|max:255',
            'bank_reference' => 'nullable|required_if:payment_method,bank|string|max:100',
            'bank_name' => 'nullable|string|max:255',
            'split_payments' => 'nullable|array',
            'hold_sale_id' => 'nullable|exists:hold_sales,id',
            'invoice_no' => 'nullable|string|max:100',
            'receipt_no' => 'nullable|string|max:100',
            'unified_number' => 'nullable|string|max:100',
        ]);
        
        if ($validator->fails()) {
            \Log::error('Payment validation failed:', $validator->errors()->toArray());
            throw new \Illuminate\Validation\ValidationException($validator);
        }
        
        $validated = $validator->validated();
        
        // Normalize quantity field
        foreach ($validated['cart'] as &$item) {
            if (isset($item['quantity']) && !isset($item['qty'])) {
                $item['qty'] = $item['quantity'];
            } elseif (isset($item['qty']) && !isset($item['quantity'])) {
                $item['quantity'] = $item['qty'];
            }
            
            if (!isset($item['qty']) && !isset($item['quantity'])) {
                $item['qty'] = $item['quantity'] = 1;
            }
            
            if (!isset($item['qty'])) {
                $item['qty'] = $item['quantity'];
            }
            if (!isset($item['quantity'])) {
                $item['quantity'] = $item['qty'];
            }
            
            // Ensure price_ex_tax is set
            if (!isset($item['price_ex_tax']) && isset($item['price'])) {
                $item['price_ex_tax'] = $item['price'];
            }
        }
        
        \Log::info('Validated payment data:', ['cart_count' => count($validated['cart']), 'cart_items' => $validated['cart']]);
        
        return $validated;
    }
    
    /**
     * Validate amount with tolerance
     */
    private function validateAmount($providedAmount, $calculatedAmount, $tolerance = 0.01): void
    {
        $difference = abs($providedAmount - $calculatedAmount);
        
        if ($difference > $tolerance) {
            throw new \Exception(
                sprintf(
                    'Amount mismatch: Provided %.2f, Calculated %.2f (Difference: %.2f)',
                    $providedAmount,
                    $calculatedAmount,
                    $difference
                )
            );
        }
    }
    
    /**
     * Handle payment method specific records
     */
    private function handlePaymentMethodRecords($method, $sale, $data, $payment)
    {
        switch ($method) {
            case 'mpesa':
                if (!empty($data['mpesa_phone']) || !empty($data['mpesa_transaction_id'])) {
                    MpesaTransaction::create([
                        'sale_id' => $sale->id,
                        'transaction_id' => $data['mpesa_transaction_id'] ?? null,
                        'receipt_no' => $data['mpesa_receipt_no'] ?? null,
                        'phone' => $data['mpesa_phone'] ?? null,
                        'amount' => $sale->grand_total,
                        'status' => 'completed',
                        'payment_id' => $payment->id,
                        'transaction_date' => now(),
                    ]);
                }
                break;
        }
    }
    
    /**
     * Update customer purchase history
     */
    private function updateCustomerPurchase($customerId, $amount)
    {
        $customer = Customer::find($customerId);
        if ($customer) {
            $customer->total_purchases += $amount;
            $customer->last_purchase_date = now();
            $customer->save();
        }
    }
    
    /**
     * Generate payment reference
     */
    private function generatePaymentReference($method)
    {
        return strtoupper($method) . '-' . now()->format('Ymd') . '-' . Str::random(6);
    }
    
    /**
     * Get payment details for meta field
     */
    private function getPaymentDetails($data)
    {
        $details = [];
        
        switch ($data['payment_method']) {
            case 'cash':
                $details = [
                    'cash_received' => $data['cash_received'] ?? null,
                    'change' => $data['change'] ?? null,
                ];
                break;
            case 'mpesa':
                $details = [
                    'mpesa_phone' => $data['mpesa_phone'] ?? null,
                    'mpesa_transaction_id' => $data['mpesa_transaction_id'] ?? null,
                    'mpesa_receipt_no' => $data['mpesa_receipt_no'] ?? null,
                ];
                break;
            case 'card':
                $details = [
                    'card_last4' => !empty($data['card_number']) ? substr($data['card_number'], -4) : null,
                    'card_holder' => $data['card_holder'] ?? null,
                ];
                break;
            case 'bank':
                $details = [
                    'bank_reference' => $data['bank_reference'] ?? null,
                    'bank_name' => $data['bank_name'] ?? null,
                ];
                break;
        }
        
        return json_encode($details);
    }
    
    /**
     * Generate receipt data from sale
     */
    private function generateReceiptData(Sale $sale): array
    {
        $sale->load(['items.product', 'customer', 'user']);
        
        $items = [];
        foreach ($sale->items as $item) {
            $items[] = [
                'name' => $item->product->name ?? 'Product',
                'quantity' => $item->qty,
                'unit_price' => $item->price,
                'unit_price_ex_tax' => $item->price_ex_tax,
                'total' => $item->total,
                'tax_rate' => $item->tax_rate,
                'tax_amount' => $item->tax_amount,
                'vat_status' => $item->vat_status,
                'is_vatable' => $item->tax_rate > 0,
            ];
        }
        
        $paymentDetails = [
            'method' => $sale->payment_method,
            'amount_paid' => $sale->grand_total,
            'transaction_id' => $sale->transaction_id,
        ];
        
        if ($sale->payment_method === 'cash') {
            $paymentDetails['cash_received'] = $sale->cash_received;
            $paymentDetails['change'] = $sale->customer_change;
        }
        
        // VAT breakdown
        $vatBreakdown = json_decode($sale->vat_by_rate, true) ?: [];
        
        return [
            'unified_number' => $sale->unified_number ?? $sale->invoice_no,
            'invoice_no' => $sale->invoice_no,
            'receipt_no' => $sale->receipt_no,
            'date' => $sale->created_at->format('Y-m-d'),
            'time' => $sale->created_at->format('H:i:s'),
            'customer' => $sale->customer ? [
                'name' => $sale->customer->name,
                'phone' => $sale->customer->phone,
                'email' => $sale->customer->email,
                'vat_number' => $sale->customer->vat_number,
                'pin' => $sale->customer->pin,
                'company_name' => $sale->customer->company_name,
                'address' => $sale->customer->address,
                'vat_status' => $sale->customer->vat_status,
            ] : null,
            'items' => $items,
            'totals' => [
                'subtotal' => $sale->subtotal,
                'discount' => $sale->discount,
                'vat_amount' => $sale->tax_total,
                'tax_total' => $sale->tax_total,
                'grand_total' => $sale->grand_total,
                'taxable_amount' => $sale->taxable_amount,
                'non_taxable_amount' => $sale->non_taxable_amount,
                'exempted_amount' => $sale->exempted_amount,
                'zero_rated_amount' => $sale->zero_rated_amount,
            ],
            'vat_breakdown' => $vatBreakdown,
            'customer_vat_status' => $sale->customer_vat_status,
            'payment' => $paymentDetails,
            'store' => [
                'name' => config('app.name', 'Kenyan Supermarket'),
                'address' => config('app.address', 'Nairobi CBD'),
                'phone' => config('app.phone', '0700 000 000'),
                'email' => config('app.email', 'info@supermarket.co.ke'),
                'pin' => config('app.pin', 'P051234567N'),
                'vat_number' => config('app.vat_number', 'VAT001234567'),
            ],
            'cashier' => $sale->user->name ?? 'Cashier',
            'autoprint' => request()->has('autoprint'),
        ];
    }
    
    // ==================== OTHER PAYMENT METHODS ====================
    
    /**
     * Get available payment methods
     */
    public function getPaymentMethods()
    {
        try {
            $methods = PaymentMethod::where('is_active', true)
                ->orderBy('order')
                ->get();
            
            return response()->json([
                'success' => true,
                'methods' => $methods
            ]);
        } catch (\Exception $e) {
            Log::error('Failed to get payment methods:', ['error' => $e->getMessage()]);
            return response()->json([
                'success' => false,
                'message' => 'Failed to get payment methods'
            ], 500);
        }
    }
    
    /**
     * Download receipt as PDF
     */
    public function downloadReceipt($identifier)
    {
        try {
            $sale = Sale::where('unified_number', $identifier)
                ->orWhere('invoice_no', $identifier)
                ->orWhere('receipt_no', $identifier)
                ->firstOrFail();
            
            // Here you would generate PDF using your PDF library
            // For now, return JSON with receipt data
            return response()->json([
                'success' => true,
                'receipt_data' => $this->generateReceiptData($sale),
                'download_url' => url("/pos/receipt/print/{$sale->unified_number}"),
            ]);
        } catch (\Exception $e) {
            Log::error('Failed to download receipt:', ['error' => $e->getMessage()]);
            return response()->json([
                'success' => false,
                'message' => 'Receipt not found'
            ], 404);
        }
    }
    
    /**
     * Emergency route to fix unified number for existing sales
     */
    public function fixUnifiedNumbers(Request $request)
    {
        try {
            $date = $request->input('date', now()->format('Y-m-d'));
            $sales = Sale::whereDate('created_at', $date)
                ->whereNull('unified_number')
                ->orderBy('id')
                ->get();
            
            $fixed = 0;
            
            foreach ($sales as $sale) {
                // Create unified number from invoice_no if possible
                if ($sale->invoice_no && preg_match('/(\d{8})-(\d{4})/', $sale->invoice_no, $matches)) {
                    $unifiedNumber = 'INVRCP-' . $matches[1] . '-' . $matches[2];
                } else {
                    // Generate new unified number based on sale date
                    $saleDate = $sale->created_at->format('Ymd');
                    $counter = Sale::whereDate('created_at', $sale->created_at->toDateString())
                        ->where('id', '<=', $sale->id)
                        ->count();
                    
                    $unifiedNumber = 'INVRCP-' . $saleDate . '-' . str_pad($counter, 4, '0', STR_PAD_LEFT);
                }
                
                $sale->unified_number = $unifiedNumber;
                $sale->save();
                $fixed++;
                
                Log::info('🔧 Fixed unified number for sale:', [
                    'sale_id' => $sale->id,
                    'unified_number' => $unifiedNumber,
                    'old_invoice_no' => $sale->invoice_no
                ]);
            }
            
            return response()->json([
                'success' => true,
                'message' => "Fixed $fixed sales with unified numbers",
                'fixed_count' => $fixed
            ]);
            
        } catch (\Exception $e) {
            Log::error('Failed to fix unified numbers:', ['error' => $e->getMessage()]);
            return response()->json([
                'success' => false,
                'message' => 'Failed to fix unified numbers'
            ], 500);
        }
    }
}