<?php

use App\Enums\ConsultationStatus;
use App\Models\BlockedTime;
use App\Models\Consultation;
use App\Models\Timeline;
use App\Models\TimelineUpdate;
use App\Models\User;
use Livewire\Volt\Volt;

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

// ===========================================
// Pending Bookings Widget Tests
// ===========================================

test('pending bookings widget displays pending count', function () {
    Consultation::factory()->count(3)->pending()->create();

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

    Volt::test('admin.widgets.pending-bookings')
        ->assertSee('3')
        ->assertSee(__('widgets.pending_bookings'));
});

test('pending bookings widget shows empty state when none pending', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.widgets.pending-bookings')
        ->assertSee(__('widgets.no_pending_bookings'));
});

test('pending bookings widget shows up to 5 bookings', function () {
    $clients = User::factory()->count(7)->individual()->create();

    foreach ($clients as $client) {
        Consultation::factory()->pending()->create([
            'user_id' => $client->id,
        ]);
    }

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

    $component = Volt::test('admin.widgets.pending-bookings');

    $pendingBookings = $component->viewData('pendingBookings');

    expect($pendingBookings)->toHaveCount(5);
    expect($component->viewData('pendingCount'))->toBe(7);
});

test('pending bookings widget shows view all link when more than 5', function () {
    Consultation::factory()->count(7)->pending()->create();

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

    Volt::test('admin.widgets.pending-bookings')
        ->assertSee(__('widgets.view_all_pending', ['count' => 7]));
});

test('pending bookings widget displays client name and consultation type', function () {
    $client = User::factory()->individual()->create(['full_name' => 'Test Client Name']);

    Consultation::factory()->pending()->free()->create([
        'user_id' => $client->id,
    ]);

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

    Volt::test('admin.widgets.pending-bookings')
        ->assertSee('Test Client Name');
});

test('pending bookings widget handles missing user relationship gracefully', function () {
    // The cascade delete means if user is deleted, consultation is deleted too
    // This test verifies that the widget at least doesn't crash with the optional chaining
    // by checking that it handles the view rendering without errors
    $client = User::factory()->individual()->create();
    $consultation = Consultation::factory()->pending()->create([
        'user_id' => $client->id,
    ]);

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

    // Widget should render successfully with the client name
    Volt::test('admin.widgets.pending-bookings')
        ->assertSee($client->full_name);
});

test('pending bookings widget shows badge count 99+ for large counts', function () {
    Consultation::factory()->count(105)->pending()->create();

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

    $component = Volt::test('admin.widgets.pending-bookings');

    expect($component->viewData('pendingCount'))->toBe(105);
});

// ===========================================
// Today's Schedule Widget Tests
// ===========================================

test('today schedule widget shows only today approved consultations', function () {
    $client = User::factory()->individual()->create(['full_name' => 'Today Client']);

    // Today's approved - should show
    Consultation::factory()->approved()->create([
        'user_id' => $client->id,
        'booking_date' => today(),
        'booking_time' => '10:00:00',
    ]);

    // Tomorrow's approved - should NOT show
    Consultation::factory()->approved()->create([
        'booking_date' => today()->addDay(),
    ]);

    // Today's pending - should NOT show
    Consultation::factory()->pending()->create([
        'booking_date' => today(),
    ]);

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

    $component = Volt::test('admin.widgets.todays-schedule');

    $todaySchedule = $component->viewData('todaySchedule');

    expect($todaySchedule)->toHaveCount(1);
    $component->assertSee('Today Client')
        ->assertSee('10:00 AM');
});

test('today schedule widget shows empty state when no consultations', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.widgets.todays-schedule')
        ->assertSee(__('widgets.no_consultations_today'));
});

test('admin can mark consultation as completed', function () {
    $consultation = Consultation::factory()->approved()->create([
        'booking_date' => today(),
    ]);

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

    Volt::test('admin.widgets.todays-schedule')
        ->call('markComplete', $consultation->id)
        ->assertHasNoErrors();

    expect($consultation->fresh()->status)->toBe(ConsultationStatus::Completed);
});

