<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\CoreBundle\Tests\Entity;

use Ferienpass\CoreBundle\Entity\ConversationItem;
use Ferienpass\CoreBundle\Entity\DbafsLogo;
use Ferienpass\CoreBundle\Entity\Host;
use Ferienpass\CoreBundle\Entity\HostMemberAssociation;
use Ferienpass\CoreBundle\Entity\Offer\Base;
use Ferienpass\CoreBundle\Entity\PostalAddress;
use Ferienpass\CoreBundle\Entity\User;
use PHPUnit\Framework\TestCase;
use Symfony\Component\String\Slugger\AsciiSlugger;

final class HostTest extends TestCase
{
    public function testGetIdNullByDefault(): void
    {
        self::assertNull(new Host()->getId());
    }

    public function testGetUuidIsSetOnConstruct(): void
    {
        $host = new Host();
        self::assertNotNull($host->getUuid());
    }

    public function testGetCreatedAtIsSetOnConstruct(): void
    {
        $host = new Host();
        self::assertInstanceOf(\DateTimeInterface::class, $host->getCreatedAt());
    }

    public function testGetNameNullByDefault(): void
    {
        self::assertNull(new Host()->getName());
    }

    public function testSetName(): void
    {
        $host = new Host();
        $host->setName('Test Host');
        self::assertSame('Test Host', $host->getName());
    }

    public function testSetNameNull(): void
    {
        $host = new Host();
        $host->setName('Something');
        $host->setName(null);
        self::assertNull($host->getName());
    }

    public function testGetAliasNullByDefault(): void
    {
        self::assertNull(new Host()->getAlias());
    }

    public function testSetAlias(): void
    {
        $host = new Host();
        $host->setAlias('test-host');
        self::assertSame('test-host', $host->getAlias());
    }

    public function testGetPhoneNullByDefault(): void
    {
        self::assertNull(new Host()->getPhone());
    }

    public function testSetPhone(): void
    {
        $host = new Host();
        $host->setPhone('+49123456789');
        self::assertSame('+49123456789', $host->getPhone());
    }

    public function testGetFaxNullByDefault(): void
    {
        self::assertNull(new Host()->getFax());
    }

    public function testSetFax(): void
    {
        $host = new Host();
        $host->setFax('+49123456789');
        self::assertSame('+49123456789', $host->getFax());
    }

    public function testGetMobileNullByDefault(): void
    {
        self::assertNull(new Host()->getMobile());
    }

    public function testSetMobile(): void
    {
        $host = new Host();
        $host->setMobile('+491234567890');
        self::assertSame('+491234567890', $host->getMobile());
    }

    public function testGetEmailNullByDefault(): void
    {
        self::assertNull(new Host()->getEmail());
    }

    public function testSetEmail(): void
    {
        $host = new Host();
        $host->setEmail('test@example.com');
        self::assertSame('test@example.com', $host->getEmail());
    }

    public function testGetWebsiteNullByDefault(): void
    {
        self::assertNull(new Host()->getWebsite());
    }

    public function testSetWebsite(): void
    {
        $host = new Host();
        $host->setWebsite('https://example.com');
        self::assertSame('https://example.com', $host->getWebsite());
    }

    public function testGetTextNullByDefault(): void
    {
        self::assertNull(new Host()->getText());
    }

    public function testSetText(): void
    {
        $host = new Host();
        $host->setText('Some description');
        self::assertSame('Some description', $host->getText());
    }

    public function testGetActiveNullByDefault(): void
    {
        self::assertNull(new Host()->getActive());
    }

    public function testSetActive(): void
    {
        $host = new Host();
        $host->setActive('1');
        self::assertSame('1', $host->getActive());
    }

    public function testGetLogoNullByDefault(): void
    {
        self::assertNull(new Host()->getLogo());
    }

    public function testSetLogo(): void
    {
        $host = new Host();
        $logo = new DbafsLogo();
        $host->setLogo($logo);
        self::assertSame($logo, $host->getLogo());
    }

