<?php

namespace App\Livewire\Sales;

use App\Models\Customer;
use App\Models\PaymentMethod;
use App\Models\Product;
use App\Models\Sale;
use App\Models\SaleItem;
use App\Models\SaleType;
use Illuminate\Support\Facades\DB;
use Livewire\Attributes\Layout;
use Livewire\Component;

#[Layout('layouts.dashboard')]
class Edit extends Component
{
    public Sale $sale;

    // Form state
    public $customer_id = '';

    public $payment_method_id = '';

    public $sale_type_id = '';

    public $notes = '';

    // Product form state
    public $product_id;

    public $quantity = 1;

    public $unit_price = 0;

    // Sale items from session
    public $subtotal = 0;

    public $total = 0;

    // Options for dropdowns
    public $customer_options = [];

    public $payment_method_options = [];

    public $sale_type_options = [];

    public $product_options = [];

    // UI state
    public $loading = false;

    public $success = false;

    public $error = false;

    public $successMessage = null;

    public $errorMessage = null;

    // Product form UI state
    public $product_loading = false;

    public $product_error = false;

    public $product_error_message = '';

    public function mount(Sale $sale)
    {
        $this->sale = $sale;

        // Load existing sale data
        $this->customer_id = $sale->customer_id ?? '';
        $this->payment_method_id = $sale->payment_method_id ?? '';
        $this->sale_type_id = $sale->sale_type_id ?? '';
        $this->notes = $sale->notes ?? '';

        // Load existing sale items into session
        $this->loadExistingItems();

        $this->loadOptions();
        $this->calculateTotals();
    }

    public function loadExistingItems()
    {
        $existingItems = $this->sale->items->map(function ($item) {
            return [
                'product_id' => $item->product_id,
                'quantity' => $item->quantity,
                'unit_price' => $item->unit_price,
                'total_price' => $item->total_price,
            ];
        })->toArray();

        session(['sale_items' => $existingItems]);
    }

    public function loadOptions()
    {
        // Load payment methods (exclude debt for editing)
        $this->payment_method_options = PaymentMethod::where('status', true)
            ->where('id', '!=', \App\Models\Setting::DEFAULT_PAYMENT_METHOD_DEBT_ID)
            ->get(['id', 'name'])
            ->map(fn ($m) => (object) ['id' => $m->id, 'name' => $m->name]);

        $this->sale_type_options = SaleType::where('status', true)
            ->get(['id', 'name'])
            ->map(fn ($t) => (object) ['id' => $t->id, 'name' => $t->name]);

        $this->customer_options = Customer::where('status', 1)
            ->with('contact')
            ->get()
            ->map(function ($customer) {
                return (object) [
                    'id' => $customer->id,
                    'name' => $customer->name.' ('.($customer->contact?->phone ?? 'N/A').')',
                ];
            });

        $this->product_options = Product::where('status', true)
            ->with(['category', 'saleUnit'])
            ->get()
            ->map(function ($product) {
                return (object) [
                    'id' => $product->id,
                    'name' => $product->name,
                    'generic_name' => $product->generic_name,
                    'category' => $product->category?->name,
                    'display_name' => $product->name.' ('.$product->generic_name.') - '.($product->category?->name ?? 'Sans catégorie'),
                ];
            });
    }

    public function rules()
    {
        return [
            'customer_id' => ['nullable', 'exists:customers,id'],
            'payment_method_id' => ['required', 'exists:payment_methods,id'],
            'sale_type_id' => ['nullable', 'exists:sale_types,id'],
            'notes' => ['nullable', 'string', 'max:1000'],
            'product_id' => ['required', 'exists:products,id'],
            'quantity' => ['required', 'integer', 'min:1'],
            'unit_price' => ['required', 'numeric', 'min:0.01'],
        ];
    }

    public function updatedProductId()
    {
        if ($this->product_id) {
            $this->unit_price = $this->getProductSellingPrice($this->product_id);
        }
    }

    public function updatedQuantity()
    {
        $this->calculateTotals();
    }

    public function updatedUnitPrice()
    {
        $this->calculateTotals();
    }

