<?php

use App\Models\AdminLog;
use App\Models\User;
use App\Models\WorkingHour;
use Livewire\Volt\Volt;

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

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

test('admin can access working hours configuration page', function () {
    $this->actingAs($this->admin)
        ->get(route('admin.settings.working-hours'))
        ->assertOk();
});

test('non-admin cannot access working hours configuration page', function () {
    $client = User::factory()->individual()->create();

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

test('unauthenticated user cannot access working hours configuration page', function () {
    $this->get(route('admin.settings.working-hours'))
        ->assertRedirect(route('login'));
});

// ===========================================
// Component Initialization Tests
// ===========================================

test('component initializes with empty schedule when no working hours exist', function () {
    $this->actingAs($this->admin);

    $component = Volt::test('admin.settings.working-hours');

    foreach (range(0, 6) as $day) {
        expect($component->get("schedule.{$day}.is_active"))->toBeFalse();
        expect($component->get("schedule.{$day}.start_time"))->toBe('09:00');
        expect($component->get("schedule.{$day}.end_time"))->toBe('17:00');
    }
});

test('component initializes with existing working hours', function () {
    WorkingHour::factory()->create([
        'day_of_week' => 1,
        'start_time' => '08:00:00',
        'end_time' => '16:00:00',
        'is_active' => true,
    ]);

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

    $component = Volt::test('admin.settings.working-hours');

    expect($component->get('schedule.1.is_active'))->toBeTrue();
    expect($component->get('schedule.1.start_time'))->toBe('08:00');
    expect($component->get('schedule.1.end_time'))->toBe('16:00');
});

// ===========================================
// Save Working Hours Tests
// ===========================================

test('admin can save working hours configuration', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.settings.working-hours')
        ->set('schedule.1.is_active', true)
        ->set('schedule.1.start_time', '09:00')
        ->set('schedule.1.end_time', '17:00')
        ->call('save')
        ->assertHasNoErrors();

    $workingHour = WorkingHour::where('day_of_week', 1)->first();

    expect($workingHour)->not->toBeNull()
        ->and($workingHour->is_active)->toBeTrue()
        ->and($workingHour->start_time)->toContain('09:00')
        ->and($workingHour->end_time)->toContain('17:00');
});

test('admin can enable multiple days with different hours', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.settings.working-hours')
        ->set('schedule.0.is_active', true)
        ->set('schedule.0.start_time', '09:00')
        ->set('schedule.0.end_time', '17:00')
        ->set('schedule.1.is_active', true)
        ->set('schedule.1.start_time', '08:00')
        ->set('schedule.1.end_time', '16:00')
        ->set('schedule.2.is_active', true)
        ->set('schedule.2.start_time', '10:00')
        ->set('schedule.2.end_time', '18:00')
        ->call('save')
        ->assertHasNoErrors();

    expect(WorkingHour::where('is_active', true)->count())->toBe(3);

    $monday = WorkingHour::where('day_of_week', 1)->first();
    expect($monday->start_time)->toContain('08:00');
    expect($monday->end_time)->toContain('16:00');
});

test('admin can disable a day', function () {
    WorkingHour::factory()->create([
        'day_of_week' => 1,
        'is_active' => true,
    ]);

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

    Volt::test('admin.settings.working-hours')
        ->set('schedule.1.is_active', false)
        ->call('save')
        ->assertHasNoErrors();

    $workingHour = WorkingHour::where('day_of_week', 1)->first();
    expect($workingHour->is_active)->toBeFalse();
});

test('existing working hours are updated not duplicated', function () {
    WorkingHour::factory()->create([
        'day_of_week' => 1,
        'start_time' => '08:00:00',
        'end_time' => '16:00:00',
        'is_active' => true,
    ]);

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

    Volt::test('admin.settings.working-hours')
        ->set('schedule.1.start_time', '09:00')
        ->set('schedule.1.end_time', '17:00')
        ->call('save')
        ->assertHasNoErrors();

    expect(WorkingHour::where('day_of_week', 1)->count())->toBe(1);

    $workingHour = WorkingHour::where('day_of_week', 1)->first();
    expect($workingHour->start_time)->toContain('09:00');
    expect($workingHour->end_time)->toContain('17:00');
});

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

