<?php

namespace App\Livewire\Estimates;

use App\Models\Estimate;
use App\Models\EstimateLineItem;
use App\Models\Part;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Validate;
use Livewire\Component;

class Edit extends Component
{
    public Estimate $estimate;

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

    #[Validate('required|integer|min:1|max:365')]
    public $validity_period_days = 30;

    #[Validate('required|numeric|min:0|max:50')]
    public $tax_rate = 8.25;

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

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

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

    public $lineItems = [];

    public $deletedItems = [];

    public $subtotal = 0;

    public $tax_amount = 0;

    public $total_amount = 0;

    // Advanced features
    public $showAdvancedOptions = false;

    public $bulkOperationMode = false;

    public $selectedItems = [];

    public $autoSave = true;

    public $lastSaved;

    // Quick add presets
    public $quickAddPresets = [
        'oil_change' => ['type' => 'labor', 'description' => 'Oil Change Service', 'quantity' => 1, 'unit_price' => 75],
        'brake_inspection' => ['type' => 'labor', 'description' => 'Brake System Inspection', 'quantity' => 1, 'unit_price' => 125],
        'tire_rotation' => ['type' => 'labor', 'description' => 'Tire Rotation Service', 'quantity' => 1, 'unit_price' => 50],
    ];

    // Line item templates
    public $newItem = [
        'type' => 'labor',
        'description' => '',
        'quantity' => 1,
        'unit_price' => 0,
        'part_id' => null,
        'markup_percentage' => 15,
        'discount_type' => 'none',
        'discount_value' => 0,
        'notes' => '',
        'is_taxable' => true,
    ];

    protected $rules = [
        'terms_and_conditions' => 'required|string',
        'validity_period_days' => 'required|integer|min:1|max:365',
        'tax_rate' => 'required|numeric|min:0|max:50',
        'discount_amount' => 'nullable|numeric|min:0',
        'lineItems.*.type' => 'required|in:labor,parts,miscellaneous',
        'lineItems.*.description' => 'required|string',
        'lineItems.*.quantity' => 'required|numeric|min:0.01',
        'lineItems.*.unit_price' => 'required|numeric|min:0',
    ];

    public function mount(Estimate $estimate)
    {
        $this->estimate = $estimate->load([
            'jobCard.customer',
            'jobCard.vehicle',
            'customer', // For standalone estimates
            'vehicle',  // For standalone estimates
            'lineItems.part',
        ]);

        $this->loadEstimateData();
        $this->loadLineItems();
        $this->calculateTotals();
    }

    protected function loadEstimateData()
    {
        $this->terms_and_conditions = $this->estimate->terms_and_conditions ?? '';
        $this->validity_period_days = $this->estimate->validity_period_days ?? 30;
        $this->tax_rate = $this->estimate->tax_rate ?? 8.25;
        $this->discount_amount = $this->estimate->discount_amount ?? 0;
        $this->notes = $this->estimate->notes ?? '';
        $this->internal_notes = $this->estimate->internal_notes ?? '';
    }

    protected function loadLineItems()
    {
        $this->lineItems = $this->estimate->lineItems->map(function ($item) {
            return [
                'id' => $item->id,
                'type' => $item->type,
                'description' => $item->description,
                'quantity' => $item->quantity,
                'unit_price' => $item->unit_price,
                'total_amount' => $item->total_amount,
                'labor_hours' => $item->labor_hours,
                'labor_rate' => $item->labor_rate,
                'markup_percentage' => $item->markup_percentage ?? 15,
                'discount_type' => $item->discount_type ?? 'none',
                'discount_value' => $item->discount_value ?? 0,
                'part_id' => $item->part_id,
                'part_name' => $item->part?->name,
                'notes' => $item->notes ?? '',
                'is_taxable' => $item->is_taxable ?? true,
                'is_editing' => false,
                'required' => true,
            ];
        })->toArray();
    }

    public function addLineItem()
    {
        $this->validate([
            'newItem.type' => 'required|in:labor,parts,miscellaneous',
            'newItem.description' => 'required|string|max:255',
            'newItem.quantity' => 'required|numeric|min:0.01',
            'newItem.unit_price' => 'required|numeric|min:0',
        ]);

        $lineItem = [
            'id' => null,
            'type' => $this->newItem['type'],
            'description' => $this->newItem['description'],
            'quantity' => $this->newItem['quantity'],
            'unit_price' => $this->newItem['unit_price'],
            'part_id' => $this->newItem['part_id'],
            'markup_percentage' => $this->newItem['markup_percentage'],
            'discount_type' => $this->newItem['discount_type'],
            'discount_value' => $this->newItem['discount_value'],
            'notes' => $this->newItem['notes'],
            'is_taxable' => $this->newItem['is_taxable'],
            'is_editing' => false,
            'required' => true,
        ];

        $lineItem['total_amount'] = $this->calculateLineItemTotal($lineItem);

        $this->lineItems[] = $lineItem;

        // Reset new item form
        $this->newItem = [
            'type' => 'labor',
            'description' => '',
            'quantity' => 1,
            'unit_price' => 0,
            'part_id' => null,
            'markup_percentage' => 15,
            'discount_type' => 'none',
            'discount_value' => 0,
            'notes' => '',
            'is_taxable' => true,
        ];

        $this->calculateTotals();

        if ($this->autoSave) {
            $this->autoSaveEstimate();
        }
    }