    public function addProduct()
    {
        $this->validate([
            'product_id' => ['required', 'exists:products,id'],
            'quantity' => ['required', 'integer', 'min:1'],
            'unit_price' => ['required', 'numeric', 'min:0.01'],
        ]);

        $this->product_loading = true;
        $this->product_error = false;
        $this->product_error_message = '';

        try {
            // Check stock availability
            $available = $this->getProductStock($this->product_id);
            if ($available < $this->quantity) {
                $this->product_error = true;
                $this->product_error_message = "Stock insuffisant: disponible {$available}, demandé {$this->quantity}.";
                $this->product_loading = false;

                return;
            }

            // Prevent duplicates
            $existingItems = session('sale_items', []);
            $alreadyExists = collect($existingItems)->contains(fn ($i) => (int) ($i['product_id'] ?? 0) === (int) $this->product_id);

            if ($alreadyExists) {
                $this->product_error = true;
                $this->product_error_message = 'Ce produit est déjà ajouté à la vente.';
                $this->product_loading = false;

                return;
            }

            // Add to session
            $items = session('sale_items', []);
            $items[] = [
                'product_id' => $this->product_id,
                'quantity' => $this->quantity,
                'unit_price' => $this->unit_price,
                'total_price' => $this->quantity * $this->unit_price,
            ];

            session(['sale_items' => $items]);

            // Reset form
            $this->reset(['product_id', 'quantity', 'unit_price']);
            $this->quantity = 1;
            $this->unit_price = 0;

            $this->calculateTotals();

        } catch (\Exception $e) {
            $this->product_error = true;
            $this->product_error_message = 'Erreur lors de l\'ajout du produit: '.$e->getMessage();
        } finally {
            $this->product_loading = false;
        }
    }

    public function deleteSessionItem($index)
    {
        $items = session('sale_items', []);
        unset($items[$index]);
        $items = array_values($items); // Re-index array
        session(['sale_items' => $items]);
        $this->calculateTotals();
    }

    public function clearSaleItems()
    {
        session()->forget('sale_items');
        $this->calculateTotals();
    }

    public function calculateTotals()
    {
        $items = session('sale_items', []);
        $this->subtotal = collect($items)->sum('total_price');
        $this->total = $this->subtotal; // No taxes or discounts for now
    }

    public function updateSale()
    {
        $this->validate([
            'customer_id' => ['nullable', 'exists:customers,id'],
            'payment_method_id' => ['required', 'exists:payment_methods,id'],
            'sale_type_id' => ['nullable', 'exists:sale_types,id'],
            'notes' => ['nullable', 'string', 'max:1000'],
        ]);

        $this->loading = true;
        $this->success = false;
        $this->error = false;
        $this->successMessage = null;
        $this->errorMessage = null;

        try {
            // Check if there are items
            if (! session('sale_items') || count(session('sale_items')) === 0) {
                $this->error = true;
                $this->errorMessage = 'Veuillez ajouter au moins un produit à la vente.';
                $this->loading = false;

                return;
            }

            DB::beginTransaction();

            // Update sale basic info
            $this->sale->update([
                'customer_id' => $this->customer_id ?: null,
                'payment_method_id' => $this->payment_method_id,
                'sale_type_id' => $this->sale_type_id ?: null,
                'notes' => $this->notes,
                'subtotal_amount' => $this->subtotal,
                'total_amount' => $this->total,
            ]);

            // Delete existing sale items
            $this->sale->items()->delete();

            // Create new sale items
            foreach (session('sale_items', []) as $itemData) {
                SaleItem::create([
                    'sale_id' => $this->sale->id,
                    'product_id' => $itemData['product_id'],
                    'quantity' => $itemData['quantity'],
                    'unit_price' => $itemData['unit_price'],
                    'total_price' => $itemData['total_price'],
                ]);

                // Update product stock
                $product = Product::find($itemData['product_id']);
                if ($product) {
                    $product->decrement('current_stock', $itemData['quantity']);
                }
            }

            DB::commit();

            $this->success = true;
            $this->successMessage = 'Vente modifiée avec succès!';

            // Clear session
            session()->forget('sale_items');

        } catch (\Throwable $e) {
            DB::rollBack();
            report($e);
            $this->error = true;
            $this->errorMessage = 'Erreur lors de la modification de la vente: '.$e->getMessage();
            $this->addError('general', 'Erreur lors de la modification de la vente: '.$e->getMessage());
        } finally {
            $this->loading = false;
        }
    }

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

        return $product ? $product->current_stock ?? 0 : 0;
    }

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

        return $product ? $product->reorder_level ?? 0 : 0;
    }

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

        return $product ? $product->selling_price ?? 0 : 0;
    }

    public function getProductUnitName($productId)
    {
        if (! $productId) {
            return 'N/A';
        }
        $product = Product::find($productId);

        return $product ? $product->saleUnit?->name ?? 'N/A' : 'N/A';
    }

    public function getStockStatusClasses($productId, $quantity)
    {
        $stock = $this->getProductStock($productId);
        $reorderLevel = $this->getProductReorderLevel($productId);

        if ($stock <= 0) {
            return 'bg-red-50 border border-red-200';
        }

        if ($stock < $quantity) {
            return 'bg-orange-50 border border-orange-200';
        }

        if ($stock <= $reorderLevel) {
            return 'bg-yellow-50 border border-yellow-200';
        }

        return 'bg-green-50 border border-green-200';
    }

    public function render()
    {
        $this->calculateTotals();

        return view('livewire.sales.edit');
    }
}
