<?php

namespace App\Livewire\Accounting;

use App\Models\Partner;
use App\Models\PartnerPayment;
use App\Models\PaymentMethod;
use App\Models\PurchaseOrder;
use App\Services\AccountingService;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Livewire\Component;

class SupplierPayments extends Component
{

    public $search = '';
    public $dateFrom;
    public $dateTo;
    
    // Payment Modal
    public $showPaymentModal = false;
    public ?Partner $selectedSupplier = null;
    public $calculatedBalance = 0;
    public $amount;
    public $paymentMethodId;
    public $paymentDate;
    public $notes;
    public $referenceNumber;
    
    // Manual vs PO Selection
    public $paymentType = 'manual'; // manual, po_selection
    public $selectedPos = []; // [po_id => amount_to_pay]
    public $supplierPos = [];

    // History Modal
    public $showHistoryModal = false;
    public $supplierHistory = [];

    protected $listeners = ['refreshComponent' => '$refresh'];

    public function mount()
    {
        $this->dateFrom = Carbon::now()->startOfMonth()->format('Y-m-d');
        $this->dateTo = Carbon::now()->endOfMonth()->format('Y-m-d');
        $this->paymentDate = date('Y-m-d');
    }

    public function updatedSearch()
    {
        // No resetPage() needed as pagination is removed
    }

    public function openPaymentModal(Partner $supplier)
    {
        $this->selectedSupplier = $supplier;
        
        // Calculate actual balance from journal entries (AP account)
        $apAccount = \App\Models\Account::where('code', 
            \App\Services\AccountingService::ACCOUNTS_PAYABLE
        )->first();
        
        if ($apAccount) {
            $debit = $supplier->journalEntryLines()
                ->where('account_id', $apAccount->id)
                ->sum('debit');
            $credit = $supplier->journalEntryLines()
                ->where('account_id', $apAccount->id)
                ->sum('credit');
            
            // AP: Credit increases (we owe them), Debit decreases (we paid)
            $this->calculatedBalance = $credit - $debit;
        } else {
            $this->calculatedBalance = 0;
        }
        
        $this->amount = $this->calculatedBalance > 0 ? $this->calculatedBalance : 0;
        $this->paymentMethodId = PaymentMethod::where('is_active', true)->first()?->id;
        $this->paymentDate = date('Y-m-d');
        $this->notes = '';
        $this->referenceNumber = '';
        
        // Load Open POs
        $this->supplierPos = PurchaseOrder::where('partner_id', $supplier->id)
            ->whereIn('status', ['received', 'partial']) // simplified
            // ->where('payment_status', '!=', 'paid') // if we had payment_status
            ->orderBy('created_at', 'desc')
            ->get();
            
        $this->selectedPos = [];
        $this->paymentType = 'manual';
        $this->showPaymentModal = true;
    }

    public function updatedSelectedPos()
    {
        // Auto-calculate amount if functionality enables
    }

    public function closePaymentModal()
    {
        $this->showPaymentModal = false;
        $this->reset(['selectedSupplier', 'amount', 'paymentMethodId', 'notes', 'referenceNumber', 'selectedPos', 'supplierPos']);
    }

