<?php

namespace MintyPHP\Tests\Module\Helpdesk\Service;

use MintyPHP\Module\Helpdesk\Repository\DomainSecurityLevelRepository;
use MintyPHP\Module\Helpdesk\Service\DomainSecurityLevelService;
use PHPUnit\Framework\TestCase;

class DomainSecurityLevelServiceTest extends TestCase
{
    private const TENANT_ID = 1;

    public function testGetLevelReturnsDefaultForUnknownDomain(): void
    {
        $repository = $this->createMock(DomainSecurityLevelRepository::class);
        $repository->method('findByTenantAndDomainNo')->willReturn(null);

        $service = new DomainSecurityLevelService($repository);

        $this->assertSame('normal', $service->getLevel(self::TENANT_ID, 'DNS00001'));
    }

    public function testGetLevelReturnsStoredValue(): void
    {
        $repository = $this->createMock(DomainSecurityLevelRepository::class);
        $repository->method('findByTenantAndDomainNo')->willReturn([
            'security_level' => 'kritisch',
        ]);

        $service = new DomainSecurityLevelService($repository);

        $this->assertSame('kritisch', $service->getLevel(self::TENANT_ID, 'DNS00001'));
    }

    public function testGetLevelDefaultsOnInvalidStoredValue(): void
    {
        $repository = $this->createMock(DomainSecurityLevelRepository::class);
        $repository->method('findByTenantAndDomainNo')->willReturn([
            'security_level' => 'ungueltig',
        ]);

        $service = new DomainSecurityLevelService($repository);

        $this->assertSame('normal', $service->getLevel(self::TENANT_ID, 'DNS00001'));
    }

    public function testGetLevelReturnsDefaultForEmptyDomainNo(): void
    {
        $repository = $this->createMock(DomainSecurityLevelRepository::class);
        $repository->expects($this->never())->method('findByTenantAndDomainNo');

        $service = new DomainSecurityLevelService($repository);

        $this->assertSame('normal', $service->getLevel(self::TENANT_ID, ''));
    }

    public function testSetLevelRejectsInvalidLevel(): void
    {
        $repository = $this->createMock(DomainSecurityLevelRepository::class);
        $repository->expects($this->never())->method('upsert');

        $service = new DomainSecurityLevelService($repository);

        $this->assertFalse($service->setLevel(self::TENANT_ID, 'DNS00001', 'ungueltig', 1));
    }

    public function testSetLevelRejectsEmptyDomainNo(): void
    {
        $repository = $this->createMock(DomainSecurityLevelRepository::class);
        $repository->expects($this->never())->method('upsert');

        $service = new DomainSecurityLevelService($repository);

        $this->assertFalse($service->setLevel(self::TENANT_ID, '', 'hoch', 1));
    }

    public function testSetLevelCallsUpsertWithCorrectParams(): void
    {
        $repository = $this->createMock(DomainSecurityLevelRepository::class);
        $repository->expects($this->once())
            ->method('upsert')
            ->with(self::TENANT_ID, 'DNS00001', 'hoch', 42)
            ->willReturn(true);

        $service = new DomainSecurityLevelService($repository);

        $this->assertTrue($service->setLevel(self::TENANT_ID, 'DNS00001', 'hoch', 42));
    }

    public function testSetLevelAllowsAllValidLevels(): void
    {
        $repository = $this->createMock(DomainSecurityLevelRepository::class);
        $repository->method('upsert')->willReturn(true);

        $service = new DomainSecurityLevelService($repository);

        foreach (['niedrig', 'normal', 'hoch', 'kritisch'] as $level) {
            $this->assertTrue($service->setLevel(self::TENANT_ID, 'DNS00001', $level, 1));
        }
    }

    public function testGetAllLevelsForDomainsReturnsEmptyForEmptyInput(): void
    {
        $repository = $this->createMock(DomainSecurityLevelRepository::class);
        $repository->expects($this->never())->method('listLevelsByDomainNos');

        $service = new DomainSecurityLevelService($repository);

        $this->assertSame([], $service->getAllLevelsForDomains(self::TENANT_ID, []));
    }

    public function testGetAllLevelsForDomainsDelegatesToRepository(): void
    {
        $expected = ['DNS00001' => 'hoch', 'DNS00002' => 'niedrig'];
        $repository = $this->createMock(DomainSecurityLevelRepository::class);
        $repository->method('listLevelsByDomainNos')->willReturn($expected);

        $service = new DomainSecurityLevelService($repository);
        $result = $service->getAllLevelsForDomains(self::TENANT_ID, ['DNS00001', 'DNS00002']);

        $this->assertSame($expected, $result);
    }

    public function testGetBadgeVariantMapping(): void
    {
        $this->assertSame('info', DomainSecurityLevelService::getBadgeVariant('niedrig'));
        $this->assertSame('neutral', DomainSecurityLevelService::getBadgeVariant('normal'));
        $this->assertSame('warning', DomainSecurityLevelService::getBadgeVariant('hoch'));
        $this->assertSame('error', DomainSecurityLevelService::getBadgeVariant('kritisch'));
        $this->assertSame('neutral', DomainSecurityLevelService::getBadgeVariant('unknown'));
    }

    public function testGetAllowedLevelsReturnsFourLevels(): void
    {
        $levels = DomainSecurityLevelService::getAllowedLevels();

        $this->assertCount(4, $levels);
        $this->assertSame(['niedrig', 'normal', 'hoch', 'kritisch'], $levels);
    }
}
