<?php

namespace App\Livewire\Estimates;

use App\Models\Diagnosis;
use App\Models\Estimate;
use App\Models\EstimateLineItem;
use App\Models\Part;
use App\Notifications\EstimateNotification;
use Livewire\Component;

class Create extends Component
{
    public Diagnosis $diagnosis;

    public $terms_and_conditions = '';

    public $validity_period_days = 30;

    public $tax_rate = 8.25;

    public $discount_amount = 0;

    public $notes = '';

    public $internal_notes = '';

    public $lineItems = [];

    public $subtotal = 0;

    public $tax_amount = 0;

    public $total_amount = 0;

    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(Diagnosis $diagnosis)
    {
        $this->diagnosis = $diagnosis->load([
            'jobCard.customer',
            'jobCard.vehicle',
        ]);

        // Pre-populate from diagnosis
        $this->initializeLineItems();
        $this->terms_and_conditions = config('app.default_estimate_terms',
            'This estimate is valid for 30 days. All work will be performed according to industry standards.'
        );
    }

    public function initializeLineItems()
    {
        // Add labor operations from diagnosis
        if ($this->diagnosis->labor_operations) {
            foreach ($this->diagnosis->labor_operations as $labor) {
                $this->lineItems[] = [
                    'type' => 'labor',
                    'description' => $labor['operation'] ?? 'Labor Operation',
                    'quantity' => $labor['estimated_hours'] ?? 1,
                    'unit_price' => $labor['labor_rate'] ?? 75,
                    'total_amount' => ($labor['estimated_hours'] ?? 1) * ($labor['labor_rate'] ?? 75),
                    'labor_hours' => $labor['estimated_hours'] ?? 1,
                    'labor_rate' => $labor['labor_rate'] ?? 75,
                    'required' => true,
                ];
            }
        }

        // Add parts from diagnosis
        if ($this->diagnosis->parts_required) {
            foreach ($this->diagnosis->parts_required as $part) {
                $this->lineItems[] = [
                    'type' => 'parts',
                    'part_id' => null,
                    'description' => ($part['part_name'] ?? 'Part').' ('.($part['part_number'] ?? 'N/A').')',
                    'quantity' => $part['quantity'] ?? 1,
                    'unit_price' => $part['estimated_cost'] ?? 0,
                    'total_amount' => ($part['quantity'] ?? 1) * ($part['estimated_cost'] ?? 0),
                    'markup_percentage' => 20,
                    'required' => true,
                ];
            }
        }

        // If no line items from diagnosis, add a default labor item
        if (empty($this->lineItems)) {
            $this->lineItems[] = [
                'type' => 'labor',
                'description' => 'Diagnostic and Repair Services',
                'quantity' => $this->diagnosis->estimated_repair_time ?? 1,
                'unit_price' => 75,
                'total_amount' => ($this->diagnosis->estimated_repair_time ?? 1) * 75,
                'labor_hours' => $this->diagnosis->estimated_repair_time ?? 1,
                'labor_rate' => 75,
                'required' => true,
            ];
        }

        $this->calculateTotals();
    }

    public function addLineItem()
    {
        $this->lineItems[] = [
            'type' => 'labor',
            'description' => '',
            'quantity' => 1,
            'unit_price' => 0,
            'total_amount' => 0,
            'required' => true,
        ];
    }

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

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

    public function calculateTotals()
    {
        $this->subtotal = collect($this->lineItems)->sum(function ($item) {
            return ($item['quantity'] ?? 0) * ($item['unit_price'] ?? 0);
        });

        $this->tax_amount = ($this->subtotal - $this->discount_amount) * ($this->tax_rate / 100);
        $this->total_amount = $this->subtotal - $this->discount_amount + $this->tax_amount;

        // Update individual line item totals
        foreach ($this->lineItems as $index => &$item) {
            $item['total_amount'] = ($item['quantity'] ?? 0) * ($item['unit_price'] ?? 0);
        }
    }

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

        // Generate estimate number
        $branchCode = $this->diagnosis->jobCard->branch_code;

        // Use database lock to prevent race conditions
        $maxNumber = \DB::transaction(function () use ($branchCode) {
            $lastEstimate = Estimate::where('estimate_number', 'like', $branchCode.'/EST%')
                ->whereYear('created_at', now()->year)
                ->orderByRaw('CAST(SUBSTRING(estimate_number, '.(strlen($branchCode) + 5).') AS UNSIGNED) DESC')
                ->lockForUpdate()
                ->first();

            $nextNumber = 1;
            if ($lastEstimate) {
                // Extract the number part from the estimate number (e.g., MAIN/EST0001 -> 1)
                preg_match('/'.preg_quote($branchCode).'\/EST(\d+)/', $lastEstimate->estimate_number, $matches);
                $nextNumber = isset($matches[1]) ? intval($matches[1]) + 1 : 1;
            }

            return $nextNumber;
        });

        $estimateNumber = $branchCode.'/EST'.str_pad($maxNumber, 4, '0', STR_PAD_LEFT);

        $estimate = Estimate::create([
            'estimate_number' => $estimateNumber,
            'job_card_id' => $this->diagnosis->job_card_id,
            'diagnosis_id' => $this->diagnosis->id,
            'prepared_by_id' => auth()->id(),
            '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'),
            'subtotal' => $this->subtotal,
            'tax_rate' => $this->tax_rate,
            'tax_amount' => $this->tax_amount,
            'discount_amount' => $this->discount_amount,
            'total_amount' => $this->total_amount,
            'validity_period_days' => $this->validity_period_days,
            'terms_and_conditions' => $this->terms_and_conditions,
            'notes' => $this->notes,
            'internal_notes' => $this->internal_notes,
            'status' => 'draft',
        ]);

        // Create line items
        foreach ($this->lineItems as $item) {
            EstimateLineItem::create([
                'estimate_id' => $estimate->id,
                'type' => $item['type'],
                'part_id' => $item['part_id'] ?? null,
                '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'] ?? 0,
                'required' => $item['required'] ?? true,
            ]);
        }

        // Update job card status
        $this->diagnosis->jobCard->update(['status' => 'estimate_prepared']);

        session()->flash('message', 'Estimate created successfully!');

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

    public function sendToCustomer()
    {
        // This would be called after saving
        $customer = $this->diagnosis->jobCard->customer;
        $customer->notify(new EstimateNotification($estimate));

        session()->flash('message', 'Estimate sent to customer successfully!');
    }

    public function render()
    {
        return view('livewire.estimates.create');
    }
}
