<?php

use App\Jobs\SendSmsJob;
use App\Models\Permission;
use App\Models\Role;
use App\Models\SmsLog;
use App\Models\SmsProfile;
use App\Models\SmsSender;
use App\Models\User;
use App\Services\Sms\SmsClient;
use App\Services\Sms\SmsMessage;
use App\Services\Sms\SmsResult;
use Illuminate\Support\Facades\Http;

function adminUserForSms(): User
{
    $user = User::factory()->create();
    // Ensure admin role & manage-settings permission exist
    $role = Role::firstOrCreate(['slug' => 'admin'], ['name' => 'Admin']);
    $permission = Permission::firstOrCreate(['slug' => 'manage-settings'], ['name' => 'Manage Settings']);
    $user->roles()->syncWithoutDetaching([$role->id]);
    if (method_exists($user, 'givePermissionTo')) {
        $user->givePermissionTo('manage-settings');
    }

    return $user;
}

it('creates an sms profile and encrypts password', function () {
    $user = adminUserForSms();
    test()->actingAs($user);

    $resp = test()->postJson(route('admin.sms-profiles.store'), [
        'name' => 'Primary SMS',
        'active' => true,
        'api_username' => 'testuser',
        'api_password' => 'super-secret',
    ]);

    $resp->assertCreated();
    $resp->assertJsonStructure(['profile' => ['id', 'uuid', 'name', 'active', 'api_username', 'created_at', 'updated_at']]);

    $profile = SmsProfile::first();
    expect($profile)->not->toBeNull();
    // Attribute is hidden, but verify decrypt roundtrip via model method
    expect($profile->decryptApiPassword())->toBe('super-secret');
});

it('queues a job to send sms and logs as sent', function () {
    $user = adminUserForSms();
    test()->actingAs($user);

    $profile = SmsProfile::factory()->create([
        'api_username' => 'apiuser',
        'api_password' => 'apipass',
    ]);
    $sender = SmsSender::factory()->create(['profile_id' => $profile->id]);

    // Bind a fake client that always returns sent with provider id
    app()->instance(SmsClient::class, new class implements SmsClient
    {
        public function send(App\Models\SmsProfile $profile, SmsMessage $message): SmsResult
        {
            return new SmsResult('sent', '123456');
        }

        public function getCreditBalance(App\Models\SmsProfile $profile): int
        {
            return 0;
        }

        public function getPriceQuotes(App\Models\SmsProfile $profile): array
        {
            return [];
        }
    });

    // Run the job synchronously
    (new SendSmsJob(
        profileId: $profile->id,
        to: '+38640111222',
        content: 'Hello from test',
        senderId: null,
        countryCode: null,
        deliveryReport: true,
        clientReference: null,
    ))->handle(app(\App\Services\Sms\SmsService::class));

    $log = SmsLog::first();
    expect($log)->not->toBeNull();
    expect($log->status)->toBe('sent');
    expect($log->provider_message_id)->toBe('123456');
});

it('returns balance and price quotes', function () {
    $user = adminUserForSms();
    test()->actingAs($user);

    $profile = SmsProfile::factory()->create([
        'api_username' => 'apiuser',
        'api_password' => 'apipass',
    ]);

    $base = config('services.sms.providers.smsapi_si.base_url');
    $creditsUrl = rtrim($base, '/').config('services.sms.providers.smsapi_si.credits_endpoint', '/preveri-stanje-kreditov');
    $priceUrl = rtrim($base, '/').config('services.sms.providers.smsapi_si.price_endpoint', '/dobi-ceno');

    Http::fake([
        $creditsUrl => Http::response('42', 200),
        $priceUrl => Http::response('0.05 EUR##0.07 EUR', 200),
    ]);

    test()->postJson(route('admin.sms-profiles.balance', $profile))
        ->assertSuccessful()
        ->assertJson(['balance' => '42']);

    test()->postJson(route('admin.sms-profiles.price', $profile))
        ->assertSuccessful()
        ->assertJson(['quotes' => ['0.05 EUR', '0.07 EUR']]);
});