test('validation fails when end time is before start time for active day', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.settings.working-hours')
        ->set('schedule.1.is_active', true)
        ->set('schedule.1.start_time', '17:00')
        ->set('schedule.1.end_time', '09:00')
        ->call('save')
        ->assertHasErrors(['schedule.1.end_time']);
});

test('validation fails when end time equals start time for active day', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.settings.working-hours')
        ->set('schedule.1.is_active', true)
        ->set('schedule.1.start_time', '09:00')
        ->set('schedule.1.end_time', '09:00')
        ->call('save')
        ->assertHasErrors(['schedule.1.end_time']);
});

test('inactive days do not require time validation', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.settings.working-hours')
        ->set('schedule.1.is_active', false)
        ->set('schedule.1.start_time', '17:00')
        ->set('schedule.1.end_time', '09:00')
        ->call('save')
        ->assertHasNoErrors();
});

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

test('audit log is created when working hours are saved', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.settings.working-hours')
        ->set('schedule.0.is_active', true)
        ->set('schedule.0.start_time', '09:00')
        ->set('schedule.0.end_time', '17:00')
        ->call('save');

    expect(AdminLog::where('target_type', 'working_hours')->count())->toBe(1);

    $log = AdminLog::where('target_type', 'working_hours')->first();
    expect($log->admin_id)->toBe($this->admin->id);
    expect($log->action)->toBe('update');
});

test('audit log contains old and new values', function () {
    WorkingHour::factory()->create([
        'day_of_week' => 1,
        'start_time' => '08:00:00',
        'end_time' => '16:00:00',
        'is_active' => true,
    ]);

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

    Volt::test('admin.settings.working-hours')
        ->set('schedule.1.start_time', '09:00')
        ->set('schedule.1.end_time', '17:00')
        ->call('save');

    $log = AdminLog::where('target_type', 'working_hours')->first();

    expect($log->old_values)->toBeArray();
    expect($log->new_values)->toBeArray();
});

// ===========================================
// Slot Display Tests
// ===========================================

test('active day shows available slots badge', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.settings.working-hours')
        ->set('schedule.1.is_active', true)
        ->set('schedule.1.start_time', '09:00')
        ->set('schedule.1.end_time', '12:00')
        ->assertSee(__('admin.slots_available', ['count' => 3]));
});

test('inactive day does not show slots badge', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.settings.working-hours')
        ->set('schedule.1.is_active', false)
        ->assertSee(__('admin.closed'));
});

test('invalid time range shows no slots badge', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.settings.working-hours')
        ->set('schedule.1.is_active', true)
        ->set('schedule.1.start_time', '17:00')
        ->set('schedule.1.end_time', '09:00')
        ->assertSee(__('admin.no_slots'));
});

// ===========================================
// Time Format Display Tests
// ===========================================

test('active day displays 12-hour time format', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.settings.working-hours')
        ->set('schedule.1.is_active', true)
        ->set('schedule.1.start_time', '09:00')
        ->set('schedule.1.end_time', '17:00')
        ->assertSee('9:00 AM')
        ->assertSee('5:00 PM');
});

// ===========================================
// Flash Message Tests
// ===========================================

test('save completes without errors and data is persisted', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.settings.working-hours')
        ->set('schedule.1.is_active', true)
        ->set('schedule.1.start_time', '09:00')
        ->set('schedule.1.end_time', '17:00')
        ->call('save')
        ->assertHasNoErrors();

    // Verify data was saved
    expect(WorkingHour::where('day_of_week', 1)->exists())->toBeTrue();
});
