<?php

use App\Models\BlockedTime;

test('isAllDay returns true when start_time and end_time are null', function () {
    $blocked = BlockedTime::factory()->allDay()->create();

    expect($blocked->isAllDay())->toBeTrue();
});

test('isAllDay returns false when times are set', function () {
    $blocked = BlockedTime::factory()->timeRange('09:00', '12:00')->create();

    expect($blocked->isAllDay())->toBeFalse();
});

test('scopeUpcoming filters to today and future dates', function () {
    BlockedTime::factory()->create(['block_date' => today()]);
    BlockedTime::factory()->create(['block_date' => today()->addDays(5)]);
    BlockedTime::factory()->create(['block_date' => today()->subDays(5)]);

    $upcoming = BlockedTime::upcoming()->get();

    expect($upcoming)->toHaveCount(2)
        ->and($upcoming->pluck('block_date')->every(fn ($date) => $date->gte(today())))->toBeTrue();
});

test('scopePast filters to past dates only', function () {
    BlockedTime::factory()->create(['block_date' => today()]);
    BlockedTime::factory()->create(['block_date' => today()->addDays(5)]);
    BlockedTime::factory()->create(['block_date' => today()->subDays(5)]);

    $past = BlockedTime::past()->get();

    expect($past)->toHaveCount(1)
        ->and($past->first()->block_date->lt(today()))->toBeTrue();
});

test('scopeForDate filters by exact date', function () {
    $targetDate = today()->addDays(3);

    BlockedTime::factory()->create(['block_date' => $targetDate]);
    BlockedTime::factory()->create(['block_date' => today()]);
    BlockedTime::factory()->create(['block_date' => today()->addDays(10)]);

    $result = BlockedTime::forDate($targetDate)->get();

    expect($result)->toHaveCount(1)
        ->and($result->first()->block_date->toDateString())->toBe($targetDate->toDateString());
});

test('blocksSlot returns true for all times when all-day block', function () {
    $blocked = BlockedTime::factory()->allDay()->create();

    expect($blocked->blocksSlot('09:00'))->toBeTrue()
        ->and($blocked->blocksSlot('12:00'))->toBeTrue()
        ->and($blocked->blocksSlot('17:00'))->toBeTrue()
        ->and($blocked->blocksSlot('23:59'))->toBeTrue();
});

test('blocksSlot returns true for times within blocked range', function () {
    $blocked = BlockedTime::factory()->timeRange('09:00', '12:00')->create();

    expect($blocked->blocksSlot('09:00'))->toBeTrue()
        ->and($blocked->blocksSlot('10:00'))->toBeTrue()
        ->and($blocked->blocksSlot('11:00'))->toBeTrue()
        ->and($blocked->blocksSlot('11:30'))->toBeTrue();
});

test('blocksSlot returns false for times outside blocked range', function () {
    $blocked = BlockedTime::factory()->timeRange('09:00', '12:00')->create();

    expect($blocked->blocksSlot('08:00'))->toBeFalse()
        ->and($blocked->blocksSlot('08:59'))->toBeFalse()
        ->and($blocked->blocksSlot('12:00'))->toBeFalse()
        ->and($blocked->blocksSlot('13:00'))->toBeFalse();
});

test('blocksSlot returns true at start time boundary', function () {
    $blocked = BlockedTime::factory()->timeRange('09:00', '12:00')->create();

    expect($blocked->blocksSlot('09:00'))->toBeTrue();
});

test('blocksSlot returns false at end time boundary', function () {
    $blocked = BlockedTime::factory()->timeRange('09:00', '12:00')->create();

    expect($blocked->blocksSlot('12:00'))->toBeFalse();
});

test('block_date is cast to date', function () {
    $blocked = BlockedTime::factory()->create([
        'block_date' => '2025-12-26',
    ]);

    expect($blocked->block_date)->toBeInstanceOf(Carbon\Carbon::class);
});

test('reason can be null', function () {
    $blocked = BlockedTime::factory()->create([
        'reason' => null,
    ]);

    expect($blocked->reason)->toBeNull();
});

test('reason can be set', function () {
    $blocked = BlockedTime::factory()->withReason('Holiday vacation')->create();

    expect($blocked->reason)->toBe('Holiday vacation');
});

test('factory allDay state creates full day block', function () {
    $blocked = BlockedTime::factory()->allDay()->create();

    expect($blocked->start_time)->toBeNull()
        ->and($blocked->end_time)->toBeNull()
        ->and($blocked->isAllDay())->toBeTrue();
});

test('factory timeRange state creates partial day block', function () {
    $blocked = BlockedTime::factory()->timeRange('10:00', '14:00')->create();

    expect($blocked->start_time)->toContain('10:00')
        ->and($blocked->end_time)->toContain('14:00')
        ->and($blocked->isAllDay())->toBeFalse();
});

test('factory upcoming state creates future date', function () {
    $blocked = BlockedTime::factory()->upcoming()->create();

    expect($blocked->block_date->gt(today()))->toBeTrue();
});

test('factory past state creates past date', function () {
    $blocked = BlockedTime::factory()->past()->create();

    expect($blocked->block_date->lt(today()))->toBeTrue();
});

test('factory today state creates today date', function () {
    $blocked = BlockedTime::factory()->today()->create();

    expect($blocked->block_date->toDateString())->toBe(today()->toDateString());
});
