<?php

declare(strict_types=1);

namespace App\Framework\UserAgent;

use App\Framework\Core\ValueObjects\Version;
use App\Framework\UserAgent\Enums\BrowserType;
use App\Framework\UserAgent\Enums\EngineType;
use App\Framework\UserAgent\Enums\PlatformType;
use App\Framework\UserAgent\ValueObjects\DeviceCategory;

/**
 * Value Object representing a parsed User-Agent with rich metadata
 * Immutable data structure optimized for business logic
 */
final readonly class ParsedUserAgent
{
    public function __construct(
        public string $raw,
        public BrowserType $browser,
        public Version $browserVersion,
        public PlatformType $platform,
        public Version $platformVersion,
        public EngineType $engine,
        public Version $engineVersion,
        public bool $isMobile,
        public bool $isBot,
        public bool $isModern
    ) {
    }

    /**
     * Get original UserAgent object
     */
    public function getUserAgent(): UserAgent
    {
        return UserAgent::fromString($this->raw);
    }

    /**
     * Get browser display name with version
     */
    public function getBrowserName(): string
    {
        return $this->browser->getDisplayName() . ' ' . $this->browserVersion->toString();
    }

    /**
     * Get platform display name with version
     */
    public function getPlatformName(): string
    {
        return $this->platform->getDisplayName() . ' ' . $this->platformVersion->toString();
    }

    /**
     * Get engine display name with version
     */
    public function getEngineName(): string
    {
        return $this->engine->getDisplayName() . ' ' . $this->engineVersion->toString();
    }

    /**
     * Get a comprehensive summary
     */
    public function getSummary(): string
    {
        $parts = [$this->getBrowserName()];

        $parts[] = 'on ' . $this->getPlatformName();

        if ($this->isMobile) {
            $parts[] = '(Mobile)';
        }

        if ($this->isBot) {
            $parts[] = '(Bot)';
        }

        return implode(' ', $parts);
    }

    /**
     * Check if browser supports specific web features
     */
    public function supports(string $feature): bool
    {
        if (! $this->isModern || $this->isBot) {
            return false;
        }

        return match ($feature) {
            // Image formats
            'webp' => $this->browser->getEngine() === EngineType::BLINK ||
                     ($this->browser === BrowserType::FIREFOX &&
                      $this->browserVersion->isNewerThan(Version::fromString('65.0')) ||
                      $this->browserVersion->equals(Version::fromString('65.0'))),
            'avif' => $this->browser->getEngine() === EngineType::BLINK &&
                     ($this->browserVersion->isNewerThan(Version::fromString('85.0')) ||
                      $this->browserVersion->equals(Version::fromString('85.0'))),

            // JavaScript features
            'es6', 'css-custom-properties', 'css-flexbox', 'css-grid', 'webrtc', 'websockets' => $this->isModern,
            'es2017' => $this->isModern && $this->supportsEs2017(),
            'es2020' => $this->isModern && $this->supportsEs2020(),

            // Web APIs
            'service-worker' => $this->isModern && $this->platform !== PlatformType::IOS,
            'web-push' => $this->isModern && $this->browser !== BrowserType::SAFARI,

            default => false
        };
    }

    /**
     * Check if browser supports ES2017
     */
    private function supportsEs2017(): bool
    {
        $minVersion = $this->getEs2017MinVersion();

        return $this->browserVersion->isNewerThan($minVersion) ||
               $this->browserVersion->equals($minVersion);
    }

    /**
     * Check if browser supports ES2020
     */
    private function supportsEs2020(): bool
    {
        $minVersion = $this->getEs2020MinVersion();

        return $this->browserVersion->isNewerThan($minVersion) ||
               $this->browserVersion->equals($minVersion);
    }

    /**
     * Get minimum browser version for ES2017 support
     */
    private function getEs2017MinVersion(): Version
    {
        $versionString = match ($this->browser) {
            BrowserType::CHROME => '58.0.0',
            BrowserType::FIREFOX => '52.0.0',
            BrowserType::SAFARI => '10.1.0',
            BrowserType::EDGE => '79.0.0',
            BrowserType::OPERA => '45.0.0',
            default => '999.0.0'
        };

        return Version::fromString($versionString);
    }

    /**
     * Get minimum browser version for ES2020 support
     */
    private function getEs2020MinVersion(): Version
    {
        $versionString = match ($this->browser) {
            BrowserType::CHROME => '80.0.0',
            BrowserType::FIREFOX => '72.0.0',
            BrowserType::SAFARI => '13.1.0',
            BrowserType::EDGE => '80.0.0',
            BrowserType::OPERA => '67.0.0',
            default => '999.0.0'
        };

        return Version::fromString($versionString);
    }

    /**
     * Get device category
     */
    public function getDeviceCategory(): DeviceCategory
    {
        if ($this->isBot) {
            return DeviceCategory::BOT;
        }

        if ($this->platform->isMobile()) {
            return DeviceCategory::MOBILE;
        }

        if ($this->platform->isDesktop()) {
            return DeviceCategory::DESKTOP;
        }

        return DeviceCategory::UNKNOWN;
    }

    /**
     * Convert to array representation
     * @return array<string, mixed>
     */
    public function toArray(): array
    {
        return [
            'raw' => $this->raw,
            'browser' => [
                'type' => $this->browser->value,
                'name' => $this->browser->getDisplayName(),
                'version' => $this->browserVersion->toString(),
                'fullName' => $this->getBrowserName(),
            ],
            'platform' => [
                'type' => $this->platform->value,
                'name' => $this->platform->getDisplayName(),
                'version' => $this->platformVersion->toString(),
                'fullName' => $this->getPlatformName(),
                'family' => $this->platform->getFamily(),
            ],
            'engine' => [
                'type' => $this->engine->value,
                'name' => $this->engine->getDisplayName(),
                'version' => $this->engineVersion->toString(),
                'fullName' => $this->getEngineName(),
                'developer' => $this->engine->getDeveloper(),
            ],
            'flags' => [
                'isMobile' => $this->isMobile,
                'isBot' => $this->isBot,
                'isModern' => $this->isModern,
            ],
            'deviceCategory' => $this->getDeviceCategory()->value,
            'summary' => $this->getSummary(),
        ];
    }

    /**
     * String representation
     */
    public function __toString(): string
    {
        return $this->getSummary();
    }
}
