<?php

namespace App\Livewire\Diagnosis;

use App\Models\Diagnosis;
use App\Models\Estimate;
use App\Models\EstimateLineItem;
use App\Models\JobCard;
use App\Models\Part;
use App\Models\ServiceItem;
use App\Models\Timesheet;
use Livewire\Component;
use Livewire\WithFileUploads;

class Create extends Component
{
    use WithFileUploads;

    public JobCard $jobCard;

    public $customer_reported_issues = '';

    public $diagnostic_findings = '';

    public $root_cause_analysis = '';

    public $recommended_repairs = '';

    public $additional_issues_found = '';

    public $priority_level = 'medium';

    public $estimated_repair_time = '';

    public $parts_required = [];

    public $labor_operations = [];

    public $special_tools_required = [];

    public $safety_concerns = '';

    public $diagnostic_codes = [];

    public $test_results = [];

    public $photos = [];

    public $notes = '';

    public $environmental_impact = '';

    public $customer_authorization_required = false;

    // Timesheet tracking
    public $currentTimesheet = null;

    public $timesheets = [];

    public $selectedDiagnosisType = 'general_inspection';

    public $diagnosisTypes = [
        'general_inspection' => 'General Inspection',
        'electrical_diagnosis' => 'Electrical Diagnosis',
        'engine_diagnosis' => 'Engine Diagnosis',
        'transmission_diagnosis' => 'Transmission Diagnosis',
        'brake_diagnosis' => 'Brake System Diagnosis',
        'suspension_diagnosis' => 'Suspension Diagnosis',
        'air_conditioning' => 'Air Conditioning Diagnosis',
        'computer_diagnosis' => 'Computer/ECU Diagnosis',
        'emissions_diagnosis' => 'Emissions Diagnosis',
        'noise_diagnosis' => 'Noise/Vibration Diagnosis',
    ];

    // Parts integration
    public $availableParts = [];

    public $partSearch = '';

    public $partSearchTerm = '';

    public $partCategoryFilter = '';

    public $filteredParts;

    // Service items integration
    public $availableServiceItems = [];

    public $serviceItemSearch = '';

    public $serviceSearchTerm = '';

    public $serviceCategoryFilter = '';

    public $filteredServiceItems;

    // UI state
    public $showPartsSection = false;

    public $showLaborSection = false;

    public $showDiagnosticCodesSection = false;

    public $showTestResultsSection = false;

    public $showAdvancedOptions = false;

    public $showTimesheetSection = true;

    public $createEstimateAutomatically = true;

    protected $rules = [
        'customer_reported_issues' => 'required|string',
        'diagnostic_findings' => 'required|string|min:20',
        'root_cause_analysis' => 'required|string|min:20',
        'recommended_repairs' => 'required|string|min:10',
        'priority_level' => 'required|in:low,medium,high,urgent',
        'estimated_repair_time' => 'required|numeric|min:0.5|max:40',
        'safety_concerns' => 'nullable|string',
        'environmental_impact' => 'nullable|string',
        'notes' => 'nullable|string',
        'photos.*' => 'nullable|image|max:5120',
        'selectedDiagnosisType' => 'required|string',
    ];

    protected $messages = [
        'diagnostic_findings.min' => 'Please provide detailed diagnostic findings (at least 20 characters).',
        'root_cause_analysis.min' => 'Please provide a thorough root cause analysis (at least 20 characters).',
        'recommended_repairs.min' => 'Please specify the recommended repairs (at least 10 characters).',
        'estimated_repair_time.max' => 'Estimated repair time cannot exceed 40 hours. For longer repairs, consider breaking into phases.',
        'photos.*.max' => 'Each photo must be less than 5MB.',
        'selectedDiagnosisType.required' => 'Please select a diagnosis type.',
    ];

