<?php

namespace App\Console\Commands;

use App\Models\Attendance;
use App\Models\Device;
use App\Models\StudentFaceRegistration;
use App\Services\FaceDeviceService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class PullAttendanceCommand extends Command
{
    // Jalankan manual: php artisan attendance:pull
    protected $signature = 'attendance:pull {--minutes=10 : Tarik event N menit ke belakang dari sekarang}';

    protected $description = 'Tarik data absensi (event) dari SEMUA device aktif dan simpan ke database';

    public function handle(): int
    {
        $devices = Device::where('is_active', true)->get();

        if ($devices->isEmpty()) {
            $this->warn('Tidak ada device aktif di tabel devices. Tambahkan lewat halaman /devices dulu.');
            return self::FAILURE;
        }

        foreach ($devices as $device) {
            $this->info("=== Menarik data dari device: {$device->name} ({$device->ip_address}) ===");

            try {
                $this->pullFromDevice($device);
                $device->update(['last_synced_at' => now()]);
            } catch (\Throwable $e) {
                $this->error("Gagal narik dari {$device->name}: " . $e->getMessage());
                // Lanjut ke device berikutnya walau satu device gagal, biar gak macet semua
                continue;
            }
        }

        return self::SUCCESS;
    }

    private function pullFromDevice(Device $deviceModel): void
    {
        $service = new FaceDeviceService($deviceModel);

        $end = now();
        $start = now()->subMinutes((int) $this->option('minutes'));

        $position = 0;
        $maxResults = 30;
        $saved = 0;

        do {
            $response = $service->searchAttendanceEvents($start, $end, $position, $maxResults);

            $acsEvent = $response['AcsEvent'] ?? [];
            $infoList = $acsEvent['InfoList'] ?? [];
            $numOfMatches = $acsEvent['numOfMatches'] ?? 0;
            $totalMatches = $acsEvent['totalMatches'] ?? 0;

            foreach ($infoList as $item) {
                $employeeNo = $item['employeeNoString'] ?? null;

                if (!$employeeNo) {
                    continue; // event tanpa employeeNo (misal door open/closed, event sistem) dilewati
                }

                // Hasil pengetesan langsung ke device: minor=75 adalah "Authenticated via Face" (berhasil).
                $successMinorCodes = config('facedevice.success_minor_codes', [75]);

                if (!in_array($item['minor'] ?? null, $successMinorCodes, true)) {
                    continue; // lewati percobaan yang gagal/ditolak, cuma simpan yang benar-benar berhasil absen
                }

                $picturePath = null;
                if (!empty($item['pictureURL'])) {
                    try {
                        $binary = $service->downloadEventPicture($item['pictureURL']);
                        $filename = 'attendance-photos/' . Str::uuid() . '.jpg';
                        Storage::disk('public')->put($filename, $binary);
                        $picturePath = $filename;
                    } catch (\Throwable $e) {
                        $this->warn("Gagal download foto event: " . $e->getMessage());
                    }
                }

                $attendance = Attendance::firstOrCreate(
                    [
                        'employee_no' => $employeeNo,
                        'event_time' => $item['time'] ?? now(),
                        'serial_no' => $item['serialNo'] ?? null,
                    ],
                    [
                        'device_id' => $deviceModel->id,
                        'student_id' => StudentFaceRegistration::studentIdFromEmployeeNo($employeeNo),
                        'name' => $item['name'] ?? null,
                        'attendance_status' => $item['attendanceStatus'] ?? null,
                        'picture_path' => $picturePath,
                        'raw_payload' => $item,
                    ]
                );

                if ($attendance->wasRecentlyCreated) {
                    $saved++;
                }
            }

            $position += $numOfMatches;
        } while ($numOfMatches > 0 && $position < $totalMatches);

        $this->info("Selesai dari {$deviceModel->name}: {$saved} record absensi baru disimpan.");
    }
}