<?php

namespace Tests\Unit\Domain\CronJob;

use Domain\CronJob\CronJobType;
use PHPUnit\Framework\TestCase;

class CronJobTypeTest extends TestCase
{
    public function testAllTypesReturnsAllJobTypes(): void
    {
        $types = CronJobType::allTypes();

        $this->assertContains('apilo_token_keepalive', $types);
        $this->assertContains('apilo_send_order', $types);
        $this->assertContains('apilo_sync_payment', $types);
        $this->assertContains('apilo_sync_status', $types);
        $this->assertContains('apilo_product_sync', $types);
        $this->assertContains('apilo_pricelist_sync', $types);
        $this->assertContains('apilo_status_poll', $types);
        $this->assertContains('price_history', $types);
        $this->assertContains('order_analysis', $types);
        $this->assertContains('trustmate_invitation', $types);
        $this->assertContains('google_xml_feed', $types);
        $this->assertCount(11, $types);
    }

    public function testAllStatusesReturnsAllStatuses(): void
    {
        $statuses = CronJobType::allStatuses();

        $this->assertContains('pending', $statuses);
        $this->assertContains('processing', $statuses);
        $this->assertContains('completed', $statuses);
        $this->assertContains('failed', $statuses);
        $this->assertContains('cancelled', $statuses);
        $this->assertCount(5, $statuses);
    }

    public function testPriorityConstants(): void
    {
        $this->assertSame(10, CronJobType::PRIORITY_CRITICAL);
        $this->assertSame(40, CronJobType::PRIORITY_SEND_ORDER);
        $this->assertSame(50, CronJobType::PRIORITY_HIGH);
        $this->assertSame(100, CronJobType::PRIORITY_NORMAL);
        $this->assertSame(200, CronJobType::PRIORITY_LOW);

        // Lower value = higher priority
        $this->assertLessThan(CronJobType::PRIORITY_SEND_ORDER, CronJobType::PRIORITY_CRITICAL);
        $this->assertLessThan(CronJobType::PRIORITY_HIGH, CronJobType::PRIORITY_SEND_ORDER);
        $this->assertLessThan(CronJobType::PRIORITY_NORMAL, CronJobType::PRIORITY_HIGH);
        $this->assertLessThan(CronJobType::PRIORITY_LOW, CronJobType::PRIORITY_NORMAL);
    }

    public function testCalculateBackoffExponential(): void
    {
        // Attempt 1: 60s
        $this->assertSame(60, CronJobType::calculateBackoff(1));
        // Attempt 2: 120s
        $this->assertSame(120, CronJobType::calculateBackoff(2));
        // Attempt 3: 240s
        $this->assertSame(240, CronJobType::calculateBackoff(3));
        // Attempt 4: 480s
        $this->assertSame(480, CronJobType::calculateBackoff(4));
    }

    public function testCalculateBackoffCapsAtMax(): void
    {
        // Very high attempt should cap at MAX_BACKOFF_SECONDS (3600)
        $this->assertSame(3600, CronJobType::calculateBackoff(10));
        $this->assertSame(3600, CronJobType::calculateBackoff(20));
    }

    public function testJobTypeConstantsMatchStrings(): void
    {
        $this->assertSame('apilo_token_keepalive', CronJobType::APILO_TOKEN_KEEPALIVE);
        $this->assertSame('apilo_send_order', CronJobType::APILO_SEND_ORDER);
        $this->assertSame('apilo_sync_payment', CronJobType::APILO_SYNC_PAYMENT);
        $this->assertSame('apilo_sync_status', CronJobType::APILO_SYNC_STATUS);
        $this->assertSame('apilo_product_sync', CronJobType::APILO_PRODUCT_SYNC);
        $this->assertSame('apilo_pricelist_sync', CronJobType::APILO_PRICELIST_SYNC);
        $this->assertSame('apilo_status_poll', CronJobType::APILO_STATUS_POLL);
        $this->assertSame('price_history', CronJobType::PRICE_HISTORY);
        $this->assertSame('order_analysis', CronJobType::ORDER_ANALYSIS);
        $this->assertSame('trustmate_invitation', CronJobType::TRUSTMATE_INVITATION);
        $this->assertSame('google_xml_feed', CronJobType::GOOGLE_XML_FEED);
    }

    public function testStatusConstantsMatchStrings(): void
    {
        $this->assertSame('pending', CronJobType::STATUS_PENDING);
        $this->assertSame('processing', CronJobType::STATUS_PROCESSING);
        $this->assertSame('completed', CronJobType::STATUS_COMPLETED);
        $this->assertSame('failed', CronJobType::STATUS_FAILED);
        $this->assertSame('cancelled', CronJobType::STATUS_CANCELLED);
    }
}
