<?php

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

beforeEach(function () {
    $this->admin = User::factory()->admin()->create();
    $this->client = User::factory()->individual()->create();
    $this->timeline = Timeline::factory()->create(['user_id' => $this->client->id]);
});

// ===========================================
// Archive Timeline Tests
// ===========================================

test('admin can archive active timeline', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
        ->call('archive')
        ->assertHasNoErrors();

    expect($this->timeline->fresh()->isArchived())->toBeTrue();
});

test('admin can unarchive archived timeline', function () {
    $archivedTimeline = Timeline::factory()->archived()->create(['user_id' => $this->client->id]);

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

    Volt::test('admin.timelines.show', ['timeline' => $archivedTimeline])
        ->call('unarchive')
        ->assertHasNoErrors();

    expect($archivedTimeline->fresh()->isActive())->toBeTrue();
});

test('archiving archived timeline is noop', function () {
    $archivedTimeline = Timeline::factory()->archived()->create(['user_id' => $this->client->id]);

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

    $initialLogCount = AdminLog::count();

    Volt::test('admin.timelines.show', ['timeline' => $archivedTimeline])
        ->call('archive')
        ->assertHasNoErrors();

    // Status should remain archived
    expect($archivedTimeline->fresh()->isArchived())->toBeTrue();
    // No additional log entry should be created
    expect(AdminLog::count())->toBe($initialLogCount);
});

test('unarchiving active timeline is noop', function () {
    $this->actingAs($this->admin);

    $initialLogCount = AdminLog::count();

    Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
        ->call('unarchive')
        ->assertHasNoErrors();

    // Status should remain active
    expect($this->timeline->fresh()->isActive())->toBeTrue();
    // No additional log entry should be created
    expect(AdminLog::count())->toBe($initialLogCount);
});

test('cannot add update to archived timeline', function () {
    $archivedTimeline = Timeline::factory()->archived()->create(['user_id' => $this->client->id]);

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

    Volt::test('admin.timelines.show', ['timeline' => $archivedTimeline])
        ->set('updateText', 'This should not be added to archived timeline.')
        ->call('addUpdate');

    expect($archivedTimeline->updates()->count())->toBe(0);
});

// ===========================================
// Audit Log Tests
// ===========================================

test('audit log created on archive', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
        ->call('archive')
        ->assertHasNoErrors();

    expect(AdminLog::where('action', 'archive')
        ->where('target_type', 'timeline')
        ->where('target_id', $this->timeline->id)
        ->where('admin_id', $this->admin->id)
        ->exists())->toBeTrue();
});

test('audit log created on unarchive', function () {
    $archivedTimeline = Timeline::factory()->archived()->create(['user_id' => $this->client->id]);

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

    Volt::test('admin.timelines.show', ['timeline' => $archivedTimeline])
        ->call('unarchive')
        ->assertHasNoErrors();

    expect(AdminLog::where('action', 'unarchive')
        ->where('target_type', 'timeline')
        ->where('target_id', $archivedTimeline->id)
        ->where('admin_id', $this->admin->id)
        ->exists())->toBeTrue();
});

// ===========================================
// Authorization Tests
// ===========================================

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

test('client cannot archive timeline', function () {
    $this->actingAs($this->client)
        ->get(route('admin.timelines.show', $this->timeline))
        ->assertForbidden();
});

// ===========================================
// Visual Indicator Tests
// ===========================================

test('archived timeline shows visual indicator', function () {
    $archivedTimeline = Timeline::factory()->archived()->create(['user_id' => $this->client->id]);

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

    Volt::test('admin.timelines.show', ['timeline' => $archivedTimeline])
        ->assertSee(__('enums.timeline_status.archived'));
});

test('update form disabled on archived timeline', function () {
    $archivedTimeline = Timeline::factory()->archived()->create(['user_id' => $this->client->id]);

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

    Volt::test('admin.timelines.show', ['timeline' => $archivedTimeline])
        ->assertSee(__('timelines.archived_notice'));
});

// ===========================================
// Model Method Tests
// ===========================================

test('timeline isArchived returns true for archived timeline', function () {
    $archivedTimeline = Timeline::factory()->archived()->create(['user_id' => $this->client->id]);

    expect($archivedTimeline->isArchived())->toBeTrue();
    expect($archivedTimeline->isActive())->toBeFalse();
});

test('timeline isActive returns true for active timeline', function () {
    expect($this->timeline->isActive())->toBeTrue();
    expect($this->timeline->isArchived())->toBeFalse();
});

test('scopeActive returns only active timelines', function () {
    Timeline::factory()->archived()->create(['user_id' => $this->client->id]);
    Timeline::factory()->archived()->create(['user_id' => $this->client->id]);

    $activeTimelines = Timeline::active()->get();

    expect($activeTimelines->count())->toBe(1);
    expect($activeTimelines->first()->id)->toBe($this->timeline->id);
});

test('scopeArchived returns only archived timelines', function () {
    $archived1 = Timeline::factory()->archived()->create(['user_id' => $this->client->id]);
    $archived2 = Timeline::factory()->archived()->create(['user_id' => $this->client->id]);

    $archivedTimelines = Timeline::archived()->get();

    expect($archivedTimelines->count())->toBe(2);
    expect($archivedTimelines->pluck('id')->toArray())->toContain($archived1->id, $archived2->id);
});

test('archive method changes status to archived', function () {
    expect($this->timeline->status)->toBe(TimelineStatus::Active);

    $this->timeline->archive();

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

test('unarchive method changes status to active', function () {
    $archivedTimeline = Timeline::factory()->archived()->create(['user_id' => $this->client->id]);

    expect($archivedTimeline->status)->toBe(TimelineStatus::Archived);

    $archivedTimeline->unarchive();

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