<?php

namespace App\Livewire\Invoices;

use App\Models\Branch;
use App\Models\Customer;
use App\Models\Invoice;
use App\Models\InvoiceLineItem;
use App\Models\Part;
use App\Models\ServiceItem;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Validate;
use Livewire\Component;

class Edit extends Component
{
    public Invoice $invoice;

    #[Validate('required')]
    public $customer_id = '';

    #[Validate('required')]
    public $branch_id = '';

    #[Validate('required|date')]
    public $invoice_date = '';

    #[Validate('required|date|after:invoice_date')]
    public $due_date = '';

    #[Validate('nullable|string')]
    public $description = '';

    #[Validate('nullable|string')]
    public $notes = '';

    #[Validate('nullable|string')]
    public $terms_and_conditions = '';

    #[Validate('numeric|min:0|max:100')]
    public $tax_rate = 8.50;

    #[Validate('numeric|min:0')]
    public $discount_amount = 0;

    public $line_items = [];

    public $customers = [];

    public $branches = [];

    public $parts = [];

    public $service_items = [];

    public function mount(Invoice $invoice)
    {
        $this->invoice = $invoice;

        // Check if invoice can be edited
        if (in_array($invoice->status, ['paid', 'cancelled'])) {
            session()->flash('error', 'This invoice cannot be edited as it is '.$invoice->status.'.');

            return $this->redirect(route('invoices.show', $invoice));
        }

        // Populate form data
        $this->customer_id = $invoice->customer_id;
        $this->branch_id = $invoice->branch_id;
        $this->invoice_date = $invoice->invoice_date->format('Y-m-d');
        $this->due_date = $invoice->due_date->format('Y-m-d');
        $this->description = $invoice->description;
        $this->notes = $invoice->notes;
        $this->terms_and_conditions = $invoice->terms_and_conditions;
        $this->tax_rate = $invoice->tax_rate;
        $this->discount_amount = $invoice->discount_amount;

        // Load line items
        $this->line_items = $invoice->lineItems->map(function ($item) {
            return [
                'id' => $item->id,
                'type' => $item->type,
                'description' => $item->description,
                'quantity' => $item->quantity,
                'unit_price' => $item->unit_price,
                'part_id' => $item->part_id,
                'part_number' => $item->part_number,
                'technical_notes' => $item->technical_notes,
            ];
        })->toArray();

        // Load data
        $this->customers = Customer::orderBy('first_name')->orderBy('last_name')->get();
        $this->branches = Branch::orderBy('name')->get();
        $this->parts = Part::where('status', 'active')->orderBy('name')->get();
        $this->service_items = ServiceItem::where('status', 'active')->orderBy('service_name')->get();

        // Add empty line item if none exist
        if (empty($this->line_items)) {
            $this->addLineItem();
        }
    }

    public function addLineItem()
    {
        $this->line_items[] = [
            'id' => null,
            'type' => 'labour',
            'description' => '',
            'quantity' => 1,
            'unit_price' => 0,
            'part_id' => '',
            'part_number' => '',
            'technical_notes' => '',
        ];
    }

    public function removeLineItem($index)
    {
        unset($this->line_items[$index]);
        $this->line_items = array_values($this->line_items);
    }

