<?php

namespace App\Tests\Service;

use App\Service\UnsubscribeManager;
use PHPUnit\Framework\TestCase;

class UnsubscribeManagerTest extends TestCase
{
    private string $tempDir;
    private UnsubscribeManager $manager;

    protected function setUp(): void
    {
        $this->tempDir = sys_get_temp_dir().'/unsubscribe_test_'.uniqid();
        mkdir($this->tempDir.'/var', 0755, true);
        $this->manager = new UnsubscribeManager($this->tempDir, 'test-secret');
    }

    protected function tearDown(): void
    {
        $file = $this->tempDir.'/var/unsubscribed.json';
        if (file_exists($file)) {
            unlink($file);
        }
        if (is_dir($this->tempDir.'/var')) {
            rmdir($this->tempDir.'/var');
        }
        if (is_dir($this->tempDir)) {
            rmdir($this->tempDir);
        }
    }

    public function testGenerateTokenIsDeterministic(): void
    {
        $token1 = $this->manager->generateToken('user@example.com');
        $token2 = $this->manager->generateToken('user@example.com');

        self::assertSame($token1, $token2);
    }

    public function testGenerateTokenNormalizesEmail(): void
    {
        $token1 = $this->manager->generateToken('User@Example.com');
        $token2 = $this->manager->generateToken('  user@example.com  ');

        self::assertSame($token1, $token2);
    }

    public function testIsValidTokenReturnsTrueForMatchingToken(): void
    {
        $token = $this->manager->generateToken('user@example.com');

        self::assertTrue($this->manager->isValidToken('user@example.com', $token));
    }

    public function testIsValidTokenReturnsFalseForWrongToken(): void
    {
        self::assertFalse($this->manager->isValidToken('user@example.com', 'wrong-token'));
    }

    public function testIsUnsubscribedReturnsFalseByDefault(): void
    {
        self::assertFalse($this->manager->isUnsubscribed('user@example.com'));
    }

    public function testUnsubscribeAndIsUnsubscribed(): void
    {
        $this->manager->unsubscribe('user@example.com');

        self::assertTrue($this->manager->isUnsubscribed('user@example.com'));
    }

    public function testUnsubscribeIsIdempotent(): void
    {
        $this->manager->unsubscribe('user@example.com');
        $this->manager->unsubscribe('user@example.com');

        $data = json_decode(file_get_contents($this->tempDir.'/var/unsubscribed.json'), true);
        self::assertCount(1, $data);
    }

    public function testUnsubscribeCreatesDirWhenMissing(): void
    {
        $dir = sys_get_temp_dir().'/unsubscribe_nodir_'.uniqid();
        $manager = new UnsubscribeManager($dir, 'secret');

        $manager->unsubscribe('user@example.com');

        self::assertTrue($manager->isUnsubscribed('user@example.com'));

        @unlink($dir.'/var/unsubscribed.json');
        @rmdir($dir.'/var');
        @rmdir($dir);
    }
}