    public function mount(JobCard $jobCard)
    {
        // Validate that initial inspection has been completed
        if ($jobCard->status === 'received') {
            session()->flash('error', 'Initial vehicle inspection must be completed before starting diagnosis. Please complete the inspection first.');

            return redirect()->route('job-cards.show', $jobCard);
        }

        if (! $jobCard->incomingInspection) {
            session()->flash('error', 'No incoming inspection record found. Please complete the initial inspection before proceeding to diagnosis.');

            return redirect()->route('inspections.create', ['jobCard' => $jobCard, 'type' => 'incoming']);
        }

        $this->jobCard = $jobCard->load(['customer', 'vehicle', 'timesheets', 'incomingInspection']);
        $this->customer_reported_issues = $jobCard->customer_reported_issues ?? '';

        // Initialize arrays to prevent null issues - load from session if available
        $this->parts_required = session()->get("diagnosis_parts_{$jobCard->id}", []);
        $this->labor_operations = session()->get("diagnosis_labor_{$jobCard->id}", []);
        $this->timesheets = [];
        $this->diagnostic_codes = session()->get("diagnosis_codes_{$jobCard->id}", []);
        $this->test_results = [];
        $this->special_tools_required = [];

        // Initialize filtered collections
        $this->filteredParts = collect();
        $this->filteredServiceItems = collect();

        // Load existing timesheets for this job card related to diagnosis
        $this->loadTimesheets();

        // Load available parts and service items
        $this->loadAvailableParts();
        $this->loadAvailableServiceItems();

        // Initialize with one empty part and labor operation for convenience if none exist
        if (empty($this->parts_required)) {
            $this->addPart();
        }
        if (empty($this->labor_operations)) {
            $this->addLaborOperation();
        }
    }

    public function updatedPartsRequired()
    {
        // Save parts to session whenever they change
        session()->put("diagnosis_parts_{$this->jobCard->id}", $this->parts_required);
    }

    public function updatedLaborOperations()
    {
        // Save labor operations to session whenever they change
        session()->put("diagnosis_labor_{$this->jobCard->id}", $this->labor_operations);
    }

    public function updatedDiagnosticCodes()
    {
        // Save diagnostic codes to session whenever they change
        session()->put("diagnosis_codes_{$this->jobCard->id}", $this->diagnostic_codes);
    }

    public function loadTimesheets()
    {
        $this->timesheets = Timesheet::where('job_card_id', $this->jobCard->id)
            ->where('entry_type', 'manual')
            ->where('description', 'like', '%diagnosis%')
            ->with('user')
            ->orderBy('created_at', 'desc')
            ->get()
            ->toArray();
    }

    public function loadAvailableParts()
    {
        $query = Part::where('status', 'active');

        if (! empty($this->partSearch)) {
            $query->where(function ($q) {
                $q->where('name', 'like', '%'.$this->partSearch.'%')
                    ->orWhere('part_number', 'like', '%'.$this->partSearch.'%')
                    ->orWhere('description', 'like', '%'.$this->partSearch.'%');
            });
        }

        $this->availableParts = $query->limit(20)->get()->toArray();
    }

    public function loadAvailableServiceItems()
    {
        $query = ServiceItem::query();

        if (! empty($this->serviceItemSearch)) {
            $query->where(function ($q) {
                $q->where('service_name', 'like', '%'.$this->serviceItemSearch.'%')
                    ->orWhere('description', 'like', '%'.$this->serviceItemSearch.'%')
                    ->orWhere('category', 'like', '%'.$this->serviceItemSearch.'%');
            });
        }

        $this->availableServiceItems = $query->limit(20)->get()->toArray();
    }

    // Computed properties for filtered collections
    public function updatedPartSearchTerm()
    {
        $this->updateFilteredParts();
    }

    public function updatedPartCategoryFilter()
    {
        $this->updateFilteredParts();
    }

    public function updateFilteredParts()
    {
        try {
            // If no search criteria provided, return empty collection
            if (empty($this->partSearchTerm) && empty($this->partCategoryFilter)) {
                $this->filteredParts = collect();

                return;
            }

            // Start with active parts only
            $query = Part::where('status', 'active');

            // Add search term filter if provided
            if (! empty($this->partSearchTerm)) {
                $searchTerm = trim($this->partSearchTerm);
                $query->where(function ($q) use ($searchTerm) {
                    $q->where('name', 'like', '%'.$searchTerm.'%')
                        ->orWhere('part_number', 'like', '%'.$searchTerm.'%')
                        ->orWhere('description', 'like', '%'.$searchTerm.'%')
                        ->orWhere('manufacturer', 'like', '%'.$searchTerm.'%');
                });
            }

            // Add category filter if provided
            if (! empty($this->partCategoryFilter)) {
                $query->where('category', $this->partCategoryFilter);
            }

            // Order by name for consistent results
            $query->orderBy('name');

            // Get results and assign to property
            $this->filteredParts = $query->limit(20)->get();

            // Log for debugging
            \Log::info('Parts search executed', [
                'search_term' => $this->partSearchTerm,
                'category_filter' => $this->partCategoryFilter,
                'results_count' => $this->filteredParts->count(),
                'results' => $this->filteredParts->pluck('name')->toArray(),
            ]);

        } catch (\Exception $e) {
            // Log error and return empty collection
            \Log::error('Error in updateFilteredParts', [
                'error' => $e->getMessage(),
                'search_term' => $this->partSearchTerm,
                'category_filter' => $this->partCategoryFilter,
            ]);

            $this->filteredParts = collect();
        }
    }

