<?php

namespace App\Http\Controllers;

use App\Models\Sale;
use App\Models\SaleItem;
use App\Models\Payment;
use App\Models\Customer;
use App\Models\Product;
use App\Models\ProductBatch;
use App\Models\BatchStockMovement;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;

class SaleController extends Controller
{
    /**
     * Process and save sale transaction
     */
    public function processSale(Request $request)
    {
        DB::beginTransaction();
        
        try {
            $validated = $this->validateSaleRequest($request);
            
            // Generate invoice number
            $invoiceNo = $this->generateInvoiceNumber();
            
            // Calculate totals
            $totals = $this->calculateSaleTotals($validated['items']);
            
            // Check customer if exists
            $customer = null;
            if (!empty($validated['customer_id'])) {
                $customer = Customer::find($validated['customer_id']);
            }
            
            // Create sale record
            $sale = $this->createSaleRecord($validated, $invoiceNo, $totals, $customer);
            
            // Process sale items
            $this->processSaleItems($validated['items'], $sale, $invoiceNo);
            
            // Process payment
            $this->processPayment($validated, $sale, $totals['grand_total'], $customer);
            
            // Update stock
            $this->updateStock($validated['items']);
            
            // Update customer statistics if exists
            if ($customer) {
                $this->updateCustomerStats($customer, $totals['grand_total']);
            }
            
            DB::commit();
            
            return response()->json([
                'success' => true,
                'sale' => [
                    'id' => $sale->id,
                    'invoice_no' => $sale->invoice_no,
                    'grand_total' => $sale->grand_total,
                    'customer_id' => $sale->customer_id,
                    'customer_name' => $customer ? $customer->name : 'Walk-in Customer',
                    'change' => $validated['cash_received'] - $totals['grand_total'],
                    'payment_method' => $validated['payment_method'],
                    'vat_included' => $validated['include_vat'] ?? true,
                    'vat_amount' => $totals['vat_amount'],
                    'receipt_data' => $this->prepareReceiptData($sale, $validated, $customer, $totals),
                ]
            ]);
            
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Sale Processing Error: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'error' => $e->getMessage()
            ], 500);
        }
    }
    
    /**
     * Validate sale request
     */
    private function validateSaleRequest(Request $request)
    {
        return $request->validate([
            'customer_id' => 'nullable|exists:customers,id',
            'items' => 'required|array|min:1',
            'items.*.product_id' => 'required|exists:products,id',
            'items.*.quantity' => 'required|numeric|min:0.001',
            'items.*.unit_price' => 'required|numeric|min:0',
            'items.*.batch_id' => 'nullable|exists:product_batches,id',
            'items.*.vat_included' => 'nullable|boolean',
            'discount_amount' => 'nullable|numeric|min:0',
            'discount_percent' => 'nullable|numeric|min:0|max:100',
            'include_vat' => 'required|boolean',
            'payment_method' => 'required|in:cash,card,mpesa,bank_transfer,credit,multiple',
            'cash_received' => 'nullable|required_if:payment_method,cash|numeric|min:0',
            'cash_amount' => 'nullable|numeric|min:0',
            'mpesa_amount' => 'nullable|numeric|min:0',
            'card_amount' => 'nullable|numeric|min:0',
            'mpesa_phone' => 'nullable|string|max:20',
            'mpesa_transaction_id' => 'nullable|string|max:100',
            'card_transaction_id' => 'nullable|string|max:100',
            'bank_reference' => 'nullable|string|max:100',
            'notes' => 'nullable|string|max:1000',
            'print_receipt' => 'nullable|boolean',
            'receipt_type' => 'nullable|in:thermal,normal,both',
        ]);
    }
    
    /**
     * Calculate sale totals with VAT
     */
    private function calculateSaleTotals(array $items): array
    {
        $subtotal = 0;
        $vatableAmount = 0;
        $vatAmount = 0;
        
        foreach ($items as $item) {
            $product = Product::find($item['product_id']);
            $itemTotal = $item['quantity'] * $item['unit_price'];
            $subtotal += $itemTotal;
            
            if ($product && $product->has_vat && ($item['vat_included'] ?? true)) {
                $vatableAmount += $itemTotal;
            }
        }
        
        // Default VAT rate (can be configurable)
        $vatRate = 16.00; // 16% VAT in Kenya
        
        $vatAmount = $vatableAmount * ($vatRate / 100);
        
        $grandTotal = $subtotal + $vatAmount;
        
        return [
            'subtotal' => $subtotal,
            'vatable_amount' => $vatableAmount,
            'vat_amount' => $vatAmount,
            'vat_rate' => $vatRate,
            'grand_total' => $grandTotal,
        ];
    }
    
    /**
     * Generate invoice number
     */
    private function generateInvoiceNumber(): string
    {
        $prefix = 'INV';
        $year = date('Y');
        $month = date('m');
        
        $lastInvoice = Sale::whereYear('created_at', $year)
            ->whereMonth('created_at', $month)
            ->orderBy('id', 'desc')
            ->first();
        
        $sequence = $lastInvoice ? (int) substr($lastInvoice->invoice_no, -5) + 1 : 1;
        
        return sprintf('%s-%s%s-%05d', $prefix, $year, $month, $sequence);
    }
    
    /**
     * Create sale record
     */
    private function createSaleRecord(array $data, string $invoiceNo, array $totals, $customer): Sale
    {
        $saleData = [
            'customer_id' => $customer ? $customer->id : null,
            'invoice_no' => $invoiceNo,
            'sale_date' => now(),
            'subtotal' => $totals['subtotal'],
            'vat_amount' => $totals['vat_amount'],
            'vat_rate' => $totals['vat_rate'],
            'grand_total' => $totals['grand_total'],
            'vat_included' => $data['include_vat'] ?? true,
            'status' => 'completed',
            'payment_status' => 'paid',
            'payment_method' => $data['payment_method'],
            'notes' => $data['notes'] ?? null,
            'created_by' => Auth::id(),
            'discount_amount' => $data['discount_amount'] ?? 0,
            'discount_percent' => $data['discount_percent'] ?? 0,
            'cash_received' => $data['cash_received'] ?? 0,
            'change' => isset($data['cash_received']) ? $data['cash_received'] - $totals['grand_total'] : 0,
        ];
        
        return Sale::create($saleData);
    }
    
    /**
     * Process sale items
     */
    private function processSaleItems(array $items, Sale $sale, string $invoiceNo): void
    {
        foreach ($items as $item) {
            $product = Product::findOrFail($item['product_id']);
            
            // Calculate item tax
            $itemTotal = $item['quantity'] * $item['unit_price'];
            $taxAmount = 0;
            
            if ($product->has_vat) {
                $taxRate = $product->tax_rate;
                if ($sale->vat_included) {
                    $taxAmount = $itemTotal * ($taxRate / (100 + $taxRate));
                } else {
                    $taxAmount = $itemTotal * ($taxRate / 100);
                }
            }
            
            // Create sale item
            SaleItem::create([
                'sale_id' => $sale->id,
                'product_id' => $product->id,
                'product_name' => $product->name,
                'sku' => $product->sku,
                'quantity' => $item['quantity'],
                'unit_price' => $item['unit_price'],
                'tax_percent' => $product->tax_rate,
                'tax_amount' => $taxAmount,
                'total' => $itemTotal,
                'batch_id' => $item['batch_id'] ?? null,
                'batch_number' => $item['batch_id'] ? ProductBatch::find($item['batch_id'])->batch_number : null,
            ]);
        }
    }
    
    /**
     * Process payment
     */
    private function processPayment(array $data, Sale $sale, float $grandTotal, $customer): void
    {
        $paymentData = [
            'sale_id' => $sale->id,
            'customer_id' => $customer ? $customer->id : null,
            'amount' => $grandTotal,
            'payment_method' => $data['payment_method'],
            'reference' => $sale->invoice_no,
            'status' => 'completed',
            'payment_date' => now(),
            'received_by' => Auth::id(),
            'notes' => $data['notes'] ?? null,
        ];
        
        // Add payment-specific details
        switch ($data['payment_method']) {
            case 'cash':
                $paymentData['cash_received'] = $data['cash_received'];
                $paymentData['change'] = $data['cash_received'] - $grandTotal;
                break;
                
            case 'mpesa':
                $paymentData['transaction_id'] = $data['mpesa_transaction_id'] ?? null;
                $paymentData['phone'] = $data['mpesa_phone'] ?? null;
                break;
                
            case 'card':
                $paymentData['transaction_id'] = $data['card_transaction_id'] ?? null;
                break;
                
            case 'bank_transfer':
                $paymentData['bank_reference'] = $data['bank_reference'] ?? null;
                break;
        }
        
        Payment::create($paymentData);
    }
    
    /**
     * Update stock
     */
    private function updateStock(array $items): void
    {
        foreach ($items as $item) {
            $product = Product::findOrFail($item['product_id']);
            
            // Check if product tracks inventory
            if ($product->track_inventory) {
                $quantity = $item['quantity'];
                
                // Update product stock
                $product->decrement('stock', $quantity);
                
                // Update batch if provided
                if (!empty($item['batch_id'])) {
                    $batch = ProductBatch::find($item['batch_id']);
                    if ($batch) {
                        $batch->decrement('current_quantity', $quantity);
                    }
                }
            }
        }
    }
    
    /**
     * Update customer statistics
     */
    private function updateCustomerStats(Customer $customer, float $amount): void
    {
        $customer->increment('total_orders');
        $customer->increment('total_spent', $amount);
        $customer->last_purchase_date = now();
        $customer->save();
    }
    
    /**
     * Prepare receipt data
     */
    private function prepareReceiptData(Sale $sale, array $data, $customer, array $totals): array
    {
        $storeSettings = $this->getStoreSettings();
        
        return [
            'store' => [
                'name' => $storeSettings['store_name'],
                'address' => $storeSettings['store_address'],
                'phone' => $storeSettings['store_phone'],
                'vat_number' => $storeSettings['vat_number'],
            ],
            'sale' => [
                'invoice_no' => $sale->invoice_no,
                'date' => $sale->sale_date->format('Y-m-d H:i:s'),
                'cashier' => Auth::user()->name,
            ],
            'customer' => $customer ? [
                'name' => $customer->name,
                'phone' => $customer->phone,
                'vat_number' => $customer->vat_number,
            ] : null,
            'items' => $sale->items->map(function($item) {
                return [
                    'name' => $item->product_name,
                    'quantity' => $item->quantity,
                    'unit_price' => $item->unit_price,
                    'total' => $item->total,
                    'vat' => $item->tax_amount > 0 ? 'Yes' : 'No',
                ];
            }),
            'totals' => [
                'subtotal' => $sale->subtotal,
                'vat' => $sale->vat_amount,
                'discount' => $sale->discount_amount,
                'total' => $sale->grand_total,
                'paid' => $data['cash_received'] ?? $sale->grand_total,
                'change' => $data['cash_received'] ? $data['cash_received'] - $sale->grand_total : 0,
            ],
            'payment' => [
                'method' => $sale->payment_method,
                'status' => $sale->payment_status,
                'cash_received' => $sale->cash_received,
                'change' => $sale->change,
            ],
            'footer' => $storeSettings['receipt_footer'],
        ];
    }
    
    /**
     * Get store settings
     */
    private function getStoreSettings(): array
    {
        return [
            'store_name' => config('app.name', 'POS Store'),
            'store_address' => config('pos.store_address', ''),
            'store_phone' => config('pos.store_phone', ''),
            'vat_number' => config('pos.vat_number', ''),
            'receipt_footer' => config('pos.receipt_footer', 'Thank you for your business!'),
        ];
    }
    
    /**
     * Get sales report
     */
    public function getSalesReport(Request $request)
    {
        try {
            $startDate = $request->input('start_date', now()->startOfDay());
            $endDate = $request->input('end_date', now()->endOfDay());
            $paymentMethod = $request->input('payment_method');
            $customerId = $request->input('customer_id');
            
            $query = Sale::with(['customer', 'items.product', 'payments'])
                ->whereBetween('sale_date', [$startDate, $endDate])
                ->where('status', 'completed');
            
            if ($paymentMethod) {
                $query->where('payment_method', $paymentMethod);
            }
            
            if ($customerId) {
                $query->where('customer_id', $customerId);
            }
            
            $sales = $query->orderBy('sale_date', 'desc')->get();
            
            // Summary statistics
            $summary = [
                'total_sales' => $sales->count(),
                'total_revenue' => $sales->sum('grand_total'),
                'total_vat' => $sales->sum('vat_amount'),
                'total_discount' => $sales->sum('discount_amount'),
                'avg_sale' => $sales->avg('grand_total'),
                'payment_methods' => $sales->groupBy('payment_method')
                    ->map(function($group) {
                        return [
                            'count' => $group->count(),
                            'total' => $group->sum('grand_total'),
                        ];
                    }),
            ];
            
            return response()->json([
                'success' => true,
                'sales' => $sales,
                'summary' => $summary,
            ]);
            
        } catch (\Exception $e) {
            Log::error('Sales Report Error: ' . $e->getMessage());
            return response()->json(['success' => false, 'error' => 'Failed to generate report'], 500);
        }
    }
    
    /**
     * Get sale by ID
     */
    public function getSale($id)
    {
        try {
            $sale = Sale::with(['customer', 'items.product', 'payments'])->findOrFail($id);
            
            return response()->json([
                'success' => true,
                'sale' => $sale,
            ]);
            
        } catch (\Exception $e) {
            Log::error('Get Sale Error: ' . $e->getMessage());
            return response()->json(['success' => false, 'error' => 'Sale not found'], 404);
        }
    }
    
    /**
     * Refund sale
     */
    public function refundSale(Request $request, $id)
    {
        DB::beginTransaction();
        
        try {
            $sale = Sale::with('items')->findOrFail($id);
            
            // Create refund record
            $refundData = [
                'original_sale_id' => $sale->id,
                'invoice_no' => 'REFUND-' . $sale->invoice_no,
                'sale_date' => now(),
                'subtotal' => -$sale->subtotal,
                'vat_amount' => -$sale->vat_amount,
                'grand_total' => -$sale->grand_total,
                'status' => 'refunded',
                'payment_status' => 'refunded',
                'payment_method' => $sale->payment_method,
                'notes' => $request->input('notes', 'Sale refund'),
                'created_by' => Auth::id(),
            ];
            
            $refundSale = Sale::create($refundData);
            
            // Create refund items
            foreach ($sale->items as $item) {
                $refundItem = $item->replicate();
                $refundItem->sale_id = $refundSale->id;
                $refundItem->quantity = -$item->quantity;
                $refundItem->total = -$item->total;
                $refundItem->tax_amount = -$item->tax_amount;
                $refundItem->save();
                
                // Restock product
                $product = Product::find($item->product_id);
                if ($product && $product->track_inventory) {
                    $product->increment('stock', abs($refundItem->quantity));
                    
                    // Restore batch if exists
                    if ($item->batch_id) {
                        $batch = ProductBatch::find($item->batch_id);
                        if ($batch) {
                            $batch->increment('current_quantity', abs($refundItem->quantity));
                        }
                    }
                }
            }
            
            // Create refund payment
            Payment::create([
                'sale_id' => $refundSale->id,
                'amount' => -$sale->grand_total,
                'payment_method' => $sale->payment_method,
                'reference' => 'REFUND-' . $sale->invoice_no,
                'status' => 'refunded',
                'payment_date' => now(),
                'received_by' => Auth::id(),
                'notes' => 'Refund for sale ' . $sale->invoice_no,
            ]);
            
            // Update original sale status
            $sale->update(['status' => 'refunded', 'refunded_at' => now()]);
            
            DB::commit();
            
            return response()->json([
                'success' => true,
                'message' => 'Sale refunded successfully',
                'refund' => $refundSale,
            ]);
            
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Refund Sale Error: ' . $e->getMessage());
            return response()->json(['success' => false, 'error' => 'Failed to refund sale'], 500);
        }
    }
    // In your SaleController todayStats method:
public function todayStats()
{
    $today = now()->format('Y-m-d');
    
    $stats = Sale::whereDate('created_at', $today)
        ->where('status', 'completed')
        ->selectRaw('COUNT(*) as total_sales')
        ->selectRaw('SUM(grand_total) as total_revenue')
        ->selectRaw('SUM(vat_amount) as total_vat')
        ->selectRaw('SUM(discount_amount) as total_discount')
        ->selectRaw('SUM(cash_received) as total_cash_received')
        ->selectRaw('SUM(change_amount) as total_change') // Renamed from 'change'
        ->selectRaw('AVG(grand_total) as average_sale')
        ->first();
    
    return response()->json([
        'success' => true,
        'data' => $stats
    ]);
}
}