<?php

declare(strict_types=1);

namespace App\Domain\SmartLink\Entities;

use App\Domain\SmartLink\Enums\DeviceType;
use App\Domain\SmartLink\ValueObjects\ClickId;
use App\Domain\SmartLink\ValueObjects\SmartLinkId;
use App\Framework\Core\ValueObjects\CountryCode;
use App\Framework\Core\ValueObjects\Timestamp;
use App\Framework\DateTime\Clock;
use App\Framework\Http\IpAddress;
use App\Framework\UserAgent\UserAgent;

final readonly class ClickEvent
{
    public function __construct(
        public ClickId $id,
        public SmartLinkId $linkId,
        public string $ipHash,
        public CountryCode $countryCode,
        public DeviceType $deviceType,
        public string $userAgentString,
        public ?string $referer,
        public ?string $destinationService,
        public bool $converted,
        public Timestamp $clickedAt
    ) {
    }

    public static function create(
        Clock $clock,
        SmartLinkId $linkId,
        IpAddress $ip,
        CountryCode $countryCode,
        UserAgent $userAgent,
        ?string $referer = null,
        ?string $destinationService = null
    ): self {
        return new self(
            id: ClickId::generate($clock),
            linkId: $linkId,
            ipHash: self::hashIp($ip),
            countryCode: $countryCode,
            deviceType: DeviceType::fromUserAgent($userAgent->toString()),
            userAgentString: $userAgent->toString(),
            referer: $referer,
            destinationService: $destinationService,
            converted: false,
            clickedAt: Timestamp::now()
        );
    }

    private static function hashIp(IpAddress $ip): string
    {
        // Privacy-compliant: Hash IP with daily rotating salt
        $salt = date('Y-m-d');

        return hash('sha256', $ip->value . $salt);
    }

    public function withConversion(): self
    {
        return new self(
            id: $this->id,
            linkId: $this->linkId,
            ipHash: $this->ipHash,
            countryCode: $this->countryCode,
            deviceType: $this->deviceType,
            userAgentString: $this->userAgentString,
            referer: $this->referer,
            destinationService: $this->destinationService,
            converted: true,
            clickedAt: $this->clickedAt
        );
    }

    public function isUnique(array $recentClicks): bool
    {
        foreach ($recentClicks as $click) {
            if ($click->ipHash === $this->ipHash &&
                $click->clickedAt->isWithinMinutes($this->clickedAt, 60)) {
                return false;
            }
        }

        return true;
    }

    public function toArray(): array
    {
        return [
            'id' => $this->id->toString(),
            'link_id' => $this->linkId->toString(),
            'ip_hash' => $this->ipHash,
            'country_code' => (string) $this->countryCode,
            'country_name' => $this->countryCode->getCountryName(),
            'device_type' => $this->deviceType->value,
            'user_agent' => $this->userAgentString,
            'referer' => $this->referer,
            'destination_service' => $this->destinationService,
            'converted' => $this->converted,
            'clicked_at' => $this->clickedAt->format('Y-m-d H:i:s'),
        ];
    }
}
