<?php

namespace App\Service;

use Symfony\Component\DependencyInjection\Attribute\Autowire;

class AnalyticsCryptoService
{
    private string $key;

    public function __construct(
        #[Autowire(env: 'SECRET_ANALYTICS')] private string $analyticsSecret,
    ) {
        $this->key = substr(hash('sha256', $this->analyticsSecret, true), 0, 32);
    }

    /** @param array<string, mixed> $data */
    public function encrypt(array $data): string
    {
        $json = json_encode($data, \JSON_THROW_ON_ERROR);
        $iv = random_bytes(12);
        $encrypted = openssl_encrypt($json, 'aes-256-gcm', $this->key, \OPENSSL_RAW_DATA, $iv, $tag, '', 16);

        // Format compatible with Web Crypto API: iv + ciphertext + tag
        return base64_encode($iv.$encrypted.$tag);
    }

    /** @return array<string, mixed>|null */
    public function decrypt(string $payload): ?array
    {
        $raw = base64_decode($payload, true);
        if (false === $raw || \strlen($raw) < 28) {
            return null;
        }

        // Try JS format first: iv (12) + ciphertext_with_tag (tag is last 16 bytes)
        $iv = substr($raw, 0, 12);
        $ciphertextWithTag = substr($raw, 12);

        if (\strlen($ciphertextWithTag) >= 16) {
            $tag = substr($ciphertextWithTag, -16);
            $encrypted = substr($ciphertextWithTag, 0, -16);

            $json = openssl_decrypt($encrypted, 'aes-256-gcm', $this->key, \OPENSSL_RAW_DATA, $iv, $tag);
            if (false !== $json) {
                return json_decode($json, true);
            }
        }

        // Fallback: PHP format iv (12) + tag (16) + ciphertext
        $tag = substr($raw, 12, 16);
        $encrypted = substr($raw, 28);

        $json = openssl_decrypt($encrypted, 'aes-256-gcm', $this->key, \OPENSSL_RAW_DATA, $iv, $tag);
        if (false === $json) {
            return null;
        }

        return json_decode($json, true);
    }

    public function generateVisitorHash(string $uid): string
    {
        return hash_hmac('sha256', $uid, $this->key);
    }

    public function verifyVisitorHash(string $uid, string $hash): bool
    {
        return hash_equals($this->generateVisitorHash($uid), $hash);
    }

    public function getKeyForJs(): string
    {
        return base64_encode($this->key);
    }
}
