<?php

use App\Models\User;
use Illuminate\Http\Client\Request;
use Illuminate\Support\Facades\Http;
use Livewire\Livewire;
use Modules\AiAgent\Filament\Pages\ManageAgentInstructions;
use Spatie\Permission\Models\Permission;

beforeEach(function () {
    config([
        'services.bnfexpress.ai_api_url' => 'https://bnfexpress.test',
        'services.bnfexpress.client_id' => 'ev_admin',
        'services.bnfexpress.client_secret' => 'test-secret',
    ]);

    Permission::findOrCreate('manage_ai_agent', 'web');

    $this->admin = User::factory()->create()->givePermissionTo(['manage_ai_agent']);
    $this->actingAs($this->admin);
});

test('a user without manage_ai_agent cannot access it', function () {
    $this->actingAs(User::factory()->create());

    expect(ManageAgentInstructions::canAccess())->toBeFalse();
});

test('it renders the active instruction and version history', function () {
    Http::fake([
        'bnfexpress.test/admin/agent-instructions/active*' => Http::response(['id' => 2, 'content' => 'You are the EV assistant.']),
        'bnfexpress.test/admin/agent-instructions*' => Http::response([
            'total' => 1,
            'instructions' => [['id' => 2, 'is_active' => true, 'content' => 'You are the EV assistant.', 'created_at' => now()->toIso8601String()]],
        ]),
    ]);

    Livewire::test(ManageAgentInstructions::class)
        ->assertOk()
        ->assertSee('You are the EV assistant.')
        ->loadTable()
        ->assertSee('You are the EV assistant.');
});

test('publishing a new version calls publishInstruction and shows a success notification', function () {
    Http::fake([
        'bnfexpress.test/admin/agent-instructions/active*' => Http::response(['id' => 3, 'content' => 'New instructions.']),
        'bnfexpress.test/admin/agent-instructions*' => fn (Request $request) => match ($request->method()) {
            'POST' => Http::response(['id' => 3, 'content' => 'New instructions.', 'is_active' => true], 201),
            default => Http::response(['total' => 0, 'instructions' => []]),
        },
    ]);

    Livewire::test(ManageAgentInstructions::class)
        ->loadTable()
        ->callTableAction('publish', data: ['content' => 'New instructions.', 'activate' => true])
        ->assertNotified('New instruction version published');

    Http::assertSent(fn (Request $request) => $request->method() === 'POST'
        && str_contains($request->url(), '/admin/agent-instructions')
        && ! str_contains($request->url(), '/active')
        && $request['content'] === 'New instructions.'
        && $request['activate'] === true);
});

test('a failed publish surfaces the gateway detail message', function () {
    Http::fake([
        'bnfexpress.test/admin/agent-instructions/active*' => Http::response(['id' => 1, 'content' => 'Old instructions.']),
        'bnfexpress.test/admin/agent-instructions*' => fn (Request $request) => match ($request->method()) {
            'POST' => Http::response(['detail' => 'Content is required.'], 422),
            default => Http::response(['total' => 0, 'instructions' => []]),
        },
    ]);

    Livewire::test(ManageAgentInstructions::class)
        ->loadTable()
        ->callTableAction('publish', data: ['content' => 'New instructions.', 'activate' => true])
        ->assertNotified('Failed to publish instruction');
});

test('activate is hidden on the already-active row and visible on others', function () {
    Http::fake([
        'bnfexpress.test/admin/agent-instructions/active*' => Http::response(['id' => 2, 'content' => 'Current.']),
        'bnfexpress.test/admin/agent-instructions*' => Http::response([
            'total' => 2,
            'instructions' => [
                ['id' => 2, 'is_active' => true, 'content' => 'Current.', 'created_at' => now()->toIso8601String()],
                ['id' => 1, 'is_active' => false, 'content' => 'Older.', 'created_at' => now()->toIso8601String()],
            ],
        ]),
    ]);

    Livewire::test(ManageAgentInstructions::class)
        ->loadTable()
        ->assertTableActionHidden('activate', 2)
        ->assertTableActionVisible('activate', 1);
});
