<?php

namespace App\Livewire\Estimates;

use App\Models\Customer;
use App\Models\Estimate;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;

class Index extends Component
{
    use WithPagination;

    #[Url(as: 'search')]
    public $search = '';

    #[Url(as: 'status')]
    public $statusFilter = '';

    #[Url(as: 'approval')]
    public $approvalStatusFilter = '';

    #[Url(as: 'customer')]
    public $customerFilter = '';

    #[Url(as: 'date_from')]
    public $dateFrom = '';

    #[Url(as: 'date_to')]
    public $dateTo = '';

    #[Url(as: 'sort')]
    public $sortBy = 'created_at';

    #[Url(as: 'direction')]
    public $sortDirection = 'desc';

    #[Url(as: 'per_page')]
    public $perPage = 15;

    // Advanced filters
    public $showAdvancedFilters = false;

    public $totalAmountMin = '';

    public $totalAmountMax = '';

    public $validityFilter = '';

    public $branchFilter = '';

    // Bulk operations
    public $bulkMode = false;

    public $selectedEstimates = [];

    public $selectAll = false;

    // Quick stats
    public $stats = [];

    protected $queryString = [
        'search' => ['except' => ''],
        'statusFilter' => ['except' => ''],
        'approvalStatusFilter' => ['except' => ''],
        'customerFilter' => ['except' => ''],
        'dateFrom' => ['except' => ''],
        'dateTo' => ['except' => ''],
        'sortBy' => ['except' => 'created_at'],
        'sortDirection' => ['except' => 'desc'],
        'perPage' => ['except' => 15],
    ];

    public function mount()
    {
        $this->loadStats();
    }

    public function loadStats()
    {
        $userId = auth()->id();

        // Check if user can view all estimates or only their own
        $canViewAll = Auth::user()->can('viewAny', Estimate::class);

        // Build base where clause
        $baseWhere = [];
        if (! $canViewAll) {
            $baseWhere['prepared_by_id'] = $userId;
        }

        // Calculate stats individually with fresh queries each time
        $this->stats = [
            'total' => Estimate::where($baseWhere)->count(),
            'draft' => Estimate::where($baseWhere)->where('status', 'draft')->count(),
            'sent' => Estimate::where($baseWhere)->where('status', 'sent')->count(),
            'approved' => Estimate::where($baseWhere)->where('customer_approval_status', 'approved')->count(),
            'pending' => Estimate::where($baseWhere)->whereIn('status', ['sent', 'viewed'])->where('customer_approval_status', 'pending')->count(),
            'expired' => $this->getExpiredCount($canViewAll ? null : $userId),
            'total_value' => Estimate::where($baseWhere)->sum('total_amount') ?: 0,
            'avg_value' => Estimate::where($baseWhere)->avg('total_amount') ?: 0,
        ];
    }

    private function getExpiredCount($userId = null)
    {
        $query = Estimate::where('status', '!=', 'approved')
            ->whereNotNull('validity_period_days');

        if ($userId) {
            $query->where('prepared_by_id', $userId);
        }

        if (\DB::getDriverName() === 'mysql') {
            return $query->whereRaw('DATE_ADD(created_at, INTERVAL validity_period_days DAY) < NOW()')->count();
        } else {
            return $query->whereRaw("datetime(created_at, '+' || validity_period_days || ' days') < datetime('now')")->count();
        }
    }

    public function getDateAddExpressionForDatabase($comparison = 'expired')
    {
        // Use the actual database connection driver instead of config
        $databaseDriver = \DB::getDriverName();

        if ($databaseDriver === 'mysql') {
            switch ($comparison) {
                case 'expired':
                    return 'DATE_ADD(created_at, INTERVAL validity_period_days DAY) < NOW()';
                case 'expiring_soon':
                    return 'DATE_ADD(created_at, INTERVAL validity_period_days DAY) BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 7 DAY)';
                case 'valid':
                    return 'DATE_ADD(created_at, INTERVAL validity_period_days DAY) > NOW()';
                default:
                    return 'DATE_ADD(created_at, INTERVAL validity_period_days DAY) < NOW()';
            }
        } else {
            // SQLite syntax
            switch ($comparison) {
                case 'expired':
                    return "datetime(created_at, '+' || validity_period_days || ' days') < datetime('now')";
                case 'expiring_soon':
                    return "datetime(created_at, '+' || validity_period_days || ' days') BETWEEN datetime('now') AND datetime('now', '+7 days')";
                case 'valid':
                    return "datetime(created_at, '+' || validity_period_days || ' days') > datetime('now')";
                default:
                    return "datetime(created_at, '+' || validity_period_days || ' days') < datetime('now')";
            }
        }
    }

