<?php

namespace Tests\Unit\Support;

use App\Support\ProviderFailure;
use RuntimeException;
use Tests\TestCase;

/**
 * A quota window and a busy server need opposite advice.
 *
 * The chat was fixed for this first. The creative studio was not, and on 23 Sep
 * a Gemini 429 on dev reached the user as "Generation failed. Please try
 * again." - advice that is not merely unhelpful but wrong, because every retry
 * fails identically until the window resets.
 */
class ProviderFailureTest extends TestCase
{
    public function test_a_rate_limit_is_recognised_however_the_provider_words_it(): void
    {
        foreach ([
            'Application rate limited by AI provider [gemini]',
            'HTTP 429 Too Many Requests',
            'RESOURCE_EXHAUSTED: quota exceeded for model',
            'You exceeded your current quota',
        ] as $message) {
            $this->assertTrue(
                ProviderFailure::isRateLimit(new RuntimeException($message)),
                "Not recognised as a rate limit: {$message}",
            );
        }
    }

    public function test_an_ordinary_failure_is_not_mistaken_for_a_rate_limit(): void
    {
        foreach ([
            'Connection timed out after 30001 milliseconds',
            'The model returned no image',
            'cURL error 28',
        ] as $message) {
            $this->assertFalse(
                ProviderFailure::isRateLimit(new RuntimeException($message)),
                "Wrongly treated as a rate limit: {$message}",
            );
        }
    }

    /** Never "try again", which is the whole point. */
    public function test_the_message_does_not_tell_the_user_to_retry(): void
    {
        $message = ProviderFailure::rateLimited(new RuntimeException('429 rate limit'));

        $this->assertStringNotContainsStringIgnoringCase('please try again', $message);
        $this->assertStringContainsString('fail the same way', $message);
    }

    public function test_a_stated_wait_is_passed_on_so_the_user_knows_how_long(): void
    {
        $this->assertStringContainsString(
            '45 seconds',
            ProviderFailure::rateLimited(new RuntimeException('rate limit, retry after 45 seconds')),
        );

        $this->assertStringContainsString(
            '2 minutes',
            ProviderFailure::rateLimited(new RuntimeException('rate limit, try again in 120 seconds')),
        );
    }

    /**
     * The provider's own message never reaches the user.
     *
     * These carry endpoints, model names and occasionally credentials, and none
     * of it means anything to a buyer.
     */
    public function test_the_vendor_message_is_not_echoed_back(): void
    {
        $raw = 'Application rate limited by AI provider [gemini] at '
            .'https://generativelanguage.googleapis.com/v1/models/imagen-3:predict?key=AIzaSyD_SECRET';

        $message = ProviderFailure::rateLimited(new RuntimeException($raw));

        $this->assertStringNotContainsString('googleapis.com', $message);
        $this->assertStringNotContainsString('AIzaSyD_SECRET', $message);
        $this->assertStringNotContainsString('imagen-3', $message);
    }
}