    public function getFilteredServiceItemsProperty()
    {
        $query = ServiceItem::query();

        if (! empty($this->serviceSearchTerm)) {
            $query->where(function ($q) {
                $q->where('name', 'like', '%'.$this->serviceSearchTerm.'%')
                    ->orWhere('description', 'like', '%'.$this->serviceSearchTerm.'%');
            });
        }

        if (! empty($this->serviceCategoryFilter)) {
            $query->where('category', $this->serviceCategoryFilter);
        }

        return $query->limit(20)->get();
    }

    public function updatedPartSearch()
    {
        $this->loadAvailableParts();
    }

    public function updatedServiceSearchTerm()
    {
        $this->updateFilteredServiceItems();
    }

    public function updatedServiceCategoryFilter()
    {
        $this->updateFilteredServiceItems();
    }

    public function updateFilteredServiceItems()
    {
        try {
            // If no search criteria provided, return empty collection
            if (empty($this->serviceSearchTerm) && empty($this->serviceCategoryFilter)) {
                $this->filteredServiceItems = collect();

                return;
            }

            // Start with active service items only
            $query = ServiceItem::where('status', 'active');

            // Add search term filter if provided
            if (! empty($this->serviceSearchTerm)) {
                $searchTerm = trim($this->serviceSearchTerm);
                $query->where(function ($q) use ($searchTerm) {
                    $q->where('service_name', 'like', '%'.$searchTerm.'%')
                        ->orWhere('description', 'like', '%'.$searchTerm.'%');
                });
            }

            // Add category filter if provided
            if (! empty($this->serviceCategoryFilter)) {
                $query->where('category', $this->serviceCategoryFilter);
            }

            // Order by name for consistent results
            $query->orderBy('service_name');

            // Get results
            $results = $query->limit(20)->get();

            $this->filteredServiceItems = $results;
        } catch (\Exception $e) {
            // Log error and return empty collection
            \Log::error('Error in updateFilteredServiceItems', [
                'error' => $e->getMessage(),
                'search_term' => $this->serviceSearchTerm,
                'category_filter' => $this->serviceCategoryFilter,
            ]);

            $this->filteredServiceItems = collect();
        }
    }

    public function startTimesheet()
    {
        // End any currently running timesheet
        if ($this->currentTimesheet) {
            $this->endTimesheet();
        }

        $this->currentTimesheet = Timesheet::create([
            'job_card_id' => $this->jobCard->id,
            'user_id' => auth()->id(),
            'entry_type' => 'manual',
            'description' => 'Diagnosis: '.($this->diagnosisTypes[$this->selectedDiagnosisType] ?? 'General Diagnosis'),
            'date' => now()->toDateString(),
            'start_time' => now(),
            'hourly_rate' => auth()->user()->hourly_rate ?? 85.00,
            'status' => 'draft',
        ]);

        $this->loadTimesheets();
        session()->flash('timesheet_message', 'Timesheet started for '.($this->diagnosisTypes[$this->selectedDiagnosisType] ?? 'Diagnosis'));
    }

    public function endTimesheet()
    {
        if (! $this->currentTimesheet) {
            return;
        }

        $timesheet = Timesheet::find($this->currentTimesheet['id']);
        if ($timesheet && ! $timesheet->end_time) {
            $endTime = now();
            $totalMinutes = $timesheet->start_time->diffInMinutes($endTime);
            $billableHours = round($totalMinutes / 60, 2);

            $timesheet->update([
                'end_time' => $endTime,
                'hours_worked' => $billableHours,
                'billable_hours' => $billableHours,
                'total_amount' => $billableHours * $timesheet->hourly_rate,
                'status' => 'submitted',
            ]);

            session()->flash('timesheet_message', 'Timesheet ended. Total time: '.$billableHours.' hours');
        }

        $this->currentTimesheet = null;
        $this->loadTimesheets();
    }

    public function addPartFromCatalog($partId)
    {
        $part = Part::find($partId);
        if ($part) {
            $this->parts_required[] = [
                'part_id' => $part->id,
                'part_name' => $part->name,
                'part_number' => $part->part_number,
                'quantity' => 1,
                'estimated_cost' => $part->sell_price,
                'availability' => $part->quantity_on_hand > 0 ? 'in_stock' : 'out_of_stock',
            ];
            $this->updatedPartsRequired(); // Save to session
        }
    }