    public function updatedSearch()
    {
        $this->resetPage();
    }

    public function updatedStatusFilter()
    {
        $this->resetPage();
    }

    public function updatedApprovalStatusFilter()
    {
        $this->resetPage();
    }

    public function updatedCustomerFilter()
    {
        $this->resetPage();
    }

    public function updatedDateFrom()
    {
        $this->resetPage();
    }

    public function updatedDateTo()
    {
        $this->resetPage();
    }

    public function updatedPerPage()
    {
        $this->resetPage();
    }

    public function sortBy($field)
    {
        if ($this->sortBy === $field) {
            $this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc';
        } else {
            $this->sortBy = $field;
            $this->sortDirection = 'asc';
        }
        $this->resetPage();
    }

    public function clearFilters()
    {
        $this->reset([
            'search',
            'statusFilter',
            'approvalStatusFilter',
            'customerFilter',
            'dateFrom',
            'dateTo',
            'totalAmountMin',
            'totalAmountMax',
            'validityFilter',
            'branchFilter',
        ]);
        $this->resetPage();
    }

    public function toggleAdvancedFilters()
    {
        $this->showAdvancedFilters = ! $this->showAdvancedFilters;
    }

    public function toggleBulkMode()
    {
        $this->bulkMode = ! $this->bulkMode;
        $this->selectedEstimates = [];
        $this->selectAll = false;
    }

    public function updatedSelectAll($value)
    {
        if ($value) {
            $this->selectedEstimates = $this->getEstimates()->pluck('id')->toArray();
        } else {
            $this->selectedEstimates = [];
        }
    }

    public function bulkAction($action)
    {
        if (empty($this->selectedEstimates)) {
            session()->flash('error', 'Please select estimates to perform bulk action.');

            return;
        }

        $estimates = Estimate::whereIn('id', $this->selectedEstimates)->get();

        switch ($action) {
            case 'delete':
                $estimates->each(function ($estimate) {
                    if (Auth::user()->can('delete', $estimate)) {
                        $estimate->delete();
                    }
                });
                session()->flash('success', count($this->selectedEstimates).' estimates deleted.');
                break;

            case 'mark_sent':
                $estimates->each(function ($estimate) {
                    if (Auth::user()->can('update', $estimate)) {
                        $estimate->update([
                            'status' => 'sent',
                            'sent_to_customer_at' => now(),
                        ]);
                    }
                });
                session()->flash('success', count($this->selectedEstimates).' estimates marked as sent.');
                break;

            case 'export':
                // Export functionality would go here
                session()->flash('success', 'Export started for '.count($this->selectedEstimates).' estimates.');
                break;
        }

        $this->selectedEstimates = [];
        $this->selectAll = false;
        $this->bulkMode = false;
        $this->loadStats();
    }

