<?php

use App\Enums\WorkspaceUserRole;
use App\Models\Client;
use App\Models\Declaration;
use App\Models\User;
use App\Models\Workspace;
use Inertia\Testing\AssertableInertia as Assert;

function setupClientTestUser(string $role, array $permissions = []): array
{
    $user = User::factory()->create();
    $workspace = Workspace::factory()->create();
    $workspace->users()->attach($user->id, [
        'role' => $role,
        'permissions' => $permissions,
    ]);
    session(['current_workspace_id' => $workspace->id]);

    return [$user, $workspace];
}

// AC #1: Workers see only clients with assigned declarations
test('worker sees only clients with assigned declarations in index', function () {
    [$worker, $workspace] = setupClientTestUser(WorkspaceUserRole::Worker);

    $clientWithAssignment = Client::factory()->create(['workspace_id' => $workspace->id]);
    $clientWithoutAssignment = Client::factory()->create(['workspace_id' => $workspace->id]);

    Declaration::factory()->create([
        'workspace_id' => $workspace->id,
        'client_id' => $clientWithAssignment->id,
        'assigned_to' => $worker->id,
    ]);

    Declaration::factory()->create([
        'workspace_id' => $workspace->id,
        'client_id' => $clientWithoutAssignment->id,
        'assigned_to' => null,
    ]);

    $response = $this->actingAs($worker)->get(route('clients.index'));

    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->component('clients/Index')
        ->has('clients.data', 1)
        ->where('clients.data.0.id', $clientWithAssignment->id)
    );
});

// AC #3: Owners see all workspace clients
test('owner sees all workspace clients in index', function () {
    [$owner, $workspace] = setupClientTestUser(WorkspaceUserRole::Owner);

    Client::factory()->count(3)->create(['workspace_id' => $workspace->id]);

    $response = $this->actingAs($owner)->get(route('clients.index'));

    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->component('clients/Index')
        ->has('clients.data', 3)
    );
});

// AC #3: Managers see all workspace clients
test('manager sees all workspace clients in index', function () {
    [$manager, $workspace] = setupClientTestUser(WorkspaceUserRole::Manager);

    Client::factory()->count(3)->create(['workspace_id' => $workspace->id]);

    $response = $this->actingAs($manager)->get(route('clients.index'));

    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->component('clients/Index')
        ->has('clients.data', 3)
    );
});

// AC #5: Worker gets 404 accessing client with no assigned declarations
test('worker gets 404 accessing client with no assigned declarations', function () {
    [$worker, $workspace] = setupClientTestUser(WorkspaceUserRole::Worker);

    $client = Client::factory()->create(['workspace_id' => $workspace->id]);

    // No declarations assigned to this worker for this client
    Declaration::factory()->create([
        'workspace_id' => $workspace->id,
        'client_id' => $client->id,
        'assigned_to' => null,
    ]);

    $response = $this->actingAs($worker)->get(route('clients.show', $client));

    $response->assertNotFound();
});

// Worker can access client show when they have assigned declarations
test('worker can access client show when they have assigned declarations', function () {
    [$worker, $workspace] = setupClientTestUser(WorkspaceUserRole::Worker);

    $client = Client::factory()->create(['workspace_id' => $workspace->id]);

    Declaration::factory()->create([
        'workspace_id' => $workspace->id,
        'client_id' => $client->id,
        'assigned_to' => $worker->id,
    ]);

    $response = $this->actingAs($worker)->get(route('clients.show', $client));

    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->component('clients/Show')
    );
});

// AC #6: Worker gets 404 on create
test('worker gets 404 on client create', function () {
    [$worker, $workspace] = setupClientTestUser(WorkspaceUserRole::Worker);

    $response = $this->actingAs($worker)->get(route('clients.create'));

    $response->assertNotFound();
});

// AC #6: Worker gets 404 on store
test('worker gets 404 on client store', function () {
    [$worker, $workspace] = setupClientTestUser(WorkspaceUserRole::Worker);

    $response = $this->actingAs($worker)->post(route('clients.store'), [
        'company_name' => 'Test',
        'legal_form' => 'sarl',
        'contacts' => [['full_name' => 'Test', 'is_principal' => true]],
    ]);

    $response->assertNotFound();
});

// AC #6: Worker gets 404 on edit
test('worker gets 404 on client edit', function () {
    [$worker, $workspace] = setupClientTestUser(WorkspaceUserRole::Worker);

    $client = Client::factory()->create(['workspace_id' => $workspace->id]);

    $response = $this->actingAs($worker)->get(route('clients.edit', $client));

    $response->assertNotFound();
});

// AC #6: Worker gets 404 on update
test('worker gets 404 on client update', function () {
    [$worker, $workspace] = setupClientTestUser(WorkspaceUserRole::Worker);

    $client = Client::factory()->create(['workspace_id' => $workspace->id]);

    $response = $this->actingAs($worker)->put(route('clients.update', $client), [
        'company_name' => 'Updated',
        'legal_form' => 'sarl',
        'contacts' => [
            ['full_name' => 'Test Contact', 'is_principal' => true],
        ],
    ]);

    $response->assertNotFound();
});

// AC #6: Worker gets 404 on destroy
test('worker gets 404 on client destroy', function () {
    [$worker, $workspace] = setupClientTestUser(WorkspaceUserRole::Worker);

    $client = Client::factory()->create(['workspace_id' => $workspace->id]);

    $response = $this->actingAs($worker)->delete(route('clients.destroy', $client));

    $response->assertNotFound();
});

// AC #3: Manager can access all CRUD operations
test('manager can access all client CRUD operations', function () {
    [$manager, $workspace] = setupClientTestUser(WorkspaceUserRole::Manager);

    $client = Client::factory()->create(['workspace_id' => $workspace->id]);

    // Index
    $this->actingAs($manager)->get(route('clients.index'))->assertOk();

    // Show
    $this->actingAs($manager)->get(route('clients.show', $client))->assertOk();

    // Create page
    $this->actingAs($manager)->get(route('clients.create'))->assertOk();

    // Edit page
    $this->actingAs($manager)->get(route('clients.edit', $client))->assertOk();
});

// AC #3: Owner can access all CRUD operations
test('owner can access all client CRUD operations', function () {
    [$owner, $workspace] = setupClientTestUser(WorkspaceUserRole::Owner);

    $client = Client::factory()->create(['workspace_id' => $workspace->id]);

    // Index
    $this->actingAs($owner)->get(route('clients.index'))->assertOk();

    // Show
    $this->actingAs($owner)->get(route('clients.show', $client))->assertOk();

    // Create page
    $this->actingAs($owner)->get(route('clients.create'))->assertOk();

    // Edit page
    $this->actingAs($owner)->get(route('clients.edit', $client))->assertOk();
});

// AC #10: canCreate/canEdit/canDelete props are false for Workers
test('worker gets canCreate canEdit canDelete as false in index', function () {
    [$worker, $workspace] = setupClientTestUser(WorkspaceUserRole::Worker);

    $response = $this->actingAs($worker)->get(route('clients.index'));

    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->where('canCreate', false)
        ->where('canEdit', false)
        ->where('canDelete', false)
    );
});

// AC #10: canCreate/canEdit/canDelete props are true for Owners
test('owner gets canCreate canEdit canDelete as true in index', function () {
    [$owner, $workspace] = setupClientTestUser(WorkspaceUserRole::Owner);

    $response = $this->actingAs($owner)->get(route('clients.index'));

    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->where('canCreate', true)
        ->where('canEdit', true)
        ->where('canDelete', true)
    );
});
