<?php

namespace App\Livewire\Admin\QrCodes;

use App\Models\QrCode;
use Livewire\Component;
use Livewire\WithPagination;

class Index extends Component
{
    use WithPagination;

    public $search = '';
    public $perPage = 10;
    public $filterDate = '';
    public $filterStatus = '';
    public $filterLucky = '';
    public $filterAttempts = '';
    public $sortField = 'created_at';
    public $sortDirection = 'desc';

    protected $queryString = [
        'search' => ['except' => ''],
        'perPage' => ['except' => 10],
        'filterDate' => ['except' => ''],
        'filterStatus' => ['except' => ''],
        'filterLucky' => ['except' => ''],
        'filterAttempts' => ['except' => ''],
    ];

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

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

    public function clearDateFilter()
    {
        $this->filterDate = '';
        $this->resetPage();
    }

    public function clearFilters()
    {
        $this->filterDate = '';
        $this->filterStatus = '';
        $this->filterLucky = '';
        $this->filterAttempts = '';
        $this->search = '';
        $this->resetPage();
    }

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

    public function toggleLucky($codeId)
    {
        $code = QrCode::find($codeId);
        if ($code) {
            $code->toggleLucky();
            session()->flash('message', 'Lucky status updated successfully!');
        }
    }

    public function delete($codeId)
    {
        $code = QrCode::find($codeId);
        if ($code) {
            $code->delete();
            session()->flash('message', 'QR Code deleted successfully!');
        }
    }

    public function exportCsv()
    {
        $query = $this->getQuery();
        $filename = 'qr_codes_' . date('Y-m-d_His') . '.csv';

        // Get IDs for updating later (more memory efficient)
        $codeIds = $query->pluck('id')->toArray();

        // Use streaming download with chunking for memory efficiency
        return response()->streamDownload(function() use ($query) {
            $handle = fopen('php://output', 'w');

            // CSV Header
            fputcsv($handle, ['serial', 'url', 'qr_pin']);

            // Process in chunks to avoid memory issues with large datasets
            $query->chunk(1000, function($codes) use ($handle) {
                foreach ($codes as $code) {
                    fputcsv($handle, [
                        $code->serial,
                        $code->url,
                        $code->qr_pin,
                    ]);
                }
            });

            fclose($handle);
        }, $filename, [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="' . $filename . '"',
        ]);

        // Update last_exported_at in chunks to avoid locking issues
        // This runs after the download starts, using a job would be better for very large datasets
        if (count($codeIds) > 0) {
            foreach (array_chunk($codeIds, 1000) as $chunk) {
                QrCode::whereIn('id', $chunk)->update(['last_exported_at' => now()]);
            }
        }
    }

    private function getQuery()
    {
        $query = QrCode::query();

        // Status filter - Uses index
        if ($this->filterStatus !== '') {
            $query->where('status', $this->filterStatus);
        }

        // Lucky filter - Uses index
        if ($this->filterLucky !== '') {
            $query->where('is_lucky', $this->filterLucky === '1');
        }

        // Attempts filter - Uses index
        if ($this->filterAttempts !== '') {
            if ($this->filterAttempts === '0') {
                $query->where('attempts', 0);
            } elseif ($this->filterAttempts === '1-2') {
                $query->whereBetween('attempts', [1, 2]);
            } elseif ($this->filterAttempts === '3-4') {
                $query->whereBetween('attempts', [3, 4]);
            } elseif ($this->filterAttempts === '5+') {
                $query->where('attempts', '>=', 5);
            }
        }

        // Date filter - Uses index
        if ($this->filterDate) {
            $query->whereDate('created_at', $this->filterDate);
        }

        // Search - Optimized for large datasets
        if ($this->search) {
            $searchTerm = trim($this->search);

            $query->where(function($q) use ($searchTerm) {
                // Try exact match first (uses index)
                $q->where('serial', $searchTerm)
                  ->orWhere('qr_pin', $searchTerm)
                  ->orWhere('assigned_to_id', $searchTerm);

                // If search term is long enough, also try prefix match (can use index)
                if (strlen($searchTerm) >= 3) {
                    $q->orWhere('serial', 'like', $searchTerm . '%')
                      ->orWhere('qr_pin', 'like', $searchTerm . '%');
                }

                // Full wildcard search as last resort (slowest but most flexible)
                $q->orWhere('serial', 'like', '%' . $searchTerm . '%')
                  ->orWhere('qr_pin', 'like', '%' . $searchTerm . '%');
            });
        }

        // Sorting - All sortable fields are indexed
        $query->orderBy($this->sortField, $this->sortDirection);

        return $query;
    }

    public function render()
    {
        $codes = $this->getQuery()->paginate($this->perPage);

        return view('livewire.admin.qr-codes.index', [
            'codes' => $codes,
        ])->layout('layouts.app');
    }
}
