<?php

namespace App\Http\Controllers\Sales;

use App\Http\Controllers\Controller;
use App\Models\Commission;
use App\Models\Customer;
use App\Models\Payment;
use App\Models\Sale;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use PDF;

class PaymentController extends Controller
{
    public function index()
    {
        $customers = Customer::where('sales_rep_id', Auth::id())
            ->with(['sales'])
            ->get();
            
        // Filter only those with outstanding > 1.00 (tolerance)
        $customers = $customers->filter(function($c) {
            $c->outstanding = $c->sales->sum('balance_due');
            return $c->outstanding > 1;
        });

        return view('sales.payments.index', compact('customers'));
    }

    public function create(Request $request)
    {
        $customerId = $request->get('customer_id');
        $selectedCustomer = null;
        
        $customers = Customer::where('sales_rep_id', Auth::id())->get();
        
        if ($customerId) {
            $selectedCustomer = Customer::with('sales')->find($customerId);
            if($selectedCustomer) {
                // Determine outstanding
                $selectedCustomer->outstanding = $selectedCustomer->sales->sum('balance_due');
            }
        }

        return view('sales.payments.create', compact('customers', 'selectedCustomer'));
    }

    public function store(Request $request)
    {
        $request->validate([
            'customer_id' => 'required|exists:customers,id',
            'amount' => 'required|numeric|min:1',
            'method' => 'required|in:Cash,Cheque',
            // Cheque validation
            'bank_name' => 'nullable|required_if:method,Cheque|string|max:255',
            'cheque_number' => 'nullable|required_if:method,Cheque|string|max:50',
            'cheque_date' => 'nullable|required_if:method,Cheque|date',
            'cheque_image' => 'nullable|image|max:4096', // Max 4MB
        ]);

        $rep = Auth::user();
        $customerId = $request->customer_id;
        $amount = $request->amount;
        $method = $request->method;
        
        // Cheque Data
        $bankName = $request->bank_name;
        $chequeNumber = $request->cheque_number;
        $chequeDate = $request->cheque_date;
        $chequeImagePath = null;

        if ($request->hasFile('cheque_image')) {
            $chequeImagePath = $request->file('cheque_image')->store('cheques', 'public');
        }

        $allocatedAmount = 0;
        $processedSales = [];
        $paymentIds = []; // Track created payment IDs to pass to receipt
        
        $publicToken = \Illuminate\Support\Str::random(32);
        $receiptNumber = 'REC-' . now()->timestamp . '-' . $rep->id;

        DB::transaction(function() use ($rep, $customerId, $amount, $method, $bankName, $chequeNumber, $chequeDate, $chequeImagePath, $publicToken, $receiptNumber, &$allocatedAmount, &$processedSales, &$paymentIds) {
            
            // 1. Get Unpaid Sales (FIFO)
            $sales = Sale::where('customer_id', $customerId)
                        ->where('balance_due', '>', 0.01)
                        ->orderBy('created_at', 'asc') // FIFO
                        ->get();

            $remainingPayment = $amount;
            
            // If no sales found... logic
            
            foreach ($sales as $sale) {
                if ($remainingPayment <= 0) break;

                $due = $sale->balance_due;
                $payAmount = 0;

                $previousDue = $due; // For receipt

                if ($remainingPayment >= $due) {
                    // Full Pay for this sale
                    $payAmount = $due;
                    $remainingPayment -= $due;
                    
                    $sale->balance_due = 0;
                    $sale->payment_status = 'paid';
                } else {
                    // Partial Pay
                    $payAmount = $remainingPayment;
                    $remainingPayment = 0;
                    
                    $sale->balance_due -= $payAmount;
                    $sale->payment_status = 'partial';
                }

                $sale->save();

                $payment = Payment::create([
                    'sale_id' => $sale->id,
                    'customer_id' => $customerId,
                    'amount' => $payAmount,
                    'method' => $method,
                    'payment_date' => now(),
                    'collected_by' => $rep->id,
                    'bank_name' => $bankName,
                    'cheque_number' => $chequeNumber,
                    'cheque_date' => $chequeDate,
                    'cheque_image_path' => $chequeImagePath,
                    'cheque_status' => ($method === 'Cheque') ? 'pending' : null,
                    'public_token' => $publicToken,
                    'receipt_number' => $receiptNumber,
                ]);

                $paymentIds[] = $payment->id;

                // 3. Calculate Commission (Per Payment Portion)
                $commissionRate = 0;
                
                if ($method === 'Cash') {
                    // Check if settlement is within 24 hours of Sale Creation
                    // Note: This relies on $sale->created_at.
                    $hoursDiff = $sale->created_at->diffInHours(now());
                    
                    if ($hoursDiff <= 24) {
                        // "Cash Sale" Commission
                        $commissionRate = $rep->commission_cash ?? 0;
                    } else {
                        // "Credit Payment" Collection Commission
                        $commissionRate = $rep->commission_credit ?? 0;
                    }
                } elseif ($method === 'Cheque') {
                    $commissionRate = $rep->commission_cheque ?? 0;
                }
                
                $commAmount = $payAmount * ($commissionRate / 100);

                if ($commAmount > 0) {
                    Commission::create([
                        'sales_rep_id' => $rep->id,
                        'sale_id' => $sale->id,
                        'payment_id' => $payment->id,
                        'commission_amount' => $commAmount,
                        'percentage' => $commissionRate,
                        'status' => ($method === 'Cash') ? 'approved' : 'pending', 
                    ]);
                }

                $allocatedAmount += $payAmount;
                $processedSales[] = [
                    'invoice' => $sale->invoice_number,
                    'paid' => $payAmount,
                    'prev_due' => $previousDue,
                    'remaining' => $sale->balance_due
                ];
            }

            // 4. Send Receipt SMS
            try {
                $customer = Customer::find($customerId);
                if ($customer && $customer->mobile) {
                    $notify = new \App\Services\NotifyLKService();
                    // Generate public link
                    $link = route('public.receipt.show', $publicToken);
                    
                    // "Payment Received - (link)"
                    $message = "Payment Received LKR {$amount} - {$link}";
                    
                    $notify->sendSMS($customer->mobile, $message);
                }
            } catch (\Exception $e) {
                \Illuminate\Support\Facades\Log::error("SMS Sending Failed (Receipt): " . $e->getMessage());
            }
        });

        // Store receipt data in session flash to display in receipt view
        // Or redirect to a route with IDs.
        // Let's redirect to a receipt show page with the Customer ID and Payment IDs reference.
        // We can pass the payment IDs as a query param or session.
        
        return redirect()->route('sales.payments.receipt', ['ids' => implode(',', $paymentIds)])
                         ->with('success', 'Payment processed successfully. SMS Sent.');
    }