    public function updatedLineItems($value, $key)
    {
        // Auto-populate part details when part is selected
        if (str_contains($key, 'part_id')) {
            $index = explode('.', $key)[0];
            $partId = $this->line_items[$index]['part_id'];

            if ($partId) {
                $part = Part::find($partId);
                if ($part) {
                    $this->line_items[$index]['description'] = $part->name;
                    $this->line_items[$index]['unit_price'] = $part->sell_price ?? 0;
                    $this->line_items[$index]['part_number'] = $part->part_number;
                }
            }
        }

        // Reset part selection when type changes
        if (str_contains($key, 'type')) {
            $index = explode('.', $key)[0];
            $this->line_items[$index]['part_id'] = '';
            $this->line_items[$index]['part_number'] = '';
            if ($this->line_items[$index]['type'] !== 'parts') {
                $this->line_items[$index]['description'] = '';
                $this->line_items[$index]['unit_price'] = 0;
            }
        }

        // Auto-populate service item details
        if (str_contains($key, 'service_item_id')) {
            $index = explode('.', $key)[0];
            $serviceItemId = $this->line_items[$index]['service_item_id'] ?? null;

            if ($serviceItemId) {
                $serviceItem = ServiceItem::find($serviceItemId);
                if ($serviceItem) {
                    $this->line_items[$index]['description'] = $serviceItem->service_name;
                    $this->line_items[$index]['unit_price'] = $serviceItem->price ?? 0;
                }
            }
        }
    }

    public function calculateSubtotal()
    {
        return collect($this->line_items)->sum(function ($item) {
            return ($item['quantity'] ?? 0) * ($item['unit_price'] ?? 0);
        });
    }

    public function calculateTax()
    {
        $subtotal = $this->calculateSubtotal() - $this->discount_amount;

        return $subtotal * ($this->tax_rate / 100);
    }

    public function calculateTotal()
    {
        $subtotal = $this->calculateSubtotal();
        $tax = $this->calculateTax();

        return $subtotal + $tax - $this->discount_amount;
    }

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

        // Validate line items
        if (empty($this->line_items)) {
            $this->addError('line_items', 'At least one line item is required.');

            return;
        }

        foreach ($this->line_items as $index => $item) {
            if (empty($item['description'])) {
                $this->addError("line_items.{$index}.description", 'Description is required.');

                return;
            }
            if ($item['quantity'] <= 0) {
                $this->addError("line_items.{$index}.quantity", 'Quantity must be greater than 0.');

                return;
            }
            if ($item['unit_price'] < 0) {
                $this->addError("line_items.{$index}.unit_price", 'Unit price cannot be negative.');

                return;
            }
        }

        // Update invoice
        $this->invoice->update([
            'customer_id' => $this->customer_id,
            'branch_id' => $this->branch_id,
            'invoice_date' => $this->invoice_date,
            'due_date' => $this->due_date,
            'description' => $this->description,
            'notes' => $this->notes,
            'terms_and_conditions' => $this->terms_and_conditions,
            'tax_rate' => $this->tax_rate,
            'discount_amount' => $this->discount_amount,
        ]);

        // Get existing line item IDs
        $existingIds = collect($this->line_items)->pluck('id')->filter()->toArray();

        // Delete line items not in the current list
        $this->invoice->lineItems()->whereNotIn('id', $existingIds)->delete();

        // Update or create line items
        foreach ($this->line_items as $item) {
            if ($item['id']) {
                // Update existing line item
                InvoiceLineItem::where('id', $item['id'])->update([
                    'type' => $item['type'],
                    'description' => $item['description'],
                    'quantity' => $item['quantity'],
                    'unit_price' => $item['unit_price'],
                    'part_id' => $item['part_id'] ?: null,
                    'part_number' => $item['part_number'] ?: null,
                    'technical_notes' => $item['technical_notes'] ?: null,
                ]);
            } else {
                // Create new line item
                InvoiceLineItem::create([
                    'invoice_id' => $this->invoice->id,
                    'type' => $item['type'],
                    'description' => $item['description'],
                    'quantity' => $item['quantity'],
                    'unit_price' => $item['unit_price'],
                    'part_id' => $item['part_id'] ?: null,
                    'part_number' => $item['part_number'] ?: null,
                    'technical_notes' => $item['technical_notes'] ?: null,
                ]);
            }
        }

        session()->flash('success', 'Invoice updated successfully.');

        return $this->redirect(route('invoices.show', $this->invoice));
    }

    #[Layout('components.layouts.app.sidebar')]
    public function render()
    {
        return view('livewire.invoices.edit');
    }
}
