<?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\CmsBundle\Tests\View;

use Ferienpass\CmsBundle\View\ApplicationList;
use Ferienpass\CoreBundle\Entity\Attendance;
use Ferienpass\CoreBundle\Entity\Offer\Base;
use Ferienpass\CoreBundle\Entity\Participant\BaseParticipant;
use PHPUnit\Framework\TestCase;

final class ApplicationListTest extends TestCase
{
    public function testFilterAbgemeldetReturnsWithdrawnAttendances(): void
    {
        $withdrawn = $this->makeAttendance('withdrawn');
        $confirmed = $this->makeAttendance('confirmed');

        $list = ApplicationList::fromDatabaseResult([$withdrawn, $confirmed]);
        $result = $list->getFilteredAttendances('abgemeldet');

        self::assertCount(1, $result);
        self::assertSame('withdrawn', $result[0]->getStatus());
    }

    public function testFilterAbgemeldetReturnsUnfulfilledAndRejected(): void
    {
        $unfulfilled = $this->makeAttendance('unfulfilled');
        $rejected = $this->makeAttendance('rejected');
        $waitlisted = $this->makeAttendance('waitlisted');

        $list = ApplicationList::fromDatabaseResult([$unfulfilled, $rejected, $waitlisted]);
        $result = $list->getFilteredAttendances('abgemeldet');

        self::assertCount(2, $result);
    }

    public function testFilterUnbezahlteReturnsPayableAndUnpaidOnly(): void
    {
        $payableUnpaid = $this->makeAttendance('confirmed', payable: true, paid: false);
        $notPayable = $this->makeAttendance('confirmed', payable: false);

        $list = ApplicationList::fromDatabaseResult([$payableUnpaid, $notPayable]);
        $result = $list->getFilteredAttendances('unbezahlte');

        self::assertCount(1, $result);
    }

    public function testDefaultFilterExcludesWithdrawnStatus(): void
    {
        $withdrawn = $this->makeAttendance('withdrawn');
        $confirmed = $this->makeAttendance('confirmed');

        $list = ApplicationList::fromDatabaseResult([$withdrawn, $confirmed]);
        $result = $list->getFilteredAttendances('');

        // Withdrawn is excluded
        foreach ($result as $attendance) {
            self::assertNotSame('withdrawn', $attendance->getStatus());
        }
    }

    private function makeAttendance(string $status, ?bool $payable = false, ?bool $paid = false, ?\DateTimeInterface $dateBegin = null): Attendance
    {
        $offer = new Base();

        if (null !== $dateBegin) {
            // set date via reflection since there's no public setter for dates
            $offerDate = new \Ferienpass\CoreBundle\Entity\OfferDate($offer);
            $offerDate->setBegin($dateBegin);
        }

        $attendance = new Attendance($offer, new BaseParticipant());
        $attendance->setStatus($status);

        if ($payable) {
            $attendance->setPayable(true);
        }

        return $attendance;
    }
}
