<?php

namespace App\Livewire\Admin\QrCodes;

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

class Import extends Component
{
    use WithFileUploads;

    public $csvFile;
    public $isImporting = false;
    public $importProgress = 0;
    public $importTotal = 0;
    public $importedCount = 0;
    public $skippedCount = 0;
    public $importComplete = false;

    protected $rules = [
        'csvFile' => 'required|file|mimes:csv,txt|max:51200', // 50MB max
    ];

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

        $this->isImporting = true;
        $this->importProgress = 0;
        $this->importedCount = 0;
        $this->skippedCount = 0;
        $this->importComplete = false;

        try {
            // Read CSV file
            $path = $this->csvFile->getRealPath();
            $file = fopen($path, 'r');

            // Read and map header row
            $header = fgetcsv($file);

            // Validate that we have headers
            if (!$header || count($header) < 2) {
                throw new \Exception('Invalid CSV file: No headers found or insufficient columns.');
            }

            $columnMap = $this->mapColumns($header);

            // Validate required columns are present
            if (!isset($columnMap['serial']) || !isset($columnMap['qr_pin'])) {
                throw new \Exception('Invalid CSV format: Required columns "serial" and "qr_pin" not found. Found columns: ' . implode(', ', $header));
            }

            // Count total rows for progress
            $totalRows = 0;
            while (fgetcsv($file) !== false) {
                $totalRows++;
            }
            $this->importTotal = $totalRows;

            // Reset file pointer
            rewind($file);
            fgetcsv($file); // Skip header again

            $batchSize = 100;
            $batch = [];
            $rowCount = 0;

            while (($row = fgetcsv($file)) !== false) {
                $rowCount++;

                // Parse row using column mapping
                $serial = isset($columnMap['serial']) ? trim($row[$columnMap['serial']]) : null;
                $qrPin = isset($columnMap['qr_pin']) ? trim(strtoupper($row[$columnMap['qr_pin']])) : null;

                // Validate required fields
                if (empty($serial) || empty($qrPin)) {
                    $this->skippedCount++;
                    $this->importProgress = $rowCount;
                    continue;
                }

                // Check for duplicates
                if (QrCode::where('serial', $serial)->orWhere('qr_pin', $qrPin)->exists()) {
                    $this->skippedCount++;
                    $this->importProgress = $rowCount;
                    continue;
                }

                // Get status value and validate it
                $status = 'unused';
                if (isset($columnMap['status']) && !empty($row[$columnMap['status']])) {
                    $statusValue = strtolower(trim($row[$columnMap['status']]));
                    // Map various status values to 'unused' or 'used'
                    if (in_array($statusValue, ['used', 'fake'])) {
                        // 'fake' from old codes table is treated as 'used'
                        $status = 'used';
                    } elseif (in_array($statusValue, ['unused', 'original', 'active', 'available'])) {
                        $status = 'unused';
                    }
                }

                // Get used_at timestamp
                $usedAt = null;
                if (isset($columnMap['used_at']) && !empty($row[$columnMap['used_at']])) {
                    $usedAtValue = trim($row[$columnMap['used_at']]);
                    // Only set if it's a valid timestamp format
                    if ($usedAtValue && $usedAtValue !== 'NULL' && strtotime($usedAtValue)) {
                        $usedAt = $usedAtValue;
                    }
                }

                // Get is_lucky flag
                $isLucky = false;
                if (isset($columnMap['is_lucky']) && !empty($row[$columnMap['is_lucky']])) {
                    $isLucky = in_array(strtolower(trim($row[$columnMap['is_lucky']])), ['1', 'true', 'yes']);
                }

                // Get attempts count
                $attempts = 0;
                if (isset($columnMap['attempts']) && !empty($row[$columnMap['attempts']])) {
                    $attempts = max(0, (int) $row[$columnMap['attempts']]);
                }

                $batch[] = [
                    'serial' => $serial,
                    'qr_pin' => $qrPin,
                    'status' => $status,
                    'used_at' => $usedAt,
                    'is_lucky' => $isLucky,
                    'attempts' => $attempts,
                    'created_at' => now(),
                    'updated_at' => now(),
                ];

                // Insert in batches
                if (count($batch) >= $batchSize) {
                    QrCode::insert($batch);
                    $this->importedCount += count($batch);
                    $batch = [];
                }

                $this->importProgress = $rowCount;
            }

            // Insert remaining batch
            if (!empty($batch)) {
                QrCode::insert($batch);
                $this->importedCount += count($batch);
            }

            fclose($file);

            $this->importComplete = true;
            $this->isImporting = false;

            session()->flash('message', "Import completed! Imported: {$this->importedCount}, Skipped: {$this->skippedCount}");

        } catch (\Exception $e) {
            $this->isImporting = false;
            $errorMessage = $e->getMessage();

            // Log detailed error for debugging
            \Log::error('QR Code Import Failed', [
                'error' => $errorMessage,
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]);

            session()->flash('error', 'Import failed: ' . $errorMessage);
        }
    }

    /**
     * Map CSV columns to database columns
     * Supports both old 'codes' table format and new 'qr_codes' table format
     */
    private function mapColumns(array $header): array
    {
        $map = [];

        foreach ($header as $index => $columnName) {
            $columnName = strtolower(trim($columnName));

            // Map various possible column names to standard names
            switch ($columnName) {
                // Serial number mapping (new format uses 'serial', old format uses 'guid')
                case 'serial':
                case 'serial_number':
                case 'serial_no':
                case 'guid':  // Old codes table column
                    $map['serial'] = $index;
                    break;

                // QR PIN mapping (new format uses 'qr_pin', old format uses 'qr')
                case 'qr_pin':
                case 'qrpin':
                case 'pin':
                case 'code':
                case 'qr_code':
                case 'qrcode':
                case 'qr':  // Old codes table column
                    $map['qr_pin'] = $index;
                    break;

                // Status mapping
                case 'status':
                case 'state':
                    $map['status'] = $index;
                    break;

                // Used at timestamp mapping
                case 'used_at':
                case 'usedat':
                case 'used_date':
                case 'date_used':
                case 'lastverified':  // Old codes table column
                    $map['used_at'] = $index;
                    break;

                // Lucky flag mapping (new format uses 'is_lucky', old format uses 'islucky')
                case 'is_lucky':
                case 'islucky':  // Old codes table column
                case 'lucky':
                    $map['is_lucky'] = $index;
                    break;

                // Attempts mapping
                case 'attempts':
                case 'attempt':
                case 'tries':
                    $map['attempts'] = $index;
                    break;
            }
        }

        return $map;
    }

    public function resetImport()
    {
        $this->reset(['csvFile', 'isImporting', 'importProgress', 'importTotal', 'importedCount', 'skippedCount', 'importComplete']);
    }

    public function render()
    {
        return view('livewire.admin.qr-codes.import')
            ->layout('layouts.app');
    }
}