test('admin can mark consultation as no-show', function () {
    $consultation = Consultation::factory()->approved()->create([
        'booking_date' => today(),
    ]);

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

    Volt::test('admin.widgets.todays-schedule')
        ->call('markNoShow', $consultation->id)
        ->assertHasNoErrors();

    expect($consultation->fresh()->status)->toBe(ConsultationStatus::NoShow);
});

test('today schedule widget orders by time', function () {
    $client = User::factory()->individual()->create();

    Consultation::factory()->approved()->create([
        'user_id' => $client->id,
        'booking_date' => today(),
        'booking_time' => '14:00:00',
    ]);

    Consultation::factory()->approved()->create([
        'user_id' => $client->id,
        'booking_date' => today(),
        'booking_time' => '09:00:00',
    ]);

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

    $component = Volt::test('admin.widgets.todays-schedule');

    $todaySchedule = $component->viewData('todaySchedule');

    expect($todaySchedule->first()->booking_time)->toBe('09:00:00');
    expect($todaySchedule->last()->booking_time)->toBe('14:00:00');
});

// ===========================================
// Recent Timeline Updates Widget Tests
// ===========================================

test('recent updates widget shows last 5 updates', function () {
    $timeline = Timeline::factory()->create();
    TimelineUpdate::factory()->count(7)->create(['timeline_id' => $timeline->id]);

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

    $component = Volt::test('admin.widgets.recent-updates');

    $recentUpdates = $component->viewData('recentUpdates');

    expect($recentUpdates)->toHaveCount(5);
});

test('recent updates widget shows empty state when no updates', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.widgets.recent-updates')
        ->assertSee(__('widgets.no_recent_updates'));
});

test('recent updates widget displays case name and client name', function () {
    $client = User::factory()->individual()->create(['full_name' => 'Case Owner']);
    $timeline = Timeline::factory()->create([
        'user_id' => $client->id,
        'case_name' => 'Test Case Name',
    ]);
    TimelineUpdate::factory()->create([
        'timeline_id' => $timeline->id,
        'update_text' => 'This is a test update text',
    ]);

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

    Volt::test('admin.widgets.recent-updates')
        ->assertSee('Test Case Name')
        ->assertSee('Case Owner')
        ->assertSee('This is a test update text');
});

test('recent updates widget truncates long update text', function () {
    $timeline = Timeline::factory()->create();
    TimelineUpdate::factory()->create([
        'timeline_id' => $timeline->id,
        'update_text' => str_repeat('A', 100),
    ]);

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

    $component = Volt::test('admin.widgets.recent-updates');

    // Should show truncated text (50 chars)
    $component->assertDontSee(str_repeat('A', 100));
});

test('recent updates widget shows relative timestamp', function () {
    $timeline = Timeline::factory()->create();
    $update = TimelineUpdate::factory()->create([
        'timeline_id' => $timeline->id,
        'created_at' => now()->subHours(2),
    ]);

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

    $component = Volt::test('admin.widgets.recent-updates');

    // Check that the component has the update with a created_at timestamp
    $recentUpdates = $component->viewData('recentUpdates');

    // Verify the timestamp is correctly set (approximately 2 hours ago)
    expect($recentUpdates->first()->created_at->diffInHours(now()))->toBeGreaterThanOrEqual(2);
});

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

test('quick actions widget displays action buttons', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.widgets.quick-actions')
        ->assertSee(__('widgets.create_client'))
        ->assertSee(__('widgets.create_post'))
        ->assertSee(__('widgets.block_time_slot'));
});

