<?php

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
#[ORM\Index(columns: ['ip_hash'], name: 'idx_analytics_ip')]
#[ORM\Index(columns: ['created_at'], name: 'idx_analytics_created')]
class AnalyticsUniqId
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 36, unique: true)]
    private string $uid;

    #[ORM\Column(length: 64)]
    private string $hash;

    #[ORM\ManyToOne(targetEntity: User::class)]
    #[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')]
    private ?User $user = null;

    #[ORM\Column(length: 64)]
    private string $ipHash;

    #[ORM\Column(length: 512)]
    private string $userAgent;

    #[ORM\Column(nullable: true)]
    private ?int $screenWidth = null;

    #[ORM\Column(nullable: true)]
    private ?int $screenHeight = null;

    #[ORM\Column(length: 10, nullable: true)]
    private ?string $language = null;

    #[ORM\Column(length: 10)]
    private string $deviceType = 'desktop';

    #[ORM\Column(length: 30, nullable: true)]
    private ?string $os = null;

    #[ORM\Column(length: 30, nullable: true)]
    private ?string $browser = null;

    #[ORM\Column]
    private \DateTimeImmutable $createdAt;

    /** @var Collection<int, AnalyticsEvent> */
    #[ORM\OneToMany(targetEntity: AnalyticsEvent::class, mappedBy: 'visitor', cascade: ['remove'])]
    private Collection $events;

    public function __construct()
    {
        $this->createdAt = new \DateTimeImmutable();
        $this->events = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getUid(): string
    {
        return $this->uid;
    }

    public function setUid(string $uid): static
    {
        $this->uid = $uid;

        return $this;
    }

    public function getHash(): string
    {
        return $this->hash;
    }

    public function setHash(string $hash): static
    {
        $this->hash = $hash;

        return $this;
    }

    public function getUser(): ?User
    {
        return $this->user;
    }

    public function setUser(?User $user): static
    {
        $this->user = $user;

        return $this;
    }

    public function getIpHash(): string
    {
        return $this->ipHash;
    }

    public function setIpHash(string $ipHash): static
    {
        $this->ipHash = $ipHash;

        return $this;
    }

    public function getUserAgent(): string
    {
        return $this->userAgent;
    }

    public function setUserAgent(string $userAgent): static
    {
        $this->userAgent = $userAgent;

        return $this;
    }

    public function getScreenWidth(): ?int
    {
        return $this->screenWidth;
    }

    public function setScreenWidth(?int $screenWidth): static
    {
        $this->screenWidth = $screenWidth;

        return $this;
    }

    public function getScreenHeight(): ?int
    {
        return $this->screenHeight;
    }

    public function setScreenHeight(?int $screenHeight): static
    {
        $this->screenHeight = $screenHeight;

        return $this;
    }

    public function getLanguage(): ?string
    {
        return $this->language;
    }

    public function setLanguage(?string $language): static
    {
        $this->language = $language;

        return $this;
    }

    public function getDeviceType(): string
    {
        return $this->deviceType;
    }

    public function setDeviceType(string $deviceType): static
    {
        $this->deviceType = $deviceType;

        return $this;
    }

    public function getOs(): ?string
    {
        return $this->os;
    }

    public function setOs(?string $os): static
    {
        $this->os = $os;

        return $this;
    }

    public function getBrowser(): ?string
    {
        return $this->browser;
    }

    public function setBrowser(?string $browser): static
    {
        $this->browser = $browser;

        return $this;
    }

    public function getCreatedAt(): \DateTimeImmutable
    {
        return $this->createdAt;
    }

    /**
     * @return Collection<int, AnalyticsEvent>
     */
    public function getEvents(): Collection
    {
        return $this->events;
    }

    public static function parseDeviceType(string $ua): string
    {
        $ua = strtolower($ua);
        if (preg_match('/tablet|ipad|playbook|silk/i', $ua)) {
            return 'tablet';
        }
        if (preg_match('/mobile|iphone|ipod|android.*mobile|windows phone|blackberry/i', $ua)) {
            return 'mobile';
        }

        return 'desktop';
    }

    public static function parseOs(string $ua): ?string
    {
        $patterns = [
            '/windows nt/i' => 'Windows',
            '/macintosh|mac os x/i' => 'macOS',
            '/iphone|ipad|ipod/i' => 'iOS',
            '/android/i' => 'Android',
            '/linux/i' => 'Linux',
            '/cros/i' => 'ChromeOS',
        ];

        foreach ($patterns as $pattern => $name) {
            if (preg_match($pattern, $ua)) {
                return $name;
            }
        }

        return null;
    }

    public static function parseBrowser(string $ua): ?string
    {
        $patterns = [
            '/edg(?:e|a)?\/[\d.]+/i' => 'Edge',
            '/opr\/[\d.]+|opera/i' => 'Opera',
            '/chrome\/[\d.]+(?!.*edg)/i' => 'Chrome',
            '/safari\/[\d.]+(?!.*chrome)/i' => 'Safari',
            '/firefox\/[\d.]+/i' => 'Firefox',
        ];

        foreach ($patterns as $pattern => $name) {
            if (preg_match($pattern, $ua)) {
                return $name;
            }
        }

        return null;
    }
}