    public function addQuickPreset($presetKey)
    {
        if (isset($this->quickAddPresets[$presetKey])) {
            $preset = $this->quickAddPresets[$presetKey];

            $lineItem = array_merge([
                'id' => null,
                'part_id' => null,
                'markup_percentage' => 15,
                'discount_type' => 'none',
                'discount_value' => 0,
                'notes' => '',
                'is_taxable' => true,
                'is_editing' => false,
                'required' => true,
            ], $preset);

            $lineItem['total_amount'] = $this->calculateLineItemTotal($lineItem);

            $this->lineItems[] = $lineItem;
            $this->calculateTotals();

            if ($this->autoSave) {
                $this->autoSaveEstimate();
            }
        }
    }

    public function removeLineItem($index)
    {
        if (isset($this->lineItems[$index]['id'])) {
            $this->deletedItems[] = $this->lineItems[$index]['id'];
        }

        unset($this->lineItems[$index]);
        $this->lineItems = array_values($this->lineItems);
        $this->calculateTotals();

        if ($this->autoSave) {
            $this->autoSaveEstimate();
        }
    }

    public function duplicateLineItem($index)
    {
        if (isset($this->lineItems[$index])) {
            $item = $this->lineItems[$index];
            unset($item['id']); // Remove ID so it's treated as new
            $item['description'] .= ' (Copy)';
            $item['is_editing'] = false;

            $this->lineItems[] = $item;
            $this->calculateTotals();
        }
    }

    public function editLineItem($index)
    {
        $this->lineItems[$index]['is_editing'] = true;
    }

    public function saveLineItem($index)
    {
        $this->lineItems[$index]['is_editing'] = false;
        $this->lineItems[$index]['total_amount'] = $this->calculateLineItemTotal($this->lineItems[$index]);
        $this->calculateTotals();

        if ($this->autoSave) {
            $this->autoSaveEstimate();
        }
    }

    public function cancelEditLineItem($index)
    {
        $this->lineItems[$index]['is_editing'] = false;
        // Reload from database if it's an existing item
        if (isset($this->lineItems[$index]['id'])) {
            $this->loadLineItems();
            $this->calculateTotals();
        }
    }

    public function toggleBulkMode()
    {
        $this->bulkOperationMode = ! $this->bulkOperationMode;
        $this->selectedItems = [];
    }

    public function bulkDelete()
    {
        foreach ($this->selectedItems as $index) {
            if (isset($this->lineItems[$index]['id'])) {
                $this->deletedItems[] = $this->lineItems[$index]['id'];
            }
            unset($this->lineItems[$index]);
        }

        $this->lineItems = array_values($this->lineItems);
        $this->selectedItems = [];
        $this->bulkOperationMode = false;
        $this->calculateTotals();
    }

    public function bulkApplyDiscount($discountType, $discountValue)
    {
        foreach ($this->selectedItems as $index) {
            if (isset($this->lineItems[$index])) {
                $this->lineItems[$index]['discount_type'] = $discountType;
                $this->lineItems[$index]['discount_value'] = $discountValue;
                $this->lineItems[$index]['total_amount'] = $this->calculateLineItemTotal($this->lineItems[$index]);
            }
        }

        $this->selectedItems = [];
        $this->bulkOperationMode = false;
        $this->calculateTotals();
    }

    public function bulkApplyMarkup($markupPercentage)
    {
        foreach ($this->selectedItems as $index) {
            if (isset($this->lineItems[$index])) {
                $this->lineItems[$index]['markup_percentage'] = $markupPercentage;
                $this->lineItems[$index]['total_amount'] = $this->calculateLineItemTotal($this->lineItems[$index]);
            }
        }

        $this->selectedItems = [];
        $this->bulkOperationMode = false;
        $this->calculateTotals();
    }

    protected function calculateLineItemTotal($item)
    {
        $baseAmount = $item['quantity'] * $item['unit_price'];

        // Apply markup
        if (isset($item['markup_percentage']) && $item['markup_percentage'] > 0) {
            $baseAmount += $baseAmount * ($item['markup_percentage'] / 100);
        }

        // Apply discount
        if ($item['discount_type'] === 'percentage') {
            $discount = $baseAmount * ($item['discount_value'] / 100);
        } elseif ($item['discount_type'] === 'fixed') {
            $discount = min($item['discount_value'], $baseAmount);
        } else {
            $discount = 0;
        }

        return $baseAmount - $discount;
    }

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