    public function testSetLogoNull(): void
    {
        $host = new Host();
        $logo = new DbafsLogo();
        $host->setLogo($logo);
        $host->setLogo(null);
        self::assertNull($host->getLogo());
    }

    public function testGetLogoOldNullByDefault(): void
    {
        self::assertNull(new Host()->getLogoOld());
    }

    public function testSetLogoOld(): void
    {
        $host = new Host();
        $host->setLogoOld('abc123');
        self::assertSame('abc123', $host->getLogoOld());
    }

    public function testGetPostalAddressesInitiallyEmpty(): void
    {
        self::assertCount(0, new Host()->getPostalAddresses());
    }

    public function testAddPostalAddress(): void
    {
        $host = new Host();
        $address = new PostalAddress();
        $host->addPostalAddress($address);
        self::assertCount(1, $host->getPostalAddresses());
    }

    public function testRemovePostalAddress(): void
    {
        $host = new Host();
        $address = new PostalAddress();
        $host->addPostalAddress($address);
        $host->removePostalAddress($address);
        self::assertCount(0, $host->getPostalAddresses());
    }

    public function testGetOffersInitiallyEmpty(): void
    {
        self::assertCount(0, new Host()->getOffers());
    }

    public function testAddOffer(): void
    {
        $host = new Host();
        $offer = new Base();
        $host->addOffer($offer);
        self::assertCount(1, $host->getOffers());
    }

    public function testGetMemberAssociationsInitiallyEmpty(): void
    {
        self::assertCount(0, new Host()->getMemberAssociations());
    }

    public function testHasMemberReturnsFalseWhenNoMembers(): void
    {
        $host = new Host();
        $user = new User();
        self::assertFalse($host->hasMember($user));
    }

    public function testAddMemberMakesHasMemberTrue(): void
    {
        $host = new Host();
        $user = new User();
        $host->addMember($user);
        self::assertTrue($host->hasMember($user));
        self::assertCount(1, $host->getMemberAssociations());
    }

    public function testAddMemberIsIdempotent(): void
    {
        $host = new Host();
        $user = new User();
        $host->addMember($user);
        $host->addMember($user);
        self::assertCount(1, $host->getMemberAssociations());
    }

    public function testAddMemberAssociation(): void
    {
        $host = new Host();
        $user = new User();
        $assoc = new HostMemberAssociation($user, $host);
        $host->addMemberAssociation($assoc);
        self::assertCount(1, $host->getMemberAssociations());
    }

    public function testRemoveMemberAssociation(): void
    {
        $host = new Host();
        $user = new User();
        $assoc = new HostMemberAssociation($user, $host);
        $host->addMemberAssociation($assoc);
        $host->removeMemberAssociation($assoc);
        self::assertCount(0, $host->getMemberAssociations());
    }

    public function testGetUsersReturnsEmptyArrayInitially(): void
    {
        self::assertSame([], new Host()->getUsers());
    }

    public function testGetUsersReturnsAddedUsers(): void
    {
        $host = new Host();
        $user = new User();
        $host->addMember($user);
        $users = $host->getUsers();
        self::assertCount(1, $users);
        self::assertSame($user, $users[0]);
    }

    public function testGetActivityInitiallyEmpty(): void
    {
        self::assertCount(0, new Host()->getActivity());
    }

    public function testGetCommentsInitiallyEmpty(): void
    {
        self::assertCount(0, new Host()->getConversation());
    }

    public function testGetConversationReturnsConversationItems(): void
    {
        $host = new Host();
        $user = new User();

        $host->getConversation()->add(new ConversationItem($host, $user, 'Some comment'));

        self::assertCount(1, $host->getConversation());
    }

    public function testGenerateAliasSlugifiesName(): void
    {
        $host = new Host();
        $host->setName('Mein schöner Host');
        $host->generateAlias(new AsciiSlugger());
        self::assertSame('mein-schoner-host', $host->getAlias());
    }

    public function testGenerateAliasWithNullNameUsesUniqid(): void
    {
        $host = new Host();
        $host->generateAlias(new AsciiSlugger());
        self::assertNotNull($host->getAlias());
    }
}
