<?php

namespace App\Services;

use App\Contracts\AuditLogServiceInterface;
use App\DTO\AttendanceEventData;
use App\Enums\PersonnelTargetEnum;
use App\Models\AttendanceLog;
use App\Models\FingerprintMachine;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\RateLimiter;

class SyncService
{
    public function __construct(
        protected FingerprintDeviceManager $deviceManager,
        protected AttendanceProcessorService $processorService,
        protected AuditLogServiceInterface $auditLogService
    ) {}



    /**
     * Mendorong data user aktif ke satu mesin sesuai personnel_target mesin.
     */
    public function pushUsersToMachine(FingerprintMachine $machine, ?array $userIds = null): array
    {
        $target = $machine->personnel_target instanceof PersonnelTargetEnum
            ? $machine->personnel_target
            : PersonnelTargetEnum::tryFrom((string) ($machine->personnel_target ?? 'both')) ?? PersonnelTargetEnum::Both;

        $roleNames = $target->roleNames();

        $query = User::query()
            ->where('is_active', true)
            ->whereHas('role', fn ($q) => $q->whereIn('name', $roleNames));

        if (! empty($userIds)) {
            $query->whereIn('id', $userIds);
        }

        $users = $query->get(['id', 'name', 'nip_nis', 'fingerprint_pin', 'role_id'])
            ->map(fn ($u) => [
                'id' => $u->id,
                'name' => $u->name,
                'fingerprint_pin' => $u->fingerprint_pin ?: substr((string) $u->id, 0, 8),
                'is_admin' => false,
            ])
            ->toArray();

        try {
            $provider = $this->deviceManager->make($machine);
            $res = $provider->pushUsers($machine, $users);

            if ($res['success']) {
                $machine->update([
                    'status' => 'online',
                    'last_sync' => now(),
                ]);

                $targetLabel = $target->label();
                $message = "Berhasil mengunggah {$res['count']} data personil ({$targetLabel}) ke mesin {$machine->name}";

                Log::info($message);

                $currentUser = Auth::user();
                $this->auditLogService->log(
                    $currentUser,
                    'USER_SYNC_PUSH',
                    "Push {$res['count']} personil ({$targetLabel}) ke mesin {$machine->name}"
                );

                $res['message'] = $message;
            }

            return $res;
        } catch (\Throwable $e) {
            $machine->update(['status' => 'offline']);
            Log::error('Koneksi push user gagal/timeout: ' . $e->getMessage());

            return [
                'success' => false,
                'count' => 0,
                'message' => 'Koneksi gagal: ' . $e->getMessage(),
            ];
        }
    }

    /**
     * Mendorong data user ke seluruh mesin; tiap mesin menerima set sesuai targetnya.
     */
    public function pushUsersToAllMachines(?array $userIds = null): array
    {
        $machines = FingerprintMachine::all();
        $totalPushed = 0;
        $successCount = 0;

        foreach ($machines as $machine) {
            $res = $this->pushUsersToMachine($machine, $userIds);
            if ($res['success']) {
                $successCount++;
                $totalPushed += $res['count'];
            }
        }

        return [
            'success' => $successCount > 0,
            'successful_machines' => $successCount,
            'total_pushed' => $totalPushed,
            'message' => "Proses push data personil selesai: {$totalPushed} data terunggah ke {$successCount} mesin (sesuai target masing-masing).",
        ];
    }
}