test('admin can block a time slot', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.widgets.quick-actions')
        ->call('openBlockModal')
        ->set('blockDate', today()->format('Y-m-d'))
        ->set('blockStartTime', '09:00')
        ->set('blockEndTime', '10:00')
        ->set('blockReason', 'Personal appointment')
        ->call('blockTimeSlot')
        ->assertHasNoErrors();

    expect(BlockedTime::count())->toBe(1);
    expect(BlockedTime::first())
        ->block_date->toDateString()->toBe(today()->toDateString())
        ->start_time->toBe('09:00')
        ->end_time->toBe('10:00')
        ->reason->toBe('Personal appointment');
});

test('block time slot validates required fields', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.widgets.quick-actions')
        ->call('openBlockModal')
        ->set('blockDate', '')
        ->call('blockTimeSlot')
        ->assertHasErrors(['blockDate']);
});

test('block time slot prevents past dates', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.widgets.quick-actions')
        ->call('openBlockModal')
        ->set('blockDate', today()->subDay()->format('Y-m-d'))
        ->set('blockStartTime', '09:00')
        ->set('blockEndTime', '10:00')
        ->call('blockTimeSlot')
        ->assertHasErrors(['blockDate']);
});

test('block time slot validates end time after start time', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.widgets.quick-actions')
        ->call('openBlockModal')
        ->set('blockDate', today()->format('Y-m-d'))
        ->set('blockStartTime', '10:00')
        ->set('blockEndTime', '09:00')
        ->call('blockTimeSlot')
        ->assertHasErrors(['blockEndTime']);
});

test('block time slot reason is optional', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.widgets.quick-actions')
        ->call('openBlockModal')
        ->set('blockDate', today()->format('Y-m-d'))
        ->set('blockStartTime', '09:00')
        ->set('blockEndTime', '10:00')
        ->set('blockReason', '')
        ->call('blockTimeSlot')
        ->assertHasNoErrors();

    expect(BlockedTime::first()->reason)->toBeNull();
});

test('block modal closes after successful submission', function () {
    $this->actingAs($this->admin);

    $component = Volt::test('admin.widgets.quick-actions')
        ->call('openBlockModal');

    expect($component->get('showBlockModal'))->toBeTrue();

    $component->set('blockDate', today()->format('Y-m-d'))
        ->set('blockStartTime', '09:00')
        ->set('blockEndTime', '10:00')
        ->call('blockTimeSlot');

    expect($component->get('showBlockModal'))->toBeFalse();
});

// ===========================================
// Notification Bell Tests
// ===========================================

test('notification bell shows pending count in header', function () {
    Consultation::factory()->count(5)->pending()->create();

    $this->actingAs($this->admin)
        ->get(route('admin.dashboard'))
        ->assertSee('5');
});

test('notification bell not shown when no pending items', function () {
    $response = $this->actingAs($this->admin)
        ->get(route('admin.dashboard'));

    // Should still succeed, badge just won't be visible
    $response->assertSuccessful();
});

// ===========================================
// Access Control Tests
// ===========================================

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

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

// ===========================================
// Widget Integration Tests
// ===========================================

test('dashboard displays all widgets', function () {
    $this->actingAs($this->admin)
        ->get(route('admin.dashboard'))
        ->assertSuccessful()
        ->assertSee(__('widgets.quick_actions'))
        ->assertSee(__('widgets.pending_bookings'))
        ->assertSee(__('widgets.todays_schedule'))
        ->assertSee(__('widgets.recent_timeline_updates'));
});

test('widgets handle concurrent data gracefully', function () {
    // Create mixed data
    $client = User::factory()->individual()->create();
    $timeline = Timeline::factory()->create(['user_id' => $client->id]);

    Consultation::factory()->count(3)->pending()->create(['user_id' => $client->id]);
    Consultation::factory()->count(2)->approved()->create([
        'user_id' => $client->id,
        'booking_date' => today(),
    ]);
    TimelineUpdate::factory()->count(3)->create(['timeline_id' => $timeline->id]);

    $this->actingAs($this->admin)
        ->get(route('admin.dashboard'))
        ->assertSuccessful();
});