    public function createPayment(AccountingService $accountingService)
    {
        $this->validate([
            'amount' => 'required|numeric|min:0.01',
            'paymentMethodId' => 'required|exists:payment_methods,id',
            'paymentDate' => 'required|date',
            'notes' => 'nullable|string',
        ]);

        try {
            DB::beginTransaction();

            // Create Payment Record
            $payment = PartnerPayment::create([
                'partner_id' => $this->selectedSupplier->id,
                'branch_id' => auth()->user()->branch_id,
                'user_id' => auth()->id(),
                'payment_method_id' => $this->paymentMethodId,
                'amount' => $this->amount, // Amount we PAY
                'payment_date' => $this->paymentDate,
                'notes' => $this->notes,
                'status' => 'completed',
            ]);

            // Process Selected Purchase Orders
            $paymentMethod = PaymentMethod::find($this->paymentMethodId);
            $paymentMethodCode = $paymentMethod->code ?? 'cash';

            if (!empty($this->selectedPos)) {
                foreach ($this->selectedPos as $poId => $amountToPay) {
                    $amountToPay = floatval($amountToPay);
                    if ($amountToPay > 0) {
                        $po = PurchaseOrder::find($poId);
                        if ($po) {
                            \App\Models\PurchasePayment::create([
                                'purchase_order_id' => $po->id,
                                'amount' => $amountToPay,
                                'payment_date' => $this->paymentDate,
                                'payment_method' => $paymentMethodCode,
                                'reference' => 'SUP-' . $payment->payment_number,
                                'notes' => 'Allocated from Supplier Payment',
                                'user_id' => auth()->id(),
                            ]);
                            
                            // Update PO Status
                            $totalPaid = $po->payments()->sum('amount');
                            if ($totalPaid >= ($po->total - 0.01)) {
                                $po->update(['payment_status' => 'paid']);
                            } else {
                                $po->update(['payment_status' => 'partial']);
                            }
                        }
                    }
                }
            }

            // Create Journal Entry
            $accountingService->createSupplierPaymentJournalEntry($payment);

            // Update Partner Balance
            // We pay -> Liability decreases.
            // Since Balance is Negative for Liability (We owe them), we INCREMENT (add positive payment) to move it towards 0.
            $this->selectedSupplier->increment('current_balance', $this->amount);

            DB::commit();

            $this->closePaymentModal();
            $this->dispatch('refreshComponent');
            session()->flash('success', __('Payment recorded successfully.'));

        } catch (\Exception $e) {
            DB::rollBack();
            session()->flash('error', __('Error recording payment: ') . $e->getMessage());
        }
    }

    public function viewHistory(Partner $partner)
    {
        $this->selectedSupplier = $partner;
        $this->supplierHistory = PartnerPayment::where('partner_id', $partner->id)
            ->with(['paymentMethod', 'user'])
            ->latest()
            ->take(20)
            ->get();
        $this->showHistoryModal = true;
    }

    public function closeHistoryModal()
    {
        $this->showHistoryModal = false;
        $this->selectedSupplier = null;
        $this->supplierHistory = [];
    }

    public function render()
    {
        // Get AP account for aggregations
        $apAccount = \App\Models\Account::where('code', 
            \App\Services\AccountingService::ACCOUNTS_PAYABLE
        )->first();
        
        $suppliers = Partner::query()
            ->whereHas('partnerType', fn($q) => $q->where('is_supplier_group', true))
            ->when($this->search, function ($q) {
                $q->where('name', 'like', '%' . $this->search . '%')
                  ->orWhere('phone', 'like', '%' . $this->search . '%');
            });
        
        // Add period debit/credit aggregations if AP account exists
        if ($apAccount) {
            $suppliers
                ->withSum(['journalEntryLines as period_debit' => function($q) use ($apAccount) {
                    $q->where('account_id', $apAccount->id)
                      ->whereHas('journalEntry', function($sq) {
                          $sq->whereBetween('date', [$this->dateFrom, $this->dateTo])
                             ->where('partner_id', '!=', null);
                      });
                }], 'debit')
                ->withSum(['journalEntryLines as period_credit' => function($q) use ($apAccount) {
                    $q->where('account_id', $apAccount->id)
                      ->whereHas('journalEntry', function($sq) {
                          $sq->whereBetween('date', [$this->dateFrom, $this->dateTo])
                             ->where('partner_id', '!=', null);
                      });
                }], 'credit');
        }
        
        $suppliers = $suppliers
            ->orderBy('name')
            ->get();

        $paymentMethods = PaymentMethod::where('is_active', true)->ordered()->get();

        return view('livewire.accounting.supplier-payments', [
            'suppliers' => $suppliers,
            'paymentMethods' => $paymentMethods,
        ]);
    }
}