    public function addServiceItemFromCatalog($serviceItemId)
    {
        $serviceItem = ServiceItem::find($serviceItemId);
        if ($serviceItem) {
            $this->labor_operations[] = [
                'service_item_id' => $serviceItem->id,
                'operation' => $serviceItem->service_name,
                'description' => $serviceItem->description,
                'estimated_hours' => $serviceItem->estimated_hours,
                'labor_rate' => $serviceItem->labor_rate,
                'category' => $serviceItem->category,
                'complexity' => 'medium',
            ];
            $this->updatedLaborOperations(); // Save to session
        }
    }

    public function addPart()
    {
        $this->parts_required[] = [
            'part_id' => null,
            'part_name' => '',
            'part_number' => '',
            'quantity' => 1,
            'estimated_cost' => 0,
            'availability' => 'in_stock',
        ];
        $this->updatedPartsRequired(); // Save to session
    }

    public function removePart($index)
    {
        unset($this->parts_required[$index]);
        $this->parts_required = array_values($this->parts_required);
        $this->updatedPartsRequired(); // Save to session
    }

    public function addLaborOperation()
    {
        $this->labor_operations[] = [
            'service_item_id' => null,
            'operation' => '',
            'description' => '',
            'estimated_hours' => 0,
            'labor_rate' => 85.00,
            'category' => '',
            'complexity' => 'medium',
        ];
        $this->updatedLaborOperations(); // Save to session
    }

    public function removeLaborOperation($index)
    {
        unset($this->labor_operations[$index]);
        $this->labor_operations = array_values($this->labor_operations);
        $this->updatedLaborOperations(); // Save to session
    }

    public function saveProgress()
    {
        // Manually save current progress to session
        $this->updatedPartsRequired();
        $this->updatedLaborOperations();
        $this->updatedDiagnosticCodes();

        session()->flash('progress_saved', 'Progress saved successfully!');
    }

    public function addDiagnosticCode()
    {
        $this->diagnostic_codes[] = [
            'code' => '',
            'description' => '',
            'system' => '',
            'severity' => 'medium',
        ];
    }

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

    public function addTestResult()
    {
        $this->test_results[] = [
            'test_name' => '',
            'result' => '',
            'specification' => '',
            'status' => 'pass',
        ];
    }

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

    public function addSpecialTool()
    {
        $this->special_tools_required[] = [
            'tool_name' => '',
            'tool_type' => '',
            'availability' => 'available',
        ];
    }

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

    public function togglePartsSection()
    {
        $this->showPartsSection = ! $this->showPartsSection;
    }

    public function toggleLaborSection()
    {
        $this->showLaborSection = ! $this->showLaborSection;
    }

    public function toggleDiagnosticCodesSection()
    {
        $this->showDiagnosticCodesSection = ! $this->showDiagnosticCodesSection;
    }

    public function toggleTestResultsSection()
    {
        $this->showTestResultsSection = ! $this->showTestResultsSection;
    }

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

    public function toggleTimesheetSection()
    {
        $this->showTimesheetSection = ! $this->showTimesheetSection;
    }

    public function calculateTotalEstimatedCost()
    {
        $partsCost = array_sum(array_map(function ($part) {
            return ($part['quantity'] ?? 1) * ($part['estimated_cost'] ?? 0);
        }, $this->parts_required));

        $laborCost = 0;
        foreach ($this->labor_operations as $operation) {
            $laborCost += ($operation['estimated_hours'] ?? 0) * ($operation['labor_rate'] ?? 85);
        }

        // Include diagnostic time costs
        $diagnosticCost = collect($this->timesheets)->sum('total_amount');

        return $partsCost + $laborCost + $diagnosticCost;
    }

