<?php

namespace Tests\Feature;

use App\Models\Central\Company;
use App\Models\Central\Plan;
use App\Models\Tenant\PushSubscription;
use App\Models\Tenant\User;
use App\Services\Notifications\WebPushService;
use App\Tenancy\TenantManager;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class PushSubscriptionTest extends TestCase
{
    use RefreshDatabase;

    public function test_subscribe_stores_subscription_for_user(): void
    {
        [$company, $user] = $this->makeUser('sub1');

        $this->actingAs($user)
            ->postJson('http://sub1.service.mir.md/push/subscribe', [
                'endpoint' => 'https://push.example.com/abc123',
                'keys' => ['p256dh' => 'PUBLICKEY', 'auth' => 'AUTHTOKEN'],
                'contentEncoding' => 'aes128gcm',
            ])
            ->assertOk()
            ->assertJson(['ok' => true]);

        $this->assertDatabaseHas('push_subscriptions', [
            'endpoint' => 'https://push.example.com/abc123',
            'user_id' => $user->id,
            'public_key' => 'PUBLICKEY',
            'content_encoding' => 'aes128gcm',
        ]);
    }

    public function test_subscribe_upserts_on_duplicate_endpoint(): void
    {
        [$company, $user] = $this->makeUser('sub2');

        $payload = [
            'endpoint' => 'https://push.example.com/dup',
            'keys' => ['p256dh' => 'KEY1', 'auth' => 'AUTH1'],
        ];

        $this->actingAs($user)->postJson('http://sub2.service.mir.md/push/subscribe', $payload)->assertOk();
        $payload['keys']['p256dh'] = 'KEY2';
        $this->actingAs($user)->postJson('http://sub2.service.mir.md/push/subscribe', $payload)->assertOk();

        $this->assertEquals(1, PushSubscription::where('endpoint', 'https://push.example.com/dup')->count());
        $this->assertEquals('KEY2', PushSubscription::where('endpoint', 'https://push.example.com/dup')->value('public_key'));
    }

    public function test_subscribe_requires_auth(): void
    {
        $this->makeUser('sub3');
        $this->postJson('http://sub3.service.mir.md/push/subscribe', [
            'endpoint' => 'https://push.example.com/noauth',
            'keys' => ['p256dh' => 'X', 'auth' => 'Y'],
        ])->assertStatus(401);
    }

    public function test_validation_rejects_missing_keys(): void
    {
        [$company, $user] = $this->makeUser('sub4');
        $this->actingAs($user)
            ->postJson('http://sub4.service.mir.md/push/subscribe', [
                'endpoint' => 'https://push.example.com/x',
            ])
            ->assertStatus(422);
    }

    public function test_webpush_service_reports_configured(): void
    {
        $svc = app(WebPushService::class);
        $this->assertTrue($svc->configured());
        $this->assertNotEmpty($svc->publicKey());
    }

    public function test_send_to_user_with_no_subscriptions_returns_zero(): void
    {
        [$company, $user] = $this->makeUser('sub5');
        $r = app(WebPushService::class)->sendToUser($user->id, 'T', 'B');
        $this->assertEquals(0, $r['sent']);
        $this->assertEquals(0, $r['pruned']);
    }

    private function makeUser(string $slug): array
    {
        $plan = Plan::firstOrCreate(['slug' => 'test'], ['name' => 'T', 'price' => 0, 'features' => []]);
        $company = Company::create([
            'plan_id' => $plan->id,
            'slug' => $slug,
            'name' => ucfirst($slug),
            'status' => 'active',
        ]);
        app(TenantManager::class)->setCurrent($company);

        $user = User::create([
            'company_id' => $company->id,
            'name' => 'Push User',
            'email' => $slug . '@example.com',
            'password' => bcrypt('secret'),
            'role' => 'admin',
            'status' => 'active',
        ]);

        return [$company, $user];
    }
}
