<?php

namespace Velis\Test\MaintenanceAlert;

use DateTimeImmutable;
use DateTimeZone;
use PHPUnit\Framework\TestCase;
use Velis\MaintenanceAlert\MaintenanceAlertFormatterInterface;
use Velis\MaintenanceAlert\MaintenanceAlertGenerator;

/**
 * @author Szymon Janaczek <szymon.janaczek@velistech.com>
 */
final class MaintenanceAlertGeneratorTest extends TestCase
{
    private MaintenanceAlertFormatterInterface $mockFormatter;

    protected function setUp(): void
    {
        $this->mockFormatter = $this->createMock(MaintenanceAlertFormatterInterface::class);
    }

    /**
     * @throws \Exception
     */
    public function testGetAlertReturnsNullWhenMaintenanceIsOver()
    {
        $generator = new MaintenanceAlertGenerator(
            alertFormatter: $this->mockFormatter,
            applicationDefaultTimeZone: 'Europe/Warsaw',
        );

        $actualResult = $generator->getAlert(
            maintenanceDateStart: '1492-07-29 10:00:00',
            maintenanceDateStop: '1492-07-29 14:00:00',
            maintenanceTimeZone: 'UTC',
            multipleTimeZoneSupport: false,
        );

        $this->assertNull($actualResult);
    }

    /**
     * @throws \Exception
     */
    public function testGetAlertEnabledMultipleTimezonesUserTimezone()
    {
        $startDate = '2100-07-30 10:00:00';
        $stopDate = '2100-07-30 14:00:00';
        $maintenanceTimezone = 'Europe/London';
        $userTimezone = 'Asia/Tokyo';

        $this->mockFormatter->expects($this->once())
            ->method('format')
            ->with(
                $this->callback(function ($arg) use ($userTimezone) {
                    return $arg instanceof DateTimeImmutable
                        && $arg->format('Y-m-d H:i:s') === '2100-07-30 18:00:00'
                        && $arg->getTimezone()->getName() === $userTimezone;
                }),
                $this->callback(function ($arg) use ($userTimezone) {
                    return $arg instanceof DateTimeImmutable
                        && $arg->format('Y-m-d H:i:s') === '2100-07-30 22:00:00'
                        && $arg->getTimezone()->getName() === $userTimezone;
                })
            )
            ->willReturn('Formatted Alert');

        $generator = new MaintenanceAlertGenerator(
            alertFormatter: $this->mockFormatter,
            userTimeZone: $userTimezone,
        );

        $actualResult = $generator->getAlert(
            maintenanceDateStart: $startDate,
            maintenanceDateStop: $stopDate,
            maintenanceTimeZone: $maintenanceTimezone,
            multipleTimeZoneSupport: true,
        );

        $this->assertEquals('Formatted Alert', $actualResult);
    }


    /**
     * @throws \Exception
     */
    public function testGetAlertDisabledMultipleTimezoneSupportApplicationTimezone()
    {
        $startDate = '2100-07-30 10:00:00';
        $stopDate = '2100-07-30 14:00:00';
        $maintenanceTimezone = 'Europe/London';
        $applicationDefaultTimeZone = 'Asia/Tokyo';

        $this->mockFormatter->expects($this->once())
            ->method('format')
            ->with(
                $this->callback(function ($arg) use ($applicationDefaultTimeZone, $startDate) {
                    return $arg instanceof DateTimeImmutable
                        && $arg->format('Y-m-d H:i:s') === '2100-07-30 18:00:00'
                        && $arg->getTimezone()->getName() === $applicationDefaultTimeZone;
                }),
                $this->callback(function ($arg) use ($applicationDefaultTimeZone, $stopDate) {
                    return $arg instanceof DateTimeImmutable
                        && $arg->format('Y-m-d H:i:s') === '2100-07-30 22:00:00'
                        && $arg->getTimezone()->getName() === $applicationDefaultTimeZone;
                })
            )
            ->willReturn('Formatted Alert');

        $generator = new MaintenanceAlertGenerator(
            alertFormatter: $this->mockFormatter,
            applicationDefaultTimeZone: $applicationDefaultTimeZone,
        );

        $actualResult = $generator->getAlert(
            maintenanceDateStart: $startDate,
            maintenanceDateStop: $stopDate,
            maintenanceTimeZone: $maintenanceTimezone,
            multipleTimeZoneSupport: false,
        );

        $this->assertEquals('Formatted Alert', $actualResult);
    }
}