    public function receipt(Request $request)
    {
        $ids = explode(',', $request->query('ids'));
        $payments = Payment::whereIn('id', $ids)->with(['sale', 'customer', 'collector'])->get();

        if ($payments->isEmpty()) {
            return redirect()->route('sales.payments.index')->with('error', 'Receipt not found.');
        }

        $customer = $payments->first()->customer;
        // Load ALL sales to calculate total outstanding properly
        $customer->load('sales');
        $customer->current_outstanding = $customer->sales->sum('balance_due');
        
        $collector = $payments->first()->collector;
        $totalPaid = $payments->sum('amount');
        
        // Paid Allocations
        $allocations = $payments->map(function($p) {
            return [
                'invoice' => $p->sale->invoice_number,
                'amount' => $p->amount,
                'sale_balance_after' => $p->sale->balance_due
            ];
        });

        // Other Unpaid Invoices (Excluding the ones we just paid FULLY, if any remain in 'sales' collection?)
        // The payments collection has sales. The customer->sales has ALL.
        // We want to list other invoices that still have balance > 0
        $otherUnpaid = $customer->sales->where('balance_due', '>', 0.01);

        $data = compact('payments', 'customer', 'collector', 'totalPaid', 'allocations', 'otherUnpaid');

        if ($request->has('download') && $request->download == 'pdf') {
            $pdf = PDF::loadView('sales.payments.receipt_pdf', $data);
            return $pdf->download('receipt_' . $customer->id . '_' . time() . '.pdf');
        }

        return view('sales.payments.receipt', $data);
    }
}
