<?php

use App\Enums\DeclarationStatus;
use App\Models\Client;
use App\Models\Declaration;
use App\Models\User;
use App\Models\Workspace;

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

    return [$user, $workspace, $client];
}

test('owner sees workspace-wide activity in activities prop', function () {
    [$owner, $workspace, $client] = setupActivityWorkspace('owner');

    $otherUser = User::factory()->create();
    $workspace->users()->attach($otherUser->id, ['role' => 'worker']);

    // Act as owner BEFORE creating declaration so Spatie logs the causer
    $this->actingAs($owner);

    Declaration::factory()->create([
        'workspace_id' => $workspace->id,
        'client_id' => $client->id,
        'assigned_to' => $otherUser->id,
        'status' => DeclarationStatus::EnCours,
        'due_date' => now()->addDays(10),
    ]);

    $response = $this->get(route('dashboard'));

    $response->assertOk();
    $response->assertInertia(fn ($page) => $page
        ->component('Dashboard')
        ->has('activities')
        ->where('activities.0.actorName', $owner->name)
    );
});

test('worker sees only activity related to their assigned declarations', function () {
    [$worker, $workspace, $client] = setupActivityWorkspace('worker');

    $otherWorker = User::factory()->create();
    $workspace->users()->attach($otherWorker->id, ['role' => 'worker']);

    // Declaration assigned to THIS worker — should appear in feed
    $assignedDeclaration = Declaration::factory()->create([
        'workspace_id' => $workspace->id,
        'client_id' => $client->id,
        'assigned_to' => $worker->id,
        'status' => DeclarationStatus::EnCours,
        'due_date' => now()->addDays(10),
    ]);

    // Declaration assigned to OTHER worker — should NOT appear
    Declaration::factory()->create([
        'workspace_id' => $workspace->id,
        'client_id' => $client->id,
        'assigned_to' => $otherWorker->id,
        'status' => DeclarationStatus::EnCours,
        'due_date' => now()->addDays(5),
    ]);

    $this->actingAs($worker);
    $response = $this->get(route('dashboard'));

    $response->assertOk();
    $response->assertInertia(fn ($page) => $page
        ->component('Dashboard')
        ->has('activities')
    );

    // Verify the worker only sees activities for their own declarations
    $activitiesData = $response->original->getData()['page']['props']['activities'];
    expect(count($activitiesData))->toBeGreaterThan(0);

    // All activities should relate to the worker's assigned client
    collect($activitiesData)->each(function ($a) use ($client) {
        expect($a['description'])->toContain($client->company_name);
    });
});

test('activity entries contain expected fields', function () {
    [$owner, $workspace, $client] = setupActivityWorkspace('owner');

    Declaration::factory()->create([
        'workspace_id' => $workspace->id,
        'client_id' => $client->id,
        'assigned_to' => $owner->id,
        'status' => DeclarationStatus::EnCours,
        'due_date' => now()->addDays(10),
    ]);

    $this->actingAs($owner);
    $response = $this->get(route('dashboard'));

    $response->assertOk();
    $response->assertInertia(fn ($page) => $page
        ->component('Dashboard')
        ->has('activities.0', fn ($activity) => $activity
            ->has('id')
            ->has('actorName')
            ->has('actorInitials')
            ->has('description')
            ->has('targetUrl')
            ->has('targetLabel')
            ->has('timestamp')
            ->has('eventType')
        )
    );
});

test('feed is limited to 20 most recent events', function () {
    [$owner, $workspace, $client] = setupActivityWorkspace('owner');

    // Create 25 declarations to generate 25 activity log entries
    for ($i = 0; $i < 25; $i++) {
        Declaration::factory()->create([
            'workspace_id' => $workspace->id,
            'client_id' => $client->id,
            'assigned_to' => $owner->id,
            'status' => DeclarationStatus::EnCours,
            'due_date' => now()->addDays($i + 1),
        ]);
    }

    $this->actingAs($owner);
    $response = $this->get(route('dashboard'));

    $response->assertOk();
    $activitiesData = $response->original->getData()['page']['props']['activities'];
    expect(count($activitiesData))->toBeLessThanOrEqual(20);
});

test('empty activity returns empty array', function () {
    $user = User::factory()->create();
    $workspace = Workspace::factory()->create();
    $workspace->users()->attach($user->id, ['role' => 'owner']);
    session(['current_workspace_id' => $workspace->id]);

    // No declarations or activity created

    $this->actingAs($user);
    $response = $this->get(route('dashboard'));

    $response->assertOk();
    $response->assertInertia(fn ($page) => $page
        ->component('Dashboard')
        ->where('activities', [])
    );
});

test('activity with deleted subject does not cause errors', function () {
    [$owner, $workspace, $client] = setupActivityWorkspace('owner');

    // Create a declaration (logs activity), then soft-delete it
    $declaration = Declaration::factory()->create([
        'workspace_id' => $workspace->id,
        'client_id' => $client->id,
        'assigned_to' => $owner->id,
        'status' => DeclarationStatus::EnCours,
        'due_date' => now()->addDays(10),
    ]);

    $declaration->delete();

    $this->actingAs($owner);
    $response = $this->get(route('dashboard'));

    $response->assertOk();
    $response->assertInertia(fn ($page) => $page
        ->component('Dashboard')
        ->has('activities')
    );
});

test('manager sees workspace-wide activity same as owner', function () {
    [$manager, $workspace, $client] = setupActivityWorkspace('manager');

    $worker = User::factory()->create();
    $workspace->users()->attach($worker->id, ['role' => 'worker']);

    // Create a declaration by the worker
    $this->actingAs($worker);
    Declaration::factory()->create([
        'workspace_id' => $workspace->id,
        'client_id' => $client->id,
        'assigned_to' => $worker->id,
        'status' => DeclarationStatus::EnCours,
        'due_date' => now()->addDays(10),
    ]);

    $this->actingAs($manager);
    $response = $this->get(route('dashboard'));

    $response->assertOk();
    $response->assertInertia(fn ($page) => $page
        ->component('Dashboard')
        ->has('activities')
    );

    $activitiesData = $response->original->getData()['page']['props']['activities'];
    expect(count($activitiesData))->toBeGreaterThan(0);
});
