<?php

use App\Models\Branch;
use App\Models\Region;
use App\Models\User;

test('super_admin can list all users', function () {
    $superAdmin = User::factory()->superAdmin()->create();
    User::factory()->branchAdmin()->count(3)->create();

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

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

test('region_admin sees only their own region\'s users', function () {
    $regionA = Region::factory()->create();
    $regionB = Region::factory()->create();
    $branchA = Branch::factory()->create(['region_id' => $regionA->id]);
    $branchB = Branch::factory()->create(['region_id' => $regionB->id]);

    $regionAdminA = User::factory()->regionAdmin()->create(['region_id' => $regionA->id]);
    User::factory()->branchAdmin()->create(['branch_id' => $branchA->id]);
    User::factory()->branchAdmin()->create(['branch_id' => $branchB->id]);

    $response = $this->actingAs($regionAdminA)->getJson('/api/v1/users');

    $response->assertOk();
    // regionAdminA + the one branch_admin under branchA (region B's user excluded)
    expect($response->json('data'))->toHaveCount(2);
});

test('branch_admin cannot list users', function () {
    $branchAdmin = User::factory()->branchAdmin()->create();

    $this->actingAs($branchAdmin)->getJson('/api/v1/users')->assertStatus(403);
});

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

test('super_admin can create a super_admin user', function () {
    $superAdmin = User::factory()->superAdmin()->create();

    $response = $this->actingAs($superAdmin)->postJson('/api/v1/users', [
        'name' => 'New Admin',
        'email' => 'new-admin@example.com',
        'password' => 'password123',
        'role' => 'super_admin',
        'region_id' => null,
        'branch_id' => null,
    ]);

    $response->assertCreated();
    $this->assertDatabaseHas('users', ['email' => 'new-admin@example.com', 'role' => 'super_admin']);
});

test('creating a super_admin with a branch_id fails the scope invariant', function () {
    $superAdmin = User::factory()->superAdmin()->create();
    $branch = Branch::factory()->create();

    $response = $this->actingAs($superAdmin)->postJson('/api/v1/users', [
        'name' => 'Bad Admin',
        'email' => 'bad-admin@example.com',
        'password' => 'password123',
        'role' => 'super_admin',
        'branch_id' => $branch->id,
    ]);

    $response->assertStatus(422)->assertJsonValidationErrors('role');
});

test('creating a viewer with both region_id and branch_id fails the scope invariant', function () {
    $superAdmin = User::factory()->superAdmin()->create();
    $region = Region::factory()->create();
    $branch = Branch::factory()->create();

    $response = $this->actingAs($superAdmin)->postJson('/api/v1/users', [
        'name' => 'Bad Viewer',
        'email' => 'bad-viewer@example.com',
        'password' => 'password123',
        'role' => 'viewer',
        'region_id' => $region->id,
        'branch_id' => $branch->id,
    ]);

    $response->assertStatus(422)->assertJsonValidationErrors('role');
});

test('creating a branch_admin without a branch_id fails the scope invariant', function () {
    $superAdmin = User::factory()->superAdmin()->create();

    $response = $this->actingAs($superAdmin)->postJson('/api/v1/users', [
        'name' => 'Bad Branch Admin',
        'email' => 'bad-branch-admin@example.com',
        'password' => 'password123',
        'role' => 'branch_admin',
    ]);

    $response->assertStatus(422)->assertJsonValidationErrors('branch_id');
});

test('region_admin may only create branch-level roles within their own region', function () {
    $regionA = Region::factory()->create();
    $regionB = Region::factory()->create();
    $branchB = Branch::factory()->create(['region_id' => $regionB->id]);

    $regionAdminA = User::factory()->regionAdmin()->create(['region_id' => $regionA->id]);

    // Attempting to create another region_admin is forbidden by role restriction.
    $this->actingAs($regionAdminA)->postJson('/api/v1/users', [
        'name' => 'Sneaky',
        'email' => 'sneaky@example.com',
        'password' => 'password123',
        'role' => 'region_admin',
        'region_id' => $regionA->id,
    ])->assertStatus(422)->assertJsonValidationErrors('role');

    // Attempting to create a branch_admin in another region is forbidden.
    $this->actingAs($regionAdminA)->postJson('/api/v1/users', [
        'name' => 'Out Of Region',
        'email' => 'out-of-region@example.com',
        'password' => 'password123',
        'role' => 'branch_admin',
        'branch_id' => $branchB->id,
    ])->assertStatus(422)->assertJsonValidationErrors('branch_id');
});

test('region_admin can create a branch_admin within their own region', function () {
    $region = Region::factory()->create();
    $branch = Branch::factory()->create(['region_id' => $region->id]);
    $regionAdmin = User::factory()->regionAdmin()->create(['region_id' => $region->id]);

    $response = $this->actingAs($regionAdmin)->postJson('/api/v1/users', [
        'name' => 'In Region',
        'email' => 'in-region@example.com',
        'password' => 'password123',
        'role' => 'branch_admin',
        'branch_id' => $branch->id,
    ]);

    $response->assertCreated();
});

test('a user cannot deactivate themselves', function () {
    $superAdmin = User::factory()->superAdmin()->create();

    $response = $this->actingAs($superAdmin)->postJson("/api/v1/users/{$superAdmin->id}/deactivate");

    $response->assertStatus(403);
    expect($superAdmin->fresh()->is_active)->toBeTrue();
});

test('super_admin can deactivate another user', function () {
    $superAdmin = User::factory()->superAdmin()->create();
    $target = User::factory()->branchAdmin()->create();

    $response = $this->actingAs($superAdmin)->postJson("/api/v1/users/{$target->id}/deactivate");

    $response->assertOk();
    expect($target->fresh()->is_active)->toBeFalse();
});

test('region_admin cannot manage a user outside their region', function () {
    $regionA = Region::factory()->create();
    $regionB = Region::factory()->create();
    $branchB = Branch::factory()->create(['region_id' => $regionB->id]);

    $regionAdminA = User::factory()->regionAdmin()->create(['region_id' => $regionA->id]);
    $userB = User::factory()->branchAdmin()->create(['branch_id' => $branchB->id]);

    $this->actingAs($regionAdminA)->postJson("/api/v1/users/{$userB->id}/deactivate")->assertStatus(403);
});
