<?php

use App\Enums\TimelineStatus;
use App\Models\Timeline;
use App\Models\TimelineUpdate;
use App\Models\User;
use Livewire\Volt\Volt;

beforeEach(function () {
    $this->admin = User::factory()->admin()->create();
});

// ===========================================
// Route Access Tests
// ===========================================

test('admin can view timeline dashboard', function () {
    Timeline::factory()->count(5)->create();

    $this->actingAs($this->admin)
        ->get(route('admin.timelines.index'))
        ->assertOk()
        ->assertSeeLivewire('admin.timelines.index');
});

test('non-admin cannot access timeline dashboard', function () {
    $client = User::factory()->individual()->create();

    $this->actingAs($client)
        ->get(route('admin.timelines.index'))
        ->assertForbidden();
});

test('guest cannot access timeline dashboard', function () {
    $this->get(route('admin.timelines.index'))
        ->assertRedirect(route('login'));
});

// ===========================================
// List View Tests
// ===========================================

test('timeline dashboard displays all timelines with correct data', function () {
    $client = User::factory()->individual()->create(['full_name' => 'Test Client']);
    $timeline = Timeline::factory()->create([
        'user_id' => $client->id,
        'case_name' => 'Test Case Name',
    ]);

    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->assertSee('Test Case Name')
        ->assertSee('Test Client');
});

test('dashboard shows empty state when no timelines exist', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->assertSee(__('timelines.no_timelines'));
});

test('dashboard displays timeline status correctly', function () {
    $activeTimeline = Timeline::factory()->active()->create(['case_name' => 'Active Case']);
    $archivedTimeline = Timeline::factory()->archived()->create(['case_name' => 'Archived Case']);

    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->assertSee('Active Case')
        ->assertSee('Archived Case')
        ->assertSee(__('enums.timeline_status.active'))
        ->assertSee(__('enums.timeline_status.archived'));
});

test('dashboard displays update count', function () {
    $timeline = Timeline::factory()->create();
    TimelineUpdate::factory()->count(3)->create(['timeline_id' => $timeline->id]);

    $this->actingAs($this->admin);

    $component = Volt::test('admin.timelines.index');

    // The component should have the timeline with 3 updates
    $timelines = $component->viewData('timelines');
    expect($timelines->first()->updates_count)->toBe(3);
});

// ===========================================
// Filtering Tests
// ===========================================

test('can filter timelines by status', function () {
    Timeline::factory()->active()->create(['case_name' => 'Active Case']);
    Timeline::factory()->archived()->create(['case_name' => 'Archived Case']);

    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->set('statusFilter', 'active')
        ->assertSee('Active Case')
        ->assertDontSee('Archived Case');
});

test('can filter timelines by client', function () {
    $client1 = User::factory()->individual()->create(['full_name' => 'Client One']);
    $client2 = User::factory()->individual()->create(['full_name' => 'Client Two']);
    Timeline::factory()->create(['user_id' => $client1->id, 'case_name' => 'Client1 Case']);
    Timeline::factory()->create(['user_id' => $client2->id, 'case_name' => 'Client2 Case']);

    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->set('clientFilter', $client1->id)
        ->assertSee('Client1 Case')
        ->assertDontSee('Client2 Case');
});

test('can search timelines by case name', function () {
    Timeline::factory()->create(['case_name' => 'Contract Dispute']);
    Timeline::factory()->create(['case_name' => 'Property Issue']);

    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->set('search', 'Contract')
        ->assertSee('Contract Dispute')
        ->assertDontSee('Property Issue');
});

test('can search timelines by case reference', function () {
    Timeline::factory()->create(['case_reference' => 'REF-123', 'case_name' => 'Case A']);
    Timeline::factory()->create(['case_reference' => 'REF-456', 'case_name' => 'Case B']);

    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->set('search', 'REF-123')
        ->assertSee('Case A')
        ->assertDontSee('Case B');
});

test('can filter timelines by date range', function () {
    $oldTimeline = Timeline::factory()->create([
        'case_name' => 'Old Case',
        'created_at' => now()->subDays(30),
    ]);
    $newTimeline = Timeline::factory()->create([
        'case_name' => 'New Case',
        'created_at' => now(),
    ]);

    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->set('dateFrom', now()->subDays(5)->format('Y-m-d'))
        ->assertSee('New Case')
        ->assertDontSee('Old Case');
});

test('clear filters resets all filter values', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->set('search', 'test')
        ->set('statusFilter', 'active')
        ->set('clientFilter', '1')
        ->set('dateFrom', '2024-01-01')
        ->set('dateTo', '2024-12-31')
        ->call('clearFilters')
        ->assertSet('search', '')
        ->assertSet('statusFilter', '')
        ->assertSet('clientFilter', '')
        ->assertSet('dateFrom', '')
        ->assertSet('dateTo', '');
});

test('shows no results message when filters return empty', function () {
    Timeline::factory()->create(['case_name' => 'Existing Case']);

    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->set('search', 'NonexistentCase')
        ->assertSee(__('timelines.no_timelines'));
});

// ===========================================
// Sorting Tests
// ===========================================

test('can sort timelines by case name', function () {
    Timeline::factory()->create(['case_name' => 'Zebra Case']);
    Timeline::factory()->create(['case_name' => 'Alpha Case']);

    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->call('sort', 'case_name')
        ->assertSet('sortBy', 'case_name')
        ->assertSet('sortDir', 'asc');
});

test('clicking same sort column toggles direction', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->call('sort', 'case_name')
        ->assertSet('sortDir', 'asc')
        ->call('sort', 'case_name')
        ->assertSet('sortDir', 'desc');
});

