<?php

namespace Tests\Feature;

use App\Models\Organization;
use App\Models\Room;
use App\Models\Session;
use App\Services\Meet\MeetBillingService;
use App\Services\Meet\UsageMeteringService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Tests\TestCase;

class MeetBillingTest extends TestCase
{
    use RefreshDatabase;

    protected function fakeAffordableBilling(): void
    {
        $base = rtrim((string) config('billing.api_url'), '/');

        Http::fake([
            $base.'/can-afford*' => Http::response(['affordable' => true]),
            $base.'/debit' => Http::response(['ok' => true]),
        ]);
    }

    public function test_session_end_charges_per_participant(): void
    {
        $this->fakeAffordableBilling();

        $organization = Organization::create([
            'owner_ref' => 'owner-001',
            'name' => 'Billing Org',
            'slug' => 'billing-org',
            'timezone' => 'UTC',
        ]);

        $room = Room::create([
            'owner_ref' => 'owner-001',
            'organization_id' => $organization->id,
            'host_user_ref' => 'owner-001',
            'title' => 'Billing Room',
            'type' => 'instant',
            'status' => 'live',
            'settings' => config('meet.default_settings'),
        ]);

        $session = Session::create([
            'owner_ref' => 'owner-001',
            'room_id' => $room->id,
            'media_room_name' => 'room-test',
            'status' => 'ended',
            'started_at' => now()->subHour(),
            'ended_at' => now(),
            'peak_participants' => 4,
        ]);

        app(UsageMeteringService::class)->recordSessionUsage($session);

        $this->assertDatabaseHas('meet_usage_records', [
            'organization_id' => $organization->id,
            'metric' => 'participant_count',
            'quantity' => 4,
        ]);

        Http::assertSent(fn ($request) => str_contains($request->url(), '/debit')
            && ($request->data()['source'] ?? '') === 'meet_participants');
    }

    public function test_webinar_session_end_charges_per_participant(): void
    {
        $this->fakeAffordableBilling();

        $organization = Organization::create([
            'owner_ref' => 'owner-webinar',
            'name' => 'Webinar Org',
            'slug' => 'webinar-org',
            'timezone' => 'UTC',
        ]);

        $room = Room::create([
            'owner_ref' => 'owner-webinar',
            'organization_id' => $organization->id,
            'host_user_ref' => 'owner-webinar',
            'title' => 'Webinar Room',
            'type' => 'webinar',
            'status' => 'ended',
            'settings' => config('meet.default_settings'),
        ]);

        $session = Session::create([
            'owner_ref' => 'owner-webinar',
            'room_id' => $room->id,
            'media_room_name' => 'webinar-test',
            'status' => 'ended',
            'started_at' => now()->subHour(),
            'ended_at' => now(),
            'peak_participants' => 5,
        ]);

        app(UsageMeteringService::class)->recordSessionUsage($session);

        $this->assertDatabaseHas('meet_usage_records', [
            'organization_id' => $organization->id,
            'metric' => 'participant_count',
            'quantity' => 5,
        ]);

        Http::assertSent(fn ($request) => str_contains($request->url(), '/debit')
            && ($request->data()['source'] ?? '') === 'meet_participants');
    }

    public function test_storage_renewal_enters_grace_when_wallet_is_empty(): void
    {
        $base = rtrim((string) config('billing.api_url'), '/');
        Http::fake([
            $base.'/can-afford*' => Http::response(['affordable' => false]),
        ]);

        $organization = Organization::create([
            'owner_ref' => 'owner-002',
            'name' => 'Grace Org',
            'slug' => 'grace-org',
            'timezone' => 'UTC',
        ]);

        $room = Room::create([
            'owner_ref' => 'owner-002',
            'organization_id' => $organization->id,
            'host_user_ref' => 'owner-002',
            'title' => 'Grace Room',
            'type' => 'instant',
            'status' => 'ended',
            'settings' => config('meet.default_settings'),
        ]);

        $session = Session::create([
            'owner_ref' => 'owner-002',
            'room_id' => $room->id,
            'media_room_name' => 'room-grace',
            'status' => 'ended',
            'started_at' => now()->subDay(),
            'ended_at' => now()->subDay(),
        ]);

        $file = \App\Models\SessionFile::create([
            'owner_ref' => 'owner-002',
            'room_id' => $room->id,
            'session_id' => $session->id,
            'uploaded_by_ref' => 'owner-002',
            'uploaded_by_name' => 'Host',
            'original_name' => 'notes.pdf',
            'storage_path' => 'meet-files/test/notes.pdf',
            'file_size' => 1073741824,
            'storage_paid_until' => now()->subMinute(),
        ]);

        $result = app(MeetBillingService::class)->processDueStorageRenewals();

        $file->refresh();
        $this->assertSame(1, $result['graced']);
        $this->assertNotNull($file->storage_grace_ends_at);
    }
}
