<?php

namespace App\Livewire\Sales;

use App\Models\Partner;
use App\Models\Product;
use App\Models\Sale;
use App\Models\SaleItem;
use App\Models\SalePayment;
use App\Models\PaymentMethod;
use App\Models\Inventory;
use App\Models\Setting;
use Illuminate\Support\Facades\DB;
use App\Models\Location;
use Livewire\Attributes\Computed;
use Livewire\Component;

class CreateSale extends Component
{
    // Form Fields
    public $partner_id;
    public $sale_date;
    public $warehouse_id; 
    public $status = 'completed';
    public $notes;

    // Cart
    public $cart = [];
    public $productSearch = '';
    public $searchResults = [];

    // Payments
    public $payment_method_id;
    public $amount_paid = 0;
    public $is_credit = false;

    // Totals
    public $subtotal = 0;
    public $tax_amount = 0;
    public $discount_amount = 0;
    public $total_amount = 0;

    protected $rules = [
        'partner_id' => 'nullable|exists:partners,id',
        'sale_date' => 'required|date',
        'cart' => 'required|array|min:1',
        'cart.*.product_id' => 'required|exists:products,id',
        'cart.*.quantity' => 'required|numeric|min:1',
        'cart.*.unit_price' => 'required|numeric|min:0',
        'payment_method_id' => 'required_if:is_credit,false',
    ];

    #[Computed]
    public function partners()
    {
        return Partner::active()->customers()->get();
    }

    #[Computed]
    public function paymentMethods()
    {
        return PaymentMethod::active()->get();
    }

    public function mount()
    {
        $this->sale_date = now()->format('Y-m-d');
        $this->payment_method_id = PaymentMethod::where('is_default', true)->value('id');
    }

    public function updatedProductSearch()
    {
        if (strlen($this->productSearch) < 2) {
            $this->searchResults = [];
            return;
        }

        $this->searchResults = Product::where('name', 'like', '%' . $this->productSearch . '%')
            ->orWhere('sku', 'like', '%' . $this->productSearch . '%')
            ->take(10)
            ->get();
    }

    public function addToCart($productId)
    {
        $product = Product::find($productId);
        if (!$product) return;

        $existingItemKey = null;
        foreach ($this->cart as $key => $item) {
            if ($item['product_id'] == $productId) {
                $existingItemKey = $key;
                break;
            }
        }

        if ($existingItemKey !== null) {
            $this->cart[$existingItemKey]['quantity']++;
            $this->cart[$existingItemKey]['total'] = $this->cart[$existingItemKey]['quantity'] * $this->cart[$existingItemKey]['unit_price'];
        } else {
            $this->cart[] = [
                'product_id' => $product->id,
                'name' => $product->name,
                'quantity' => 1,
                'unit_price' => $product->selling_price, // Fixed attribute name
                'cost_price' => $product->cost_price, // Fixed attribute name
                'total' => $product->selling_price,
            ];
        }

        $this->productSearch = '';
        $this->searchResults = [];
        $this->calculateTotals();
    }

    public function removeFromCart($index)
    {
        unset($this->cart[$index]);
        $this->cart = array_values($this->cart);
        $this->calculateTotals();
    }

    public function updateQuantity($index, $qty)
    {
        if ($qty < 1) $qty = 1;
        $this->cart[$index]['quantity'] = $qty;
        $this->cart[$index]['total'] = $qty * $this->cart[$index]['unit_price'];
        $this->calculateTotals();
    }

    public function updatePrice($index, $price)
    {
        if ($price < 0) $price = 0;
        $this->cart[$index]['unit_price'] = $price;
        $this->cart[$index]['total'] = $this->cart[$index]['quantity'] * $price;
        $this->calculateTotals();
    }

    public function calculateTotals()
    {
        $this->subtotal = collect($this->cart)->sum('total');
        // Add tax logic here if needed
        $this->total_amount = $this->subtotal - $this->discount_amount + $this->tax_amount;
        
        if (!$this->is_credit) {
            $this->amount_paid = $this->total_amount;
        }
    }

    public function saveSale()
    {
        $this->validate();

        DB::transaction(function () {
            // Create Sale
            $sale = Sale::create([
                'sale_number' => Sale::generateSaleNumber(),
                'partner_id' => $this->partner_id, // Use partner_id
                'branch_id' => $branchId = auth()->user()->branch_id ?? 1,
                'location_id' => $locationId = $this->warehouse_id ?: Location::defaultLocation($branchId)?->id,
                'user_id' => auth()->id(),
                'payment_method_id' => $this->is_credit ? null : $this->payment_method_id,
                'sale_date' => $this->sale_date,
                'subtotal' => $this->subtotal,
                'discount' => $this->discount_amount,
                'tax' => $this->tax_amount,
                'total' => $this->total_amount,
                'paid' => $this->is_credit ? 0 : $this->amount_paid,
                'is_credit' => $this->is_credit,
                'status' => $this->status,
                'notes' => $this->notes,
            ]);

            // Create Sale Items & Update Inventory
            foreach ($this->cart as $item) {
                SaleItem::create([
                    'sale_id' => $sale->id,
                    'product_id' => $item['product_id'],
                    'quantity' => $item['quantity'],
                    'unit_price' => $item['unit_price'],
                    'cost_price' => $item['cost_price'],
                    'total' => $item['total'],
                ]);

                // Reduce Stock
                // Use the standardized findOrCreateForProduct (but here we deduct, so we need to find it first)
                $inventory = Inventory::where('product_id', $item['product_id'])
                    ->where('branch_id', $branchId)
                    ->where('location_id', $locationId)
                    ->first();
                
                if ($inventory) {
                    $inventory->decrement('quantity', $item['quantity']);
                } else {
                     Inventory::create([
                        'product_id' => $item['product_id'],
                        'branch_id' => $branchId,
                        'location_id' => $locationId,
                        'quantity' => -$item['quantity'],
                        'avg_cost' => $item['cost_price']
                    ]);
                }
            }

            // Create Payment Record if paid
            if (!$this->is_credit && $this->amount_paid > 0) {
                SalePayment::create([
                    'sale_id' => $sale->id,
                    'payment_method_id' => $this->payment_method_id,
                    'amount' => $this->amount_paid,
                    'payment_date' => now(),
                    'user_id' => auth()->id(),
                ]);
            }
            
            // Partner Balance Update (if credit/partial)
            $remaining = $this->total_amount - ($this->is_credit ? 0 : $this->amount_paid);
            if ($this->partner_id && $remaining > 0) {
                \App\Models\Partner::where('id', $this->partner_id)->increment('current_balance', $remaining);
            }

            // Create Journal Entry for Sale (AFTER payments are recorded)
            try {
                $accountingService = app(\App\Services\AccountingService::class);
                $accountingService->createSaleJournalEntry($sale);
            } catch (\Exception $e) {
                \Log::error('Failed to create sale journal entry: ' . $e->getMessage());
                // Don't fail the sale, just log it.
            }

            session()->flash('message', 'Sale created successfully!');
            return redirect()->route('sales.index');
        });
    }

    public function render()
    {
        return view('livewire.sales.create-sale');
    }
}