test('can sort timelines by updated_at', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->call('sort', 'updated_at')
        ->assertSet('sortBy', 'updated_at')
        ->assertSet('sortDir', 'asc');
});

test('can sort timelines by created_at', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->call('sort', 'created_at')
        ->assertSet('sortBy', 'created_at')
        ->assertSet('sortDir', 'asc');
});

test('can sort timelines by client', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->call('sort', 'user_id')
        ->assertSet('sortBy', 'user_id')
        ->assertSet('sortDir', 'asc');
});

test('default sort is by updated_at desc', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->assertSet('sortBy', 'updated_at')
        ->assertSet('sortDir', 'desc');
});

// ===========================================
// Quick Actions Tests
// ===========================================

test('can archive timeline from dashboard', function () {
    $timeline = Timeline::factory()->active()->create();

    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->call('toggleArchive', $timeline->id);

    expect($timeline->fresh()->status)->toBe(TimelineStatus::Archived);
});

test('can unarchive timeline from dashboard', function () {
    $timeline = Timeline::factory()->archived()->create();

    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->call('toggleArchive', $timeline->id);

    expect($timeline->fresh()->status)->toBe(TimelineStatus::Active);
});

test('toggle archive creates admin log entry for archive', function () {
    $timeline = Timeline::factory()->active()->create();

    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->call('toggleArchive', $timeline->id);

    $this->assertDatabaseHas('admin_logs', [
        'admin_id' => $this->admin->id,
        'action' => 'archive',
        'target_type' => 'timeline',
        'target_id' => $timeline->id,
    ]);
});

test('toggle archive creates admin log entry for unarchive', function () {
    $timeline = Timeline::factory()->archived()->create();

    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->call('toggleArchive', $timeline->id);

    $this->assertDatabaseHas('admin_logs', [
        'admin_id' => $this->admin->id,
        'action' => 'unarchive',
        'target_type' => 'timeline',
        'target_id' => $timeline->id,
    ]);
});

// ===========================================
// Pagination Tests
// ===========================================

test('pagination displays correct number of items', function () {
    Timeline::factory()->count(20)->create();

    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->assertSet('perPage', 15);
});

test('can change items per page', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.timelines.index')
        ->set('perPage', 25)
        ->assertSet('perPage', 25);
});

test('changing per page resets pagination', function () {
    Timeline::factory()->count(30)->create();

    $this->actingAs($this->admin);

    // Navigate to page 2, then change perPage
    $component = Volt::test('admin.timelines.index');

    // Simulate being on page 2 then changing perPage
    $component->set('perPage', 50);

    // After changing perPage, page should reset
    $timelines = $component->viewData('timelines');
    expect($timelines->currentPage())->toBe(1);
});

// ===========================================
// Eager Loading Tests
// ===========================================

test('dashboard uses eager loading to prevent N+1 queries', function () {
    // Create 10 timelines with updates
    $timelines = Timeline::factory()->count(10)->create();
    foreach ($timelines as $timeline) {
        TimelineUpdate::factory()->count(3)->create(['timeline_id' => $timeline->id]);
    }

    $this->actingAs($this->admin);

    // This test verifies the component loads without errors
    // The eager loading is verified by checking the query includes relationships
    Volt::test('admin.timelines.index')
        ->assertHasNoErrors();

    // Verify that timelines have their relationships loaded
    $component = Volt::test('admin.timelines.index');
    $loadedTimelines = $component->viewData('timelines');

    foreach ($loadedTimelines as $timeline) {
        // These relationships should be already loaded (not lazy loaded)
        expect($timeline->relationLoaded('user'))->toBeTrue();
        expect($timeline->relationLoaded('updates'))->toBeTrue();
    }
});

// ===========================================
// Filter Reset on Search Tests
// ===========================================

test('updating search resets pagination', function () {
    Timeline::factory()->count(20)->create();

    $this->actingAs($this->admin);

    $component = Volt::test('admin.timelines.index');

    // Change search should reset page
    $component->set('search', 'test');

    $timelines = $component->viewData('timelines');
    expect($timelines->currentPage())->toBe(1);
});

test('updating status filter resets pagination', function () {
    Timeline::factory()->count(20)->create();

    $this->actingAs($this->admin);

    $component = Volt::test('admin.timelines.index');

    $component->set('statusFilter', 'active');

    $timelines = $component->viewData('timelines');
    expect($timelines->currentPage())->toBe(1);
});

test('updating client filter resets pagination', function () {
    $client = User::factory()->individual()->create();
    Timeline::factory()->count(20)->create(['user_id' => $client->id]);

    $this->actingAs($this->admin);

    $component = Volt::test('admin.timelines.index');

    $component->set('clientFilter', $client->id);

    $timelines = $component->viewData('timelines');
    expect($timelines->currentPage())->toBe(1);
});

// ===========================================
// Client List Tests
// ===========================================

test('client filter only shows clients with timelines', function () {
    $clientWithTimeline = User::factory()->individual()->create(['full_name' => 'Has Timeline']);
    $clientWithoutTimeline = User::factory()->individual()->create(['full_name' => 'No Timeline']);

    Timeline::factory()->create(['user_id' => $clientWithTimeline->id]);

    $this->actingAs($this->admin);

    $component = Volt::test('admin.timelines.index');
    $clients = $component->viewData('clients');

    expect($clients->pluck('id')->toArray())->toContain($clientWithTimeline->id);
    expect($clients->pluck('id')->toArray())->not->toContain($clientWithoutTimeline->id);
});