        if ($this->autoSave) {
            $this->autoSaveEstimate();
        }
    }

    public function calculateTotals()
    {
        // Calculate line item totals
        foreach ($this->lineItems as $index => $item) {
            $this->lineItems[$index]['total_amount'] = $this->calculateLineItemTotal($item);
        }

        // Calculate subtotal
        $this->subtotal = collect($this->lineItems)->sum('total_amount');

        // Calculate tax on taxable items only
        $taxableAmount = collect($this->lineItems)
            ->where('is_taxable', true)
            ->sum('total_amount') - $this->discount_amount;

        $this->tax_amount = max(0, $taxableAmount) * ($this->tax_rate / 100);

        // Calculate total
        $this->total_amount = $this->subtotal - $this->discount_amount + $this->tax_amount;
    }

    public function autoSaveEstimate()
    {
        try {
            $this->estimate->update([
                'subtotal' => $this->subtotal,
                'tax_amount' => $this->tax_amount,
                'total_amount' => $this->total_amount,
                'labor_cost' => collect($this->lineItems)->where('type', 'labor')->sum('total_amount'),
                'parts_cost' => collect($this->lineItems)->where('type', 'parts')->sum('total_amount'),
                'miscellaneous_cost' => collect($this->lineItems)->where('type', 'miscellaneous')->sum('total_amount'),
                'last_auto_saved_at' => now(),
            ]);

            $this->lastSaved = now()->format('H:i:s');

        } catch (\Exception $e) {
            Log::error('Auto-save failed', [
                'estimate_id' => $this->estimate->id,
                'error' => $e->getMessage(),
            ]);
        }
    }

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

        try {
            DB::transaction(function () {
                $this->calculateTotals();

                // Update estimate
                $this->estimate->update([
                    'terms_and_conditions' => $this->terms_and_conditions,
                    'validity_period_days' => $this->validity_period_days,
                    'tax_rate' => $this->tax_rate,
                    'discount_amount' => $this->discount_amount,
                    'notes' => $this->notes,
                    'internal_notes' => $this->internal_notes,
                    'subtotal' => $this->subtotal,
                    'tax_amount' => $this->tax_amount,
                    'total_amount' => $this->total_amount,
                    'labor_cost' => collect($this->lineItems)->where('type', 'labor')->sum('total_amount'),
                    'parts_cost' => collect($this->lineItems)->where('type', 'parts')->sum('total_amount'),
                    'miscellaneous_cost' => collect($this->lineItems)->where('type', 'miscellaneous')->sum('total_amount'),
                    'updated_by_id' => auth()->id(),
                ]);

                // Delete removed items
                if (! empty($this->deletedItems)) {
                    EstimateLineItem::whereIn('id', $this->deletedItems)->delete();
                }

                // Update/create line items
                foreach ($this->lineItems as $item) {
                    if ($item['id']) {
                        EstimateLineItem::where('id', $item['id'])->update([
                            'type' => $item['type'],
                            'description' => $item['description'],
                            'quantity' => $item['quantity'],
                            'unit_price' => $item['unit_price'],
                            'total_amount' => $item['total_amount'],
                            'labor_hours' => $item['labor_hours'] ?? null,
                            'labor_rate' => $item['labor_rate'] ?? null,
                            'markup_percentage' => $item['markup_percentage'] ?? null,
                            'discount_type' => $item['discount_type'] ?? 'none',
                            'discount_value' => $item['discount_value'] ?? 0,
                            'part_id' => $item['part_id'],
                            'notes' => $item['notes'] ?? '',
                            'is_taxable' => $item['is_taxable'] ?? true,
                        ]);
                    } else {
                        $this->estimate->lineItems()->create([
                            'type' => $item['type'],
                            'description' => $item['description'],
                            'quantity' => $item['quantity'],
                            'unit_price' => $item['unit_price'],
                            'total_amount' => $item['total_amount'],
                            'labor_hours' => $item['labor_hours'] ?? null,
                            'labor_rate' => $item['labor_rate'] ?? null,
                            'markup_percentage' => $item['markup_percentage'] ?? null,
                            'discount_type' => $item['discount_type'] ?? 'none',
                            'discount_value' => $item['discount_value'] ?? 0,
                            'part_id' => $item['part_id'],
                            'notes' => $item['notes'] ?? '',
                            'is_taxable' => $item['is_taxable'] ?? true,
                        ]);
                    }
                }
            });

            Log::info('Estimate updated', [
                'estimate_id' => $this->estimate->id,
                'updated_by' => auth()->id(),
            ]);

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

            return redirect()->route('estimates.show', $this->estimate);

        } catch (\Exception $e) {
            Log::error('Failed to update estimate', [
                'estimate_id' => $this->estimate->id,
                'error' => $e->getMessage(),
            ]);

            session()->flash('error', 'Failed to update estimate. Please try again.');
        }
    }

    public function getAvailablePartsProperty()
    {
        return Part::where('stock_quantity', '>', 0)
            ->orderBy('name')
            ->get(['id', 'name', 'part_number', 'unit_price']);
    }

    public function toggleAdvancedOptions()
    {
        $this->showAdvancedOptions = ! $this->showAdvancedOptions;
    }

    public function toggleAutoSave()
    {
        $this->autoSave = ! $this->autoSave;
    }

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