<?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();
});

// ===========================================
// Happy Path Tests
// ===========================================

test('admin can view timeline creation form', function () {
    $this->actingAs($this->admin)
        ->get(route('admin.timelines.create'))
        ->assertOk();
});

test('admin can search clients by name', function () {
    $client = User::factory()->individual()->create(['full_name' => 'John Doe']);
    User::factory()->individual()->create(['full_name' => 'Jane Smith']);

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

    $component = Volt::test('admin.timelines.create')
        ->set('search', 'John');

    expect($component->get('clients'))->toHaveCount(1);
    expect($component->get('clients')->first()->full_name)->toBe('John Doe');
});

test('admin can search clients by email', function () {
    $client = User::factory()->individual()->create([
        'full_name' => 'John Doe',
        'email' => 'john@example.com',
    ]);
    User::factory()->individual()->create([
        'full_name' => 'Jane Smith',
        'email' => 'jane@example.com',
    ]);

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

    $component = Volt::test('admin.timelines.create')
        ->set('search', 'john@');

    expect($component->get('clients'))->toHaveCount(1);
    expect($component->get('clients')->first()->email)->toBe('john@example.com');
});

test('admin can create timeline with required fields', function () {
    $client = User::factory()->individual()->create();

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

    Volt::test('admin.timelines.create')
        ->set('selectedUserId', $client->id)
        ->call('selectUser', $client->id)
        ->set('caseName', 'Test Case')
        ->call('create')
        ->assertHasNoErrors()
        ->assertRedirect();

    expect(Timeline::where('case_name', 'Test Case')->exists())->toBeTrue();

    $timeline = Timeline::where('case_name', 'Test Case')->first();
    expect($timeline->user_id)->toBe($client->id);
    expect($timeline->status)->toBe(TimelineStatus::Active);
    expect($timeline->case_reference)->toBeNull();
});

test('admin can create timeline with case reference', function () {
    $client = User::factory()->individual()->create();

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

    Volt::test('admin.timelines.create')
        ->set('selectedUserId', $client->id)
        ->call('selectUser', $client->id)
        ->set('caseName', 'Test Case')
        ->set('caseReference', 'REF-001')
        ->call('create')
        ->assertHasNoErrors();

    $timeline = Timeline::where('case_name', 'Test Case')->first();
    expect($timeline->case_reference)->toBe('REF-001');
});

test('initial notes creates first timeline update', function () {
    $client = User::factory()->individual()->create();

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

    Volt::test('admin.timelines.create')
        ->set('selectedUserId', $client->id)
        ->call('selectUser', $client->id)
        ->set('caseName', 'Test Case')
        ->set('initialNotes', 'Initial case notes here')
        ->call('create')
        ->assertHasNoErrors();

    $timeline = Timeline::where('case_name', 'Test Case')->first();
    expect($timeline->updates)->toHaveCount(1);

    $update = $timeline->updates->first();
    expect($update->update_text)->toBe('Initial case notes here');
    expect($update->admin_id)->toBe($this->admin->id);
});

test('audit log created on timeline creation', function () {
    $client = User::factory()->individual()->create();

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

    Volt::test('admin.timelines.create')
        ->set('selectedUserId', $client->id)
        ->call('selectUser', $client->id)
        ->set('caseName', 'Test Case')
        ->call('create')
        ->assertHasNoErrors();

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

// ===========================================
// Validation Tests
// ===========================================

test('case name is required', function () {
    $client = User::factory()->individual()->create();

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

    Volt::test('admin.timelines.create')
        ->set('selectedUserId', $client->id)
        ->call('selectUser', $client->id)
        ->set('caseName', '')
        ->call('create')
        ->assertHasErrors(['caseName' => 'required']);
});

test('case reference must be unique', function () {
    $client = User::factory()->individual()->create();
    Timeline::factory()->create(['case_reference' => 'REF-001']);

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

    Volt::test('admin.timelines.create')
        ->set('selectedUserId', $client->id)
        ->call('selectUser', $client->id)
        ->set('caseName', 'Test Case')
        ->set('caseReference', 'REF-001')
        ->call('create')
        ->assertHasErrors(['caseReference' => 'unique']);
});

test('case reference allows multiple nulls', function () {
    $client = User::factory()->individual()->create();

    // Create a timeline without case_reference
    Timeline::factory()->create([
        'user_id' => $client->id,
        'case_reference' => null,
    ]);

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

    // Creating another timeline without case_reference should succeed
    Volt::test('admin.timelines.create')
        ->set('selectedUserId', $client->id)
        ->call('selectUser', $client->id)
        ->set('caseName', 'Test Case')
        ->set('caseReference', '')
        ->call('create')
        ->assertHasNoErrors();

    expect(Timeline::where('user_id', $client->id)->whereNull('case_reference')->count())->toBe(2);
});

test('client selection is required', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.timelines.create')
        ->set('caseName', 'Test Case')
        ->call('create')
        ->assertHasErrors(['selectedUserId' => 'required']);
});

test('selected client must exist', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.timelines.create')
        ->set('selectedUserId', 99999)
        ->set('caseName', 'Test Case')
        ->call('create')
        ->assertHasErrors(['selectedUserId' => 'exists']);
});

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

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

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

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

