<?php

namespace Tests\Tenant\Services;

use App\Facades\Settings;
use App\Mail\VehiclesInVideoTokenExpiringMail;
use App\Models\ExternalApiToken;
use App\Modules\VehiclesInVideo\Services\TokenService;
use Database\Seeders\Tenant\VehiclesInVideoSettingSeeder;
use Illuminate\Support\Facades\Mail;
use Tests\TenantTestCase;

class VehiclesInVideoTokenServiceTest extends TenantTestCase
{
    protected function setUp(): void
    {
        parent::setUp();
        $this->seed(VehiclesInVideoSettingSeeder::class);
        Settings::update('vehicles-in-video-notification-recipients', 'ops@example.com');
    }

    public function testCheckTokenExpiryReturnsInfoWhenNoToken(): void
    {
        Mail::fake();

        $result = app(TokenService::class)->checkTokenExpiry();

        $this->assertEquals('info', $result['status']);
        $this->assertEquals('No connected token found.', $result['message']);
        Mail::assertNothingSent();
    }

    public function testCheckTokenExpiryReturnsInfoWhenTokenHasNoRefreshToken(): void
    {
        Mail::fake();
        ExternalApiToken::create([
            'provider' => TokenService::PROVIDER,
            'grant_url' => 'https://example.com/grant',
        ]);

        $result = app(TokenService::class)->checkTokenExpiry();

        $this->assertEquals('info', $result['status']);
        $this->assertEquals('No connected token found.', $result['message']);
        Mail::assertNothingSent();
    }

    public function testCheckTokenExpiryReturnsWarnWhenNoExpirySet(): void
    {
        Mail::fake();
        ExternalApiToken::create([
            'provider' => TokenService::PROVIDER,
            'auth_token' => 'auth',
            'refresh_token' => 'refresh',
        ]);

        $result = app(TokenService::class)->checkTokenExpiry();

        $this->assertEquals('warn', $result['status']);
        $this->assertEquals('Connected token has no refresh expiry date set.', $result['message']);
        Mail::assertNothingSent();
    }

    public function testCheckTokenExpiryReturnsInfoWhenMoreThanThirtyDaysLeft(): void
    {
        Mail::fake();
        ExternalApiToken::create([
            'provider' => TokenService::PROVIDER,
            'auth_token' => 'auth',
            'refresh_token' => 'refresh',
            'refresh_expires_at' => now()->addDays(90),
        ]);

        $result = app(TokenService::class)->checkTokenExpiry();

        $this->assertEquals('info', $result['status']);
        $this->assertStringContainsString('No action needed', $result['message']);
        Mail::assertNothingSent();
    }

    public function testCheckTokenExpiryReturnsWarnAndSendsMailWhenUnderThirtyDays(): void
    {
        Mail::fake();
        ExternalApiToken::create([
            'provider' => TokenService::PROVIDER,
            'auth_token' => 'auth',
            'refresh_token' => 'refresh',
            'refresh_expires_at' => now()->addDays(10),
        ]);

        $result = app(TokenService::class)->checkTokenExpiry();

        $this->assertEquals('warn', $result['status']);
        $this->assertStringContainsString('Notification sent', $result['message']);
        Mail::assertSent(
            VehiclesInVideoTokenExpiringMail::class,
            fn ($mail) => $mail->hasTo('ops@example.com')
        );
    }

    public function testCheckTokenExpiryReturnsErrorAndSendsMailWhenExpired(): void
    {
        Mail::fake();
        ExternalApiToken::create([
            'provider' => TokenService::PROVIDER,
            'auth_token' => 'auth',
            'refresh_token' => 'refresh',
            'refresh_expires_at' => now()->subDays(2),
        ]);

        $result = app(TokenService::class)->checkTokenExpiry();

        $this->assertEquals('error', $result['status']);
        $this->assertStringContainsString('already expired', $result['message']);
        Mail::assertSent(VehiclesInVideoTokenExpiringMail::class);
    }

    public function testCheckTokenExpiryIgnoresTokensFromOtherProviders(): void
    {
        Mail::fake();
        ExternalApiToken::create([
            'provider' => 'some-other-provider',
            'auth_token' => 'auth',
            'refresh_token' => 'refresh',
            'refresh_expires_at' => now()->subDays(2),
        ]);

        $result = app(TokenService::class)->checkTokenExpiry();

        $this->assertEquals('info', $result['status']);
        $this->assertEquals('No connected token found.', $result['message']);
        Mail::assertNothingSent();
    }
}