    public function getEstimates()
    {
        $query = Estimate::with([
            'jobCard.customer',
            'jobCard.vehicle',
            'jobCard.branch',
            'customer', // For standalone estimates
            'vehicle',  // For standalone estimates
            'preparedBy',
        ]);

        // Apply permissions
        if (! Auth::user()->can('viewAny', Estimate::class)) {
            $query->where('prepared_by_id', Auth::id());
        }

        // Search filter
        if ($this->search) {
            $query->where(function ($q) {
                $q->where('estimate_number', 'like', '%'.$this->search.'%')
                    // Search in jobCard customers (traditional estimates)
                    ->orWhereHas('jobCard.customer', function ($customerQuery) {
                        $customerQuery->where('first_name', 'like', '%'.$this->search.'%')
                            ->orWhere('last_name', 'like', '%'.$this->search.'%')
                            ->orWhere('email', 'like', '%'.$this->search.'%')
                            ->orWhere('phone', 'like', '%'.$this->search.'%');
                    })
                    // Search in direct customers (standalone estimates)
                    ->orWhereHas('customer', function ($customerQuery) {
                        $customerQuery->where('first_name', 'like', '%'.$this->search.'%')
                            ->orWhere('last_name', 'like', '%'.$this->search.'%')
                            ->orWhere('email', 'like', '%'.$this->search.'%')
                            ->orWhere('phone', 'like', '%'.$this->search.'%');
                    })
                    // Search in jobCard vehicles (traditional estimates)
                    ->orWhereHas('jobCard.vehicle', function ($vehicleQuery) {
                        $vehicleQuery->where('license_plate', 'like', '%'.$this->search.'%')
                            ->orWhere('vin', 'like', '%'.$this->search.'%')
                            ->orWhereRaw("CONCAT(year, ' ', make, ' ', model) LIKE ?", ['%'.$this->search.'%']);
                    })
                    // Search in direct vehicles (standalone estimates)
                    ->orWhereHas('vehicle', function ($vehicleQuery) {
                        $vehicleQuery->where('license_plate', 'like', '%'.$this->search.'%')
                            ->orWhere('vin', 'like', '%'.$this->search.'%')
                            ->orWhereRaw("CONCAT(year, ' ', make, ' ', model) LIKE ?", ['%'.$this->search.'%']);
                    });
            });
        }

        // Status filter
        if ($this->statusFilter) {
            if ($this->statusFilter === 'pending_approval') {
                $query->whereIn('status', ['sent', 'viewed'])
                    ->where('customer_approval_status', 'pending');
            } elseif ($this->statusFilter === 'expired') {
                $query->whereRaw($this->getDateAddExpressionForDatabase('expired'))
                    ->where('status', '!=', 'approved');
            } else {
                $query->where('status', $this->statusFilter);
            }
        }

        // Approval status filter
        if ($this->approvalStatusFilter) {
            $query->where('customer_approval_status', $this->approvalStatusFilter);
        }

        // Customer filter
        if ($this->customerFilter) {
            $query->whereHas('jobCard.customer', function ($customerQuery) {
                $customerQuery->where('id', $this->customerFilter);
            });
        }

        // Date filters
        if ($this->dateFrom) {
            $query->whereDate('created_at', '>=', $this->dateFrom);
        }

        if ($this->dateTo) {
            $query->whereDate('created_at', '<=', $this->dateTo);
        }

        // Advanced filters
        if ($this->totalAmountMin) {
            $query->where('total_amount', '>=', $this->totalAmountMin);
        }

        if ($this->totalAmountMax) {
            $query->where('total_amount', '<=', $this->totalAmountMax);
        }

        if ($this->validityFilter) {
            if ($this->validityFilter === 'expired') {
                $query->whereRaw($this->getDateAddExpressionForDatabase('expired'));
            } elseif ($this->validityFilter === 'expiring_soon') {
                $query->whereRaw($this->getDateAddExpressionForDatabase('expiring_soon'));
            } elseif ($this->validityFilter === 'valid') {
                $query->whereRaw($this->getDateAddExpressionForDatabase('valid'));
            }
        }

        if ($this->branchFilter) {
            $query->whereHas('jobCard.branch', function ($branchQuery) {
                $branchQuery->where('code', $this->branchFilter);
            });
        }

        // Sorting
        $query->orderBy($this->sortBy, $this->sortDirection);

        return $query->paginate($this->perPage);
    }

    public function getCustomersProperty()
    {
        return Customer::orderBy('first_name')->orderBy('last_name')->get(['id', 'first_name', 'last_name'])->map(function ($customer) {
            return (object) [
                'id' => $customer->id,
                'name' => $customer->name,
            ];
        });
    }

    public function getBranchesProperty()
    {
        return \App\Models\Branch::orderBy('name')->get(['code', 'name']);
    }

    public function sendEstimate($estimateId)
    {
        $estimate = Estimate::findOrFail($estimateId);

        if (! Auth::user()->can('update', $estimate)) {
            session()->flash('error', 'You are not authorized to send this estimate.');

            return;
        }

        if ($estimate->status !== 'draft') {
            session()->flash('error', 'Only draft estimates can be sent.');

            return;
        }

        $estimate->update([
            'status' => 'sent',
            'sent_to_customer_at' => now(),
        ]);

        // TODO: Send email/SMS notification to customer

        session()->flash('success', 'Estimate sent to customer successfully.');
        $this->loadStats();
    }

    public function confirmDelete($estimateId)
    {
        $estimate = Estimate::findOrFail($estimateId);

        if (! Auth::user()->can('delete', $estimate)) {
            session()->flash('error', 'You are not authorized to delete this estimate.');

            return;
        }

        // For now, just delete directly. In production, you might want a confirmation modal
        $estimate->delete();

        session()->flash('success', 'Estimate deleted successfully.');
        $this->loadStats();
    }

    #[Layout('components.layouts.app')]
    public function render()
    {
        // Get available diagnoses that don't have estimates yet
        $availableDiagnoses = \App\Models\Diagnosis::whereDoesntHave('estimate')
            ->with(['jobCard.customer', 'jobCard.vehicle'])
            ->latest()
            ->limit(5)
            ->get();

        return view('livewire.estimates.index', [
            'estimates' => $this->getEstimates(),
            'customers' => $this->customers,
            'branches' => $this->branches,
            'stats' => $this->stats,
            'availableDiagnoses' => $availableDiagnoses,
        ]);
    }
}
