<?php

use App\Enums\MembershipStatus;
use App\Models\Branch;
use App\Models\Member;
use App\Models\MemberStatusHistory;
use App\Models\User;

test('changing status appends a history row with reason and effective date', function () {
    $branch = Branch::factory()->create();
    $member = Member::factory()->create(['branch_id' => $branch->id, 'membership_status' => 'visitor']);
    $clerk = User::factory()->dataClerk()->create(['branch_id' => $branch->id]);

    $response = $this->actingAs($clerk)->postJson("/api/v1/members/{$member->id}/status", [
        'to_status' => 'member',
        'reason' => 'Completed membership class',
        'effective_date' => '2026-01-15',
    ]);

    $response->assertOk()->assertJsonPath('data.membership_status', 'member');

    $history = MemberStatusHistory::where('member_id', $member->id)->orderByDesc('id')->first();
    expect($history->from_status)->toBe(MembershipStatus::Visitor);
    expect($history->to_status)->toBe(MembershipStatus::Member);
    expect($history->reason)->toBe('Completed membership class');
    expect($history->effective_date->toDateString())->toBe('2026-01-15');
});

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

    $this->actingAs($viewer)->postJson("/api/v1/members/{$member->id}/status", [
        'to_status' => 'member',
    ])->assertStatus(403);
});

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

    $this->actingAs($clerk)->postJson("/api/v1/members/{$member->id}/status", [
        'to_status' => 'member',
    ])->assertStatus(403);
});

test('branch_admin can move a member out of deceased status', function () {
    $branch = Branch::factory()->create();
    $member = Member::factory()->create(['branch_id' => $branch->id, 'membership_status' => 'deceased']);
    $admin = User::factory()->branchAdmin()->create(['branch_id' => $branch->id]);

    $this->actingAs($admin)->postJson("/api/v1/members/{$member->id}/status", [
        'to_status' => 'member',
        'reason' => 'Recorded in error',
    ])->assertOk();
});

test('data_clerk from another branch cannot change status', 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)->postJson("/api/v1/members/{$memberB->id}/status", [
        'to_status' => 'member',
    ])->assertStatus(404);
});

test('an invalid status value fails validation', 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)->postJson("/api/v1/members/{$member->id}/status", [
        'to_status' => 'not_a_real_status',
    ])->assertStatus(422)->assertJsonValidationErrors('to_status');
});

test('member history endpoint returns newest first', function () {
    $branch = Branch::factory()->create();
    $member = Member::factory()->create(['branch_id' => $branch->id, 'membership_status' => 'visitor']);
    $clerk = User::factory()->dataClerk()->create(['branch_id' => $branch->id]);

    $this->actingAs($clerk)->postJson("/api/v1/members/{$member->id}/status", ['to_status' => 'new_convert']);
    $this->actingAs($clerk)->postJson("/api/v1/members/{$member->id}/status", ['to_status' => 'member']);

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

    $response->assertOk();
    $statuses = collect($response->json('data'))->pluck('to_status');
    expect($statuses->first())->toBe('member');
    expect($statuses)->toHaveCount(3); // initial + 2 changes
});

test('unauthenticated status change is rejected', function () {
    $branch = Branch::factory()->create();
    $member = Member::factory()->create(['branch_id' => $branch->id]);

    $this->postJson("/api/v1/members/{$member->id}/status", ['to_status' => 'member'])->assertStatus(401);
});