    private function createEstimateFromDiagnosis($diagnosis)
    {
        // Calculate totals
        $partsCost = array_sum(array_map(function ($part) {
            return ($part['quantity'] ?? 1) * ($part['estimated_cost'] ?? 0);
        }, $this->parts_required));

        $laborCost = 0;
        foreach ($this->labor_operations as $operation) {
            $laborCost += ($operation['estimated_hours'] ?? 0) * ($operation['labor_rate'] ?? 85);
        }

        $subtotal = $partsCost + $laborCost;
        $taxRate = 0.0875; // 8.75% tax rate - should be configurable
        $taxAmount = $subtotal * $taxRate;
        $totalAmount = $subtotal + $taxAmount;

        // Create the estimate
        $estimate = Estimate::create([
            'job_card_id' => $this->jobCard->id,
            'diagnosis_id' => $diagnosis->id,
            'estimate_number' => 'EST-'.str_pad(Estimate::max('id') + 1, 6, '0', STR_PAD_LEFT),
            'customer_id' => $this->jobCard->customer_id,
            'vehicle_id' => $this->jobCard->vehicle_id,
            'prepared_by_id' => auth()->id(),
            'status' => 'draft',
            'priority_level' => $this->priority_level,
            'estimated_completion_date' => now()->addHours($this->estimated_repair_time),
            'subtotal' => $subtotal,
            'tax_rate' => $taxRate,
            'tax_amount' => $taxAmount,
            'total_amount' => $totalAmount,
            'notes' => 'Auto-generated from diagnosis: '.$diagnosis->id,
            'validity_period_days' => 30,
        ]);

        // Create line items for parts
        foreach ($this->parts_required as $part) {
            if (! empty($part['part_name'])) {
                EstimateLineItem::create([
                    'estimate_id' => $estimate->id,
                    'type' => 'part',
                    'part_id' => $part['part_id'] ?? null,
                    'description' => $part['part_name'],
                    'part_number' => $part['part_number'] ?? null,
                    'quantity' => $part['quantity'] ?? 1,
                    'unit_price' => $part['estimated_cost'] ?? 0,
                    'total_price' => ($part['quantity'] ?? 1) * ($part['estimated_cost'] ?? 0),
                ]);
            }
        }

        // Create line items for labor
        foreach ($this->labor_operations as $operation) {
            if (! empty($operation['operation'])) {
                EstimateLineItem::create([
                    'estimate_id' => $estimate->id,
                    'type' => 'labor',
                    'service_item_id' => $operation['service_item_id'] ?? null,
                    'description' => $operation['operation'],
                    'labor_hours' => $operation['estimated_hours'] ?? 0,
                    'labor_rate' => $operation['labor_rate'] ?? 85,
                    'total_price' => ($operation['estimated_hours'] ?? 0) * ($operation['labor_rate'] ?? 85),
                ]);
            }
        }

        return $estimate;
    }

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

        // End any active timesheet
        if ($this->currentTimesheet) {
            $this->endTimesheet();
        }

        // Handle photo uploads
        $photoUrls = [];
        if ($this->photos) {
            foreach ($this->photos as $photo) {
                $photoUrls[] = $photo->store('diagnosis', 'public');
            }
        }

        $diagnosis = Diagnosis::create([
            'job_card_id' => $this->jobCard->id,
            'service_coordinator_id' => auth()->id(),
            'customer_reported_issues' => $this->customer_reported_issues,
            'diagnostic_findings' => $this->diagnostic_findings,
            'root_cause_analysis' => $this->root_cause_analysis,
            'recommended_repairs' => $this->recommended_repairs,
            'additional_issues_found' => $this->additional_issues_found,
            'priority_level' => $this->priority_level,
            'estimated_repair_time' => $this->estimated_repair_time,
            'parts_required' => array_filter($this->parts_required, function ($part) {
                return ! empty($part['part_name']);
            }),
            'labor_operations' => array_filter($this->labor_operations, function ($operation) {
                return ! empty($operation['operation']);
            }),
            'special_tools_required' => array_filter($this->special_tools_required, function ($tool) {
                return ! empty($tool['tool_name']);
            }),
            'safety_concerns' => $this->safety_concerns,
            'diagnostic_codes' => array_filter($this->diagnostic_codes, function ($code) {
                return ! empty($code['code']);
            }),
            'test_results' => array_filter($this->test_results, function ($result) {
                return ! empty($result['test_name']);
            }),
            'photos' => $photoUrls,
            'notes' => $this->notes,
            'environmental_impact' => $this->environmental_impact,
            'customer_authorization_required' => $this->customer_authorization_required,
            'diagnosis_status' => 'completed',
            'diagnosis_date' => now(),
        ]);

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

        // Create estimate automatically
        $estimate = $this->createEstimateFromDiagnosis($diagnosis);

        // Clear session data after successful diagnosis creation
        session()->forget([
            "diagnosis_parts_{$this->jobCard->id}",
            "diagnosis_labor_{$this->jobCard->id}",
            "diagnosis_codes_{$this->jobCard->id}",
        ]);

        session()->flash('message', 'Diagnosis completed successfully! Estimate #'.$estimate->estimate_number.' has been created automatically.');

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

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