<?php

declare(strict_types=1);

namespace App\Tests\Unit\Administration\Domain\Model\Session;

use App\Administration\Domain\Model\Session\DeviceInfo;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

final class DeviceInfoTest extends TestCase
{
    #[Test]
    #[DataProvider('userAgentProvider')]
    public function fromUserAgentParsesCorrectly(
        string $userAgent,
        string $expectedDevice,
        string $expectedBrowser,
        string $expectedOs,
    ): void {
        $deviceInfo = DeviceInfo::fromUserAgent($userAgent);

        self::assertSame($expectedDevice, $deviceInfo->device);
        self::assertSame($expectedBrowser, $deviceInfo->browser);
        self::assertSame($expectedOs, $deviceInfo->os);
        self::assertSame($userAgent, $deviceInfo->rawUserAgent);
    }

    /**
     * @return iterable<string, array{string, string, string, string}>
     */
    public static function userAgentProvider(): iterable
    {
        yield 'Chrome on Windows' => [
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
            'Desktop',
            'Chrome 120',
            'Windows 10',
        ];

        yield 'Firefox on macOS' => [
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:121.0) Gecko/20100101 Firefox/121.0',
            'Desktop',
            'Firefox 121',
            'macOS 10.15',
        ];

        yield 'Safari on iPhone' => [
            'Mozilla/5.0 (iPhone; CPU iPhone OS 17_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Mobile/15E148 Safari/604.1',
            'Mobile',
            'Safari 17',
            'iOS 17.2',
        ];

        yield 'Chrome on Android' => [
            'Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.144 Mobile Safari/537.36',
            'Mobile',
            'Chrome 120',
            'Android 14',
        ];

        yield 'Safari on iPad' => [
            'Mozilla/5.0 (iPad; CPU OS 17_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Mobile/15E148 Safari/604.1',
            'Tablet',
            'Safari 17',
            'iPadOS 17.2',
        ];

        yield 'Edge on Windows' => [
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0',
            'Desktop',
            'Edge 120',
            'Windows 10',
        ];
    }

    #[Test]
    public function fromUserAgentHandlesEmptyString(): void
    {
        $deviceInfo = DeviceInfo::fromUserAgent('');

        self::assertSame('Inconnu', $deviceInfo->device);
        self::assertSame('Inconnu', $deviceInfo->browser);
        self::assertSame('Inconnu', $deviceInfo->os);
    }

    #[Test]
    public function fromUserAgentHandlesUnknownUserAgent(): void
    {
        $deviceInfo = DeviceInfo::fromUserAgent('Some Random Bot/1.0');

        self::assertSame('Inconnu', $deviceInfo->device);
        self::assertSame('Inconnu', $deviceInfo->browser);
        self::assertSame('Inconnu', $deviceInfo->os);
    }

    #[Test]
    public function reconstituteRestoresFromStorage(): void
    {
        $deviceInfo = DeviceInfo::reconstitute(
            device: 'Desktop',
            browser: 'Chrome 120',
            os: 'Windows 10',
            rawUserAgent: 'Mozilla/5.0...',
        );

        self::assertSame('Desktop', $deviceInfo->device);
        self::assertSame('Chrome 120', $deviceInfo->browser);
        self::assertSame('Windows 10', $deviceInfo->os);
        self::assertSame('Mozilla/5.0...', $deviceInfo->rawUserAgent);
    }

    #[Test]
    public function isMobileReturnsTrueForMobileDevices(): void
    {
        $mobile = DeviceInfo::fromUserAgent(
            'Mozilla/5.0 (iPhone; CPU iPhone OS 17_2 like Mac OS X) AppleWebKit/605.1.15',
        );
        $desktop = DeviceInfo::fromUserAgent(
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0',
        );

        self::assertTrue($mobile->isMobile());
        self::assertFalse($desktop->isMobile());
    }
}
