<?php

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

test('data_clerk can create a member in their own branch', function () {
    $branch = Branch::factory()->create();
    $clerk = User::factory()->dataClerk()->create(['branch_id' => $branch->id]);

    $response = $this->actingAs($clerk)->postJson('/api/v1/members', [
        'branch_id' => $branch->id,
        'first_name' => 'Tendai',
        'last_name' => 'Moyo',
        'gender' => 'male',
    ]);

    $response->assertCreated();
    expect($response->json('data.full_name'))->toBe('Tendai Moyo');
    expect($response->json('data.member_number'))->toMatch('/^M\d{8}$/');
    $this->assertDatabaseHas('members', ['first_name' => 'Tendai', 'branch_id' => $branch->id]);
});

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

    $this->actingAs($viewer)->postJson('/api/v1/members', [
        'branch_id' => $branch->id,
        'first_name' => 'Tendai',
        'last_name' => 'Moyo',
        'gender' => 'male',
    ])->assertStatus(403);
});

test('data_clerk cannot create a member in another branch', function () {
    $ownBranch = Branch::factory()->create();
    $otherBranch = Branch::factory()->create();
    $clerk = User::factory()->dataClerk()->create(['branch_id' => $ownBranch->id]);

    $this->actingAs($clerk)->postJson('/api/v1/members', [
        'branch_id' => $otherBranch->id,
        'first_name' => 'Tendai',
        'last_name' => 'Moyo',
        'gender' => 'male',
    ])->assertStatus(403);
});

test('creating a member without required fields fails validation', function () {
    $branch = Branch::factory()->create();
    $clerk = User::factory()->dataClerk()->create(['branch_id' => $branch->id]);

    $this->actingAs($clerk)->postJson('/api/v1/members', [
        'branch_id' => $branch->id,
    ])->assertStatus(422)->assertJsonValidationErrors(['first_name', 'last_name', 'gender']);
});

test('unauthenticated request to create a member is rejected', function () {
    $this->postJson('/api/v1/members', [])->assertStatus(401);
});

test('branch_admin of branch A gets 404 on a branch B member', function () {
    $branchA = Branch::factory()->create();
    $branchB = Branch::factory()->create();
    $memberB = Member::factory()->create(['branch_id' => $branchB->id]);
    $adminA = User::factory()->branchAdmin()->create(['branch_id' => $branchA->id]);

    $this->actingAs($adminA)->getJson("/api/v1/members/{$memberB->id}")->assertStatus(404);
});

test('branch_admin sees an empty list when filtered to another branch', function () {
    $branchA = Branch::factory()->create();
    $branchB = Branch::factory()->create();
    Member::factory()->count(3)->create(['branch_id' => $branchB->id]);
    $adminA = User::factory()->branchAdmin()->create(['branch_id' => $branchA->id]);

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

    $response->assertOk();
    expect($response->json('data'))->toHaveCount(0);
});

test('data_clerk cannot update a member in another branch', function () {
    $branchA = Branch::factory()->create();
    $branchB = Branch::factory()->create();
    $memberB = Member::factory()->create(['branch_id' => $branchB->id]);
    $clerkA = User::factory()->dataClerk()->create(['branch_id' => $branchA->id]);

    $this->actingAs($clerkA)->putJson("/api/v1/members/{$memberB->id}", [
        'first_name' => 'Hijacked',
    ])->assertStatus(404);
});

test('a member can be updated', function () {
    $branch = Branch::factory()->create();
    $member = Member::factory()->create(['branch_id' => $branch->id, 'occupation' => 'Teacher']);
    $clerk = User::factory()->dataClerk()->create(['branch_id' => $branch->id]);

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

    $response->assertOk()->assertJsonPath('data.occupation', 'Engineer');
});

test('phone numbers are normalized to digits only on save', function () {
    $branch = Branch::factory()->create();
    $clerk = User::factory()->dataClerk()->create(['branch_id' => $branch->id]);

    $response = $this->actingAs($clerk)->postJson('/api/v1/members', [
        'branch_id' => $branch->id,
        'first_name' => 'Tendai',
        'last_name' => 'Moyo',
        'gender' => 'male',
        'phone_primary' => '+263 (77) 123-4567',
    ]);

    $response->assertCreated();
    $this->assertDatabaseHas('members', ['phone_primary' => '263771234567']);
});

test('a phone number with too few digits fails validation', function () {
    $branch = Branch::factory()->create();
    $clerk = User::factory()->dataClerk()->create(['branch_id' => $branch->id]);

    $this->actingAs($clerk)->postJson('/api/v1/members', [
        'branch_id' => $branch->id,
        'first_name' => 'Tendai',
        'last_name' => 'Moyo',
        'gender' => 'male',
        'phone_primary' => '123',
    ])->assertStatus(422)->assertJsonValidationErrors('phone_primary');
});

test('branch_admin can soft-delete a member in their branch', function () {
    $branch = Branch::factory()->create();
    $member = Member::factory()->create(['branch_id' => $branch->id]);
    $admin = User::factory()->branchAdmin()->create(['branch_id' => $branch->id]);

    $this->actingAs($admin)->deleteJson("/api/v1/members/{$member->id}")->assertStatus(204);

    $this->assertSoftDeleted('members', ['id' => $member->id]);
});

test('data_clerk cannot delete a member', function () {
    $branch = Branch::factory()->create();
    $member = Member::factory()->create(['branch_id' => $branch->id]);
    $clerk = User::factory()->dataClerk()->create(['branch_id' => $branch->id]);

    $this->actingAs($clerk)->deleteJson("/api/v1/members/{$member->id}")->assertStatus(403);
});

test('a soft-deleted member disappears from the default list', function () {
    $branch = Branch::factory()->create();
    $member = Member::factory()->create(['branch_id' => $branch->id]);
    $member->delete();
    $admin = User::factory()->branchAdmin()->create(['branch_id' => $branch->id]);

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

    expect(collect($response->json('data'))->pluck('id'))->not->toContain($member->id);
});

test('member detail includes household and groups when present', function () {
    $branch = Branch::factory()->create();
    $member = Member::factory()->create(['branch_id' => $branch->id]);
    $superAdmin = User::factory()->superAdmin()->create();

    $response = $this->actingAs($superAdmin)->getJson("/api/v1/members/{$member->id}");

    $response->assertOk();
    expect($response->json('data'))->toHaveKeys(['household', 'groups', 'latest_status_change']);
});