// ===========================================
// Edge Case Tests
// ===========================================

test('search only returns individual and company users', function () {
    $individualClient = User::factory()->individual()->create(['full_name' => 'Individual Client']);
    $companyClient = User::factory()->company()->create(['full_name' => 'Company Client']);
    $adminUser = User::factory()->admin()->create(['full_name' => 'Admin User']);

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

    $component = Volt::test('admin.timelines.create')
        ->set('search', 'Client');

    $clientNames = $component->get('clients')->pluck('full_name')->toArray();

    expect($clientNames)->toContain('Individual Client');
    expect($clientNames)->toContain('Company Client');
    expect($clientNames)->not->toContain('Admin User');
});

test('search only returns active users', function () {
    $activeClient = User::factory()->individual()->create(['full_name' => 'Active Client']);
    $deactivatedClient = User::factory()->individual()->deactivated()->create(['full_name' => 'Deactivated Client']);

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

    $component = Volt::test('admin.timelines.create')
        ->set('search', 'Client');

    $clientNames = $component->get('clients')->pluck('full_name')->toArray();

    expect($clientNames)->toContain('Active Client');
    expect($clientNames)->not->toContain('Deactivated Client');
});

test('can create multiple timelines for same client', function () {
    $client = User::factory()->individual()->create();

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

    // Create first timeline
    Volt::test('admin.timelines.create')
        ->set('selectedUserId', $client->id)
        ->call('selectUser', $client->id)
        ->set('caseName', 'First Case')
        ->call('create')
        ->assertHasNoErrors();

    // Create second timeline for same client
    Volt::test('admin.timelines.create')
        ->set('selectedUserId', $client->id)
        ->call('selectUser', $client->id)
        ->set('caseName', 'Second Case')
        ->call('create')
        ->assertHasNoErrors();

    expect(Timeline::where('user_id', $client->id)->count())->toBe(2);
});

// ===========================================
// Additional Tests
// ===========================================

test('search requires at least 2 characters', function () {
    User::factory()->individual()->create(['full_name' => 'John Doe']);

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

    $component = Volt::test('admin.timelines.create')
        ->set('search', 'J');

    expect($component->get('clients'))->toHaveCount(0);

    $component->set('search', 'Jo');
    expect($component->get('clients'))->toHaveCount(1);
});

test('selecting user sets search to user name', function () {
    $client = User::factory()->individual()->create(['full_name' => 'John Doe']);

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

    $component = Volt::test('admin.timelines.create')
        ->set('search', 'John')
        ->call('selectUser', $client->id);

    expect($component->get('selectedUserId'))->toBe($client->id);
    expect($component->get('search'))->toBe('John Doe');
});

test('clearing selection resets user and search', function () {
    $client = User::factory()->individual()->create(['full_name' => 'John Doe']);

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

    $component = Volt::test('admin.timelines.create')
        ->call('selectUser', $client->id)
        ->call('clearSelection');

    expect($component->get('selectedUserId'))->toBeNull();
    expect($component->get('selectedUser'))->toBeNull();
    expect($component->get('search'))->toBe('');
});

test('timeline without initial notes has no updates', function () {
    $client = User::factory()->individual()->create();

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

    Volt::test('admin.timelines.create')
        ->set('selectedUserId', $client->id)
        ->call('selectUser', $client->id)
        ->set('caseName', 'Test Case')
        ->set('initialNotes', '')
        ->call('create')
        ->assertHasNoErrors();

    $timeline = Timeline::where('case_name', 'Test Case')->first();
    expect($timeline->updates)->toHaveCount(0);
});

test('timeline status defaults to active', function () {
    $client = User::factory()->individual()->create();

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

    Volt::test('admin.timelines.create')
        ->set('selectedUserId', $client->id)
        ->call('selectUser', $client->id)
        ->set('caseName', 'Test Case')
        ->call('create')
        ->assertHasNoErrors();

    $timeline = Timeline::where('case_name', 'Test Case')->first();
    expect($timeline->status)->toBe(TimelineStatus::Active);
});
