<?php

use App\Models\Branch;
use App\Models\Member;
use App\Models\User;

test('a data_clerk cannot view the audit log', function () {
    $branch = Branch::factory()->create();
    $clerk = User::factory()->dataClerk()->create(['branch_id' => $branch->id]);

    $this->actingAs($clerk)->getJson('/api/v1/audit-logs')->assertStatus(403);
});

test('a viewer cannot view the audit log', function () {
    $branch = Branch::factory()->create();
    $viewer = User::factory()->branchViewer()->create(['branch_id' => $branch->id]);

    $this->actingAs($viewer)->getJson('/api/v1/audit-logs')->assertStatus(403);
});

test('a branch_admin only sees audit entries for their own branch', function () {
    $branchA = Branch::factory()->create();
    $branchB = Branch::factory()->create();
    $memberA = Member::factory()->create(['branch_id' => $branchA->id]);
    $memberB = Member::factory()->create(['branch_id' => $branchB->id]);
    $adminA = User::factory()->branchAdmin()->create(['branch_id' => $branchA->id]);

    $response = $this->actingAs($adminA)->getJson('/api/v1/audit-logs');

    $response->assertOk();
    $auditableIds = collect($response->json('data'))
        ->where('auditable_type', 'Member')
        ->pluck('auditable_id');
    expect($auditableIds)->toContain($memberA->id)->not->toContain($memberB->id);
});

test('super_admin sees audit entries across every branch', function () {
    $branchA = Branch::factory()->create();
    $branchB = Branch::factory()->create();
    $memberA = Member::factory()->create(['branch_id' => $branchA->id]);
    $memberB = Member::factory()->create(['branch_id' => $branchB->id]);
    $superAdmin = User::factory()->superAdmin()->create();

    $response = $this->actingAs($superAdmin)->getJson('/api/v1/audit-logs');

    $auditableIds = collect($response->json('data'))
        ->where('auditable_type', 'Member')
        ->pluck('auditable_id');
    expect($auditableIds)->toContain($memberA->id, $memberB->id);
});

test('the audit log can be filtered by member_id, action, and date range', function () {
    $branch = Branch::factory()->create();
    $member = Member::factory()->create(['branch_id' => $branch->id]);
    $otherMember = Member::factory()->create(['branch_id' => $branch->id]);
    $admin = User::factory()->branchAdmin()->create(['branch_id' => $branch->id]);

    $this->actingAs($admin)->putJson("/api/v1/members/{$member->id}", ['occupation' => 'Engineer'])->assertOk();

    $byMember = $this->actingAs($admin)->getJson("/api/v1/audit-logs?member_id={$member->id}");
    expect(collect($byMember->json('data'))->pluck('auditable_id'))->each->toBe($member->id);

    $byAction = $this->actingAs($admin)->getJson('/api/v1/audit-logs?action=updated');
    expect($byAction->json('data'))->not->toBeEmpty();
    expect(collect($byAction->json('data'))->pluck('action'))->each->toBe('updated');

    $futureOnly = $this->actingAs($admin)->getJson('/api/v1/audit-logs?date_from='.now()->addDay()->toDateString());
    expect($futureOnly->json('data'))->toBeEmpty();

    // The unrelated member's creation audit entry is still visible without the filter.
    $unfiltered = $this->actingAs($admin)->getJson('/api/v1/audit-logs');
    expect(collect($unfiltered->json('data'))->pluck('auditable_id'))->toContain($otherMember->id);
});

test('audit entries include a human-readable member label', function () {
    $branch = Branch::factory()->create();
    $member = Member::factory()->create(['branch_id' => $branch->id, 'first_name' => 'Tendai', 'last_name' => 'Moyo']);
    $admin = User::factory()->branchAdmin()->create(['branch_id' => $branch->id]);

    $response = $this->actingAs($admin)->getJson('/api/v1/audit-logs');

    $entry = collect($response->json('data'))->firstWhere('auditable_id', $member->id);
    expect($entry['auditable_label'])->toBe('Tendai Moyo');
});

test('unauthenticated request to the audit log is rejected', function () {
    $this->getJson('/api/v1/audit-logs')->assertStatus(401);
});
