<?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\Dto;

use Ferienpass\CoreBundle\Dto\ParticipantDuplicateDto;
use PHPUnit\Framework\TestCase;

final class ParticipantDuplicateDtoTest extends TestCase
{
    public function testGetIdCombinesParticipantIds(): void
    {
        $dto = $this->makeDto(p1Id: 10, p2Id: 20);

        self::assertSame('10-20', $dto->getId());
    }

    public function testGetIdWithStringIds(): void
    {
        $dto = $this->makeDto(p1Id: '5', p2Id: '7');

        self::assertSame('5-7', $dto->getId());
    }

    public function testHasDobMatchReturnsTrueWhenSameDate(): void
    {
        $dob = new \DateTimeImmutable('2010-05-15');
        $dto = $this->makeDto(p1Dob: $dob, p2Dob: new \DateTimeImmutable('2010-05-15'));

        self::assertTrue($dto->hasDobMatch());
    }

    public function testHasDobMatchReturnsFalseWhenDifferentDate(): void
    {
        $dto = $this->makeDto(
            p1Dob: new \DateTimeImmutable('2010-05-15'),
            p2Dob: new \DateTimeImmutable('2010-06-20'),
        );

        self::assertFalse($dto->hasDobMatch());
    }

    public function testHasDobMatchReturnsTrueWhenBothNull(): void
    {
        $dto = $this->makeDto(p1Dob: null, p2Dob: null);

        self::assertTrue($dto->hasDobMatch());
    }

    public function testHasDobMatchReturnsFalseWhenOnlyOneIsNull(): void
    {
        $dto = $this->makeDto(p1Dob: new \DateTimeImmutable('2010-05-15'), p2Dob: null);

        self::assertFalse($dto->hasDobMatch());
    }

    public function testHasUserMatchReturnsTrueWhenSameUserId(): void
    {
        $dto = $this->makeDto(p1UserId: 99, p2UserId: 99);

        self::assertTrue($dto->hasUserMatch());
    }

    public function testHasUserMatchReturnsFalseWhenDifferentUserId(): void
    {
        $dto = $this->makeDto(p1UserId: 1, p2UserId: 2);

        self::assertFalse($dto->hasUserMatch());
    }

    public function testHasUserMatchReturnsFalseWhenBothUserIdsNull(): void
    {
        $dto = $this->makeDto(p1UserId: null, p2UserId: null);

        self::assertFalse($dto->hasUserMatch());
    }

    public function testHasUserMatchReturnsFalseWhenOnlyOneUserIdNull(): void
    {
        $dto = $this->makeDto(p1UserId: null, p2UserId: 5);

        self::assertFalse($dto->hasUserMatch());
    }

    public function testParticipantGetNameIncludesIdSuffix(): void
    {
        $dto = $this->makeDto(p1Id: 42, p1Firstname: 'John', p1Lastname: 'Doe');

        self::assertSame('John Doe #42', $dto->participant1->getName());
    }

    public function testParticipantGetNameWithNullFirstname(): void
    {
        $dto = $this->makeDto(p1Id: 5, p1Firstname: null, p1Lastname: 'Doe');

        self::assertSame('Doe #5', $dto->participant1->getName());
    }

    public function testParticipantGetUserNameReturnsNullWhenNoUserId(): void
    {
        $dto = $this->makeDto(p1UserId: null);

        self::assertNull($dto->participant1->getUserName());
    }

    public function testParticipantGetUserNameReturnsFormattedNameWithId(): void
    {
        $dto = $this->makeDto(p1UserId: 7, p1UserFirstname: 'Parent', p1UserLastname: 'User');

        self::assertSame('Parent User #7', $dto->participant1->getUserName());
    }

    public function testParticipantGetIdReturnsInt(): void
    {
        $dto = $this->makeDto(p1Id: '12');

        self::assertSame(12, $dto->participant1->getId());
    }

    public function testStatusGroupIsSet(): void
    {
        $dto = $this->makeDto(statusGroup: 'pending');

        self::assertSame('pending', $dto->statusGroup);
    }

    public function testParticipant2GetNameIncludesIdSuffix(): void
    {
        $dto = $this->makeDto(p2Id: 99, p2Firstname: 'Jane', p2Lastname: 'Doe');

        self::assertSame('Jane Doe #99', $dto->participant2->getName());
    }

    public function testParticipant2GetUserNameReturnsNullWhenNoUserId(): void
    {
        $dto = $this->makeDto(p2UserId: null);

        self::assertNull($dto->participant2->getUserName());
    }

    public function testParticipant2GetUserNameReturnsFormattedNameWithId(): void
    {
        $dto = $this->makeDto(p2UserId: 8, p2UserFirstname: 'Parent', p2UserLastname: 'Two');

        self::assertSame('Parent Two #8', $dto->participant2->getUserName());
    }

    public function testParticipant2GetIdReturnsInt(): void
    {
        $dto = $this->makeDto(p2Id: '55');

        self::assertSame(55, $dto->participant2->getId());
    }

    private function makeDto(
        $p1Id = 1,
        $p2Id = 2,
        string $statusGroup = 'active',
        ?string $p1Firstname = 'Anna',
        ?string $p1Lastname = 'Smith',
        ?string $p1Email = null,
        $p1Uuid = null,
        $p1Dob = null,
        ?string $p2Firstname = 'Anna',
        ?string $p2Lastname = 'Jones',
        ?string $p2Email = null,
        $p2Uuid = null,
        $p2Dob = null,
        ?string $p1UserFirstname = null,
        ?string $p1UserLastname = null,
        $p1UserId = null,
        $p1AttendanceCount = 0,
        $p1UserAttendanceCount = 0,
        ?string $p2UserFirstname = null,
        ?string $p2UserLastname = null,
        $p2UserId = null,
        $p2AttendanceCount = 0,
        $p2UserAttendanceCount = 0,
    ): ParticipantDuplicateDto {
        return new ParticipantDuplicateDto(
            $p1Id,
            $p2Id,
            $statusGroup,
            $p1Firstname,
            $p1Lastname,
            $p1Email,
            $p1Uuid,
            $p1Dob,
            $p2Firstname,
            $p2Lastname,
            $p2Email,
            $p2Uuid,
            $p2Dob,
            $p1UserFirstname,
            $p1UserLastname,
            $p1UserId,
            $p1AttendanceCount,
            $p1UserAttendanceCount,
            $p2UserFirstname,
            $p2UserLastname,
            $p2UserId,
            $p2AttendanceCount,
            $p2UserAttendanceCount,
        );
    }
}
