<?php

namespace App\Service;

use Symfony\Component\DependencyInjection\Attribute\Autowire;

class UnsubscribeManager
{
    private string $storagePath;
    private string $secret;

    public function __construct(
        #[Autowire('%kernel.project_dir%')] string $projectDir,
        #[Autowire('%kernel.secret%')] string $appSecret,
    ) {
        $this->storagePath = $projectDir.'/var/unsubscribed.json';
        $this->secret = $appSecret;
    }

    public function generateToken(string $email): string
    {
        return hash_hmac('sha256', strtolower(trim($email)), $this->secret);
    }

    public function isValidToken(string $email, string $token): bool
    {
        return hash_equals($this->generateToken($email), $token);
    }

    public function isUnsubscribed(string $email): bool
    {
        $hash = $this->generateToken($email);

        return \in_array($hash, $this->loadHashes(), true);
    }

    public function unsubscribe(string $email): void
    {
        $hash = $this->generateToken($email);
        $hashes = $this->loadHashes();

        if (!\in_array($hash, $hashes, true)) {
            $hashes[] = $hash;
            $this->saveHashes($hashes);
        }
    }

    /**
     * @return list<string>
     */
    private function loadHashes(): array
    {
        if (!file_exists($this->storagePath)) {
            return [];
        }

        $data = json_decode(file_get_contents($this->storagePath), true);

        return \is_array($data) ? $data : [];
    }

    /**
     * @param list<string> $hashes
     */
    private function saveHashes(array $hashes): void
    {
        $dir = \dirname($this->storagePath);
        if (!is_dir($dir)) {
            mkdir($dir, 0o755, true);
        }

        file_put_contents($this->storagePath, json_encode($hashes), \LOCK_EX);
    }
}
