<?php

namespace App\Jobs;

use App\Models\{
    ImportFile,
    ImportError,
    Device,
    Activation
};

use App\Imports\ChunkReadFilter;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Shared\Date as ExcelDate;
use Carbon\Carbon;

class ProcessActivationImport
{
    protected int $importFileId;

    public function __construct(int $importFileId)
    {
        $this->importFileId = $importFileId;
    }

    public function handle(): void
    {
        // 🔥 allow big imports
        set_time_limit(0);
        ini_set('memory_limit', '1024M');

        $importFile = ImportFile::findOrFail($this->importFileId);

        if (!$importFile->file_path) {
            $importFile->update(['status' => 'failed']);
            return;
        }

        $filePath = Storage::disk('local')->path($importFile->file_path);

        if (!file_exists($filePath)) {
            $importFile->update(['status' => 'failed']);
            return;
        }

        // 🔒 hard lock state
        $importFile->update([
            'status'         => 'processing',
            'processed_rows' => 0,
        ]);

        $reader = IOFactory::createReaderForFile($filePath);
        $reader->setReadDataOnly(true);

        $info = $reader->listWorksheetInfo($filePath);
        $totalRows = max(((int) ($info[0]['totalRows'] ?? 0)) - 1, 0);

        $importFile->update(['total_rows' => $totalRows]);

        if ($totalRows === 0) {
            $importFile->update([
                'processed_rows' => 0,
                'status' => 'completed'
            ]);
            return;
        }

        $chunkSize = 2000; // ⚡ faster than 1000 (safe for 30k)
        $filter = new ChunkReadFilter();
        $reader->setReadFilter($filter);

        $processed = 0;

        for ($startRow = 2; $startRow <= ($totalRows + 1); $startRow += $chunkSize) {

            $filter->setRows($startRow, $chunkSize);

            $spreadsheet = $reader->load($filePath);
            $sheet = $spreadsheet->getActiveSheet();

            for ($row = $startRow; $row < ($startRow + $chunkSize) && $row <= ($totalRows + 1); $row++) {

                // ✅ ALWAYS count row for progress (even if empty)
                $processed++;

                // IMEI (Column C)
                $imei = trim(
                    preg_replace(
                        '/\D/',
                        '',
                        (string) $sheet->getCell("C{$row}")->getFormattedValue()
                    )
                );

                if ($imei === '') {
                    // optional: log missing imei
                    // $this->logError($importFile, $row, "IMEI missing");
                    continue;
                }

                // Activation date (G -> H fallback)
                $rawDate =
                    $sheet->getCell("G{$row}")->getValue()
                    ?: $sheet->getCell("H{$row}")->getValue();

                // ✅ Excel safe date parse
                try {
                    if (is_numeric($rawDate)) {
                        $activationDate = Carbon::instance(
                            ExcelDate::excelToDateTimeObject($rawDate)
                        );
                    } else {
                        $activationDate = $rawDate
                            ? Carbon::parse($rawDate)
                            : now();
                    }
                } catch (\Throwable $e) {
                    $activationDate = now();
                }

                $province = trim((string) $sheet->getCell("L{$row}")->getValue());
                $city     = trim((string) $sheet->getCell("M{$row}")->getValue());

                try {
                    DB::transaction(function () use (
                        $importFile,
                        $imei,
                        $activationDate,
                        $province,
                        $city
                    ) {
                        $device = Device::where('tenant_id', $importFile->tenant_id)
                            ->where(function ($q) use ($imei) {
                                $q->where('imei_1', $imei)
                                  ->orWhere('imei_2', $imei);
                            })
                            ->first();

                        if (!$device) {
                            throw new \Exception("Device not found for IMEI {$imei}");
                        }

                        // ✅ correct enum value
                        if ($device->status === 'active') {
                            throw new \Exception("Device already activated ({$imei})");
                        }

                        if (Activation::where('device_id', $device->id)->exists()) {
                            throw new \Exception("Activation already exists ({$imei})");
                        }

                        Activation::create([
                            'tenant_id'       => $importFile->tenant_id,
                            'device_id'       => $device->id,
                            'activated_imei'  => $imei,
                            'activation_date' => $activationDate,
                            'province'        => $province,
                            'city'            => $city,
                            'import_file_id'  => $importFile->id,
                        ]);

                        // ✅ update device status properly
                        $device->update([
                            'status' => 'active',
                        ]);
                    });

                } catch (\Throwable $e) {
                    $this->logError($importFile, $row, $e->getMessage());
                }

                // progress update in DB
                if ($processed % 200 === 0) {
                    ImportFile::where('id', $importFile->id)
                        ->update(['processed_rows' => $processed]);
                }
            }

            $spreadsheet->disconnectWorksheets();
            unset($spreadsheet);
        }

        // ✅ finalize - force 100%
        $importFile->update([
            'processed_rows' => $totalRows,
            'status'         => 'completed',
        ]);
    }

    private function logError(ImportFile $importFile, int $row, string $msg): void
    {
        ImportError::create([
            'import_file_id' => $importFile->id,
            'row_number'     => $row,
            'error_message'  => $msg,
            'created_by'     => $importFile->uploaded_by,
        ]);
    }
}
