<?php

namespace Tests\Unit;

use App\Models\FingerprintMachine;
use App\Services\Fingerprint\FingerprintDeviceManager;
use App\Services\Fingerprint\Local\AdmsPushProvider;
use App\Services\Fingerprint\Local\FingerspotLocalConnectorProvider;
use App\Services\Fingerprint\Local\FingerspotLocalProvider;
use App\Services\Fingerprint\Local\ZKTecoLegacyProvider;
use InvalidArgumentException;
use Tests\TestCase;

class FingerprintDeviceManagerTest extends TestCase
{
    /** (Software Contract Test - Mocked) */
    public function test_manager_resolves_adms_push_provider(): void
    {
        $machine = new FingerprintMachine([
            'connection_type' => 'adms',
            'protocol' => 'adms_push',
            'cloud_id' => 'DEMO-ADMS-01',
        ]);

        $manager = app(FingerprintDeviceManager::class);
        $provider = $manager->make($machine);

        $this->assertInstanceOf(AdmsPushProvider::class, $provider);
    }

    /** (Software Contract Test - Mocked) */
    public function test_manager_resolves_local_connector_provider(): void
    {
        $machine = new FingerprintMachine([
            'connection_type' => 'local_connector',
            'protocol' => 'local_connector',
            'ip_address' => '192.168.1.100',
            'port' => '8000',
        ]);

        $manager = app(FingerprintDeviceManager::class);
        $provider = $manager->make($machine);

        $this->assertInstanceOf(FingerspotLocalConnectorProvider::class, $provider);
    }

    /** (Software Contract Test - Mocked) */
    public function test_manager_resolves_zkteco_legacy_provider(): void
    {
        $machine = new FingerprintMachine([
            'connection_type' => 'local',
            'protocol' => 'zkteco_legacy',
            'ip_address' => '192.168.1.201',
            'port' => '4370',
        ]);

        $manager = app(FingerprintDeviceManager::class);
        $provider = $manager->make($machine);

        $this->assertInstanceOf(ZKTecoLegacyProvider::class, $provider);
    }

    /** (Software Contract Test - Mocked) */
    public function test_manager_resolves_direct_socket_local_provider(): void
    {
        $machine = new FingerprintMachine([
            'connection_type' => 'local',
            'protocol' => 'fingerspot_local',
            'ip_address' => '192.168.1.201',
            'port' => '4370',
        ]);

        $manager = app(FingerprintDeviceManager::class);
        $provider = $manager->make($machine);

        $this->assertInstanceOf(FingerspotLocalProvider::class, $provider);
    }

    /** (Software Contract Test - Mocked) */
    public function test_manager_handles_empty_legacy_connection_fields_with_fallback(): void
    {
        $machine = new FingerprintMachine([
            'name' => 'Legacy Machine X TKJ',
            'connection_type' => null,
            'protocol' => null,
            'ip_address' => '192.168.1.201',
            'port' => '4370',
        ]);

        $manager = app(FingerprintDeviceManager::class);
        $provider = $manager->make($machine);

        $this->assertInstanceOf(AdmsPushProvider::class, $provider);
    }

    /** (Software Contract Test - Mocked) */
    public function test_manager_throws_exception_on_invalid_protocol(): void
    {
        $this->expectException(InvalidArgumentException::class);

        $machine = new FingerprintMachine([
            'connection_type' => 'invalid_type',
            'protocol' => 'unknown_protocol',
            'name' => 'Invalid Test Machine',
        ]);

        $manager = app(FingerprintDeviceManager::class);
        $manager->make($machine);
    }
}
