<?php

use App\Enums\ConsultationStatus;
use App\Models\Consultation;
use App\Models\User;
use App\Models\WorkingHour;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\RateLimiter;
use Livewire\Volt\Volt;

beforeEach(function () {
    Mail::fake();
    RateLimiter::clear('guest-booking:127.0.0.1');
});

test('guest can view booking page', function () {
    $this->get(route('booking'))
        ->assertOk()
        ->assertSee(__('booking.request_consultation'));
});

test('logged in user sees message to book from dashboard', function () {
    $user = User::factory()->client()->create();

    $this->actingAs($user)
        ->get(route('booking'))
        ->assertOk()
        ->assertSee(__('booking.logged_in_title'))
        ->assertSee(__('booking.logged_in_message'))
        ->assertSee(__('booking.go_to_dashboard'));
});

test('guest booking page shows calendar', function () {
    $this->get(route('booking'))
        ->assertOk()
        ->assertSee(__('booking.guest_intro'));
});

test('guest can select a slot and see contact form', function () {
    WorkingHour::factory()->create([
        'day_of_week' => now()->addDay()->dayOfWeek,
        'is_active' => true,
        'start_time' => '09:00',
        'end_time' => '17:00',
    ]);

    $date = now()->addDay()->format('Y-m-d');

    Volt::test('pages.booking')
        ->call('selectSlot', $date, '09:00')
        ->assertSet('selectedDate', $date)
        ->assertSet('selectedTime', '09:00')
        ->assertSee(__('booking.guest_name'));
});

test('guest can submit booking request', function () {
    WorkingHour::factory()->create([
        'day_of_week' => now()->addDay()->dayOfWeek,
        'is_active' => true,
        'start_time' => '09:00',
        'end_time' => '17:00',
    ]);

    $date = now()->addDay()->format('Y-m-d');

    $component = Volt::test('pages.booking')
        ->call('selectSlot', $date, '09:00')
        ->set('guestName', 'John Doe')
        ->set('guestEmail', 'john@example.com')
        ->set('guestPhone', '+970599123456')
        ->set('problemSummary', 'I need legal advice regarding a contract dispute with my employer.')
        ->set('captchaAnswer', session('captcha_answer'))
        ->call('showConfirm')
        ->assertSet('showConfirmation', true)
        ->call('submit')
        ->assertRedirect(route('booking.success'));

    $this->assertDatabaseHas('consultations', [
        'guest_email' => 'john@example.com',
        'guest_name' => 'John Doe',
        'user_id' => null,
        'status' => ConsultationStatus::Pending->value,
    ]);
});

test('guest cannot book twice on same day', function () {
    $date = now()->addDay()->format('Y-m-d');

    WorkingHour::factory()->create([
        'day_of_week' => now()->addDay()->dayOfWeek,
        'is_active' => true,
        'start_time' => '09:00',
        'end_time' => '17:00',
    ]);

    // Create existing booking for this email
    Consultation::factory()->guest()->create([
        'guest_email' => 'john@example.com',
        'booking_date' => $date,
        'status' => ConsultationStatus::Pending,
    ]);

    Volt::test('pages.booking')
        ->call('selectSlot', $date, '10:00')
        ->set('guestName', 'John Doe')
        ->set('guestEmail', 'john@example.com')
        ->set('guestPhone', '+970599123456')
        ->set('problemSummary', 'Another consultation request for testing purposes.')
        ->set('captchaAnswer', session('captcha_answer'))
        ->call('showConfirm')
        ->assertHasErrors(['guestEmail']);
});

test('invalid captcha prevents submission', function () {
    WorkingHour::factory()->create([
        'day_of_week' => now()->addDay()->dayOfWeek,
        'is_active' => true,
        'start_time' => '09:00',
        'end_time' => '17:00',
    ]);

    Volt::test('pages.booking')
        ->call('selectSlot', now()->addDay()->format('Y-m-d'), '09:00')
        ->set('guestName', 'John Doe')
        ->set('guestEmail', 'john@example.com')
        ->set('guestPhone', '+970599123456')
        ->set('problemSummary', 'I need legal advice regarding a contract dispute.')
        ->set('captchaAnswer', 'wrong-answer')
        ->call('showConfirm')
        ->assertHasErrors(['captchaAnswer']);
});

test('rate limiting prevents excessive booking attempts', function () {
    $ipKey = 'guest-booking:127.0.0.1';

    // Exhaust the rate limit (5 attempts)
    for ($i = 0; $i < 5; $i++) {
        RateLimiter::hit($ipKey, 60 * 60 * 24);
    }

    WorkingHour::factory()->create([
        'day_of_week' => now()->addDay()->dayOfWeek,
        'is_active' => true,
        'start_time' => '09:00',
        'end_time' => '17:00',
    ]);

    $date = now()->addDay()->format('Y-m-d');

    Volt::test('pages.booking')
        ->call('selectSlot', $date, '09:00')
        ->set('guestName', 'John Doe')
        ->set('guestEmail', 'john@example.com')
        ->set('guestPhone', '+970599123456')
        ->set('problemSummary', 'I need legal advice regarding a contract dispute with my employer.')
        ->set('captchaAnswer', session('captcha_answer'))
        ->call('showConfirm')
        ->call('submit')
        ->assertHasErrors(['guestEmail']);

    RateLimiter::clear($ipKey);
});

test('slot taken during submission shows error', function () {
    WorkingHour::factory()->create([
        'day_of_week' => now()->addDay()->dayOfWeek,
        'is_active' => true,
        'start_time' => '09:00',
        'end_time' => '17:00',
    ]);

    $date = now()->addDay()->format('Y-m-d');

    // Start the booking process
    $component = Volt::test('pages.booking')
        ->call('selectSlot', $date, '09:00')
        ->set('guestName', 'John Doe')
        ->set('guestEmail', 'john@example.com')
        ->set('guestPhone', '+970599123456')
        ->set('problemSummary', 'I need legal advice regarding a contract dispute with my employer.')
        ->set('captchaAnswer', session('captcha_answer'))
        ->call('showConfirm')
        ->assertSet('showConfirmation', true);

    // Simulate another booking taking the slot before submission
    Consultation::factory()->guest()->create([
        'booking_date' => $date,
        'booking_time' => '09:00',
        'status' => ConsultationStatus::Pending,
    ]);

    // Try to submit - should fail with slot taken error
    $component->call('submit')
        ->assertHasErrors(['selectedTime']);
});

test('guest can clear slot selection', function () {
    WorkingHour::factory()->create([
        'day_of_week' => now()->addDay()->dayOfWeek,
        'is_active' => true,
        'start_time' => '09:00',
        'end_time' => '17:00',
    ]);

    $date = now()->addDay()->format('Y-m-d');

    Volt::test('pages.booking')
        ->call('selectSlot', $date, '09:00')
        ->assertSet('selectedDate', $date)
        ->call('clearSelection')
        ->assertSet('selectedDate', null)
        ->assertSet('selectedTime', null);
});

test('guest can refresh captcha', function () {
    $component = Volt::test('pages.booking');

    $firstQuestion = $component->get('captchaQuestion');

    $component->call('refreshCaptcha');

    // Just verify the captcha answer was reset
    $component->assertSet('captchaAnswer', '');
});

test('success page is accessible after booking', function () {
    $this->withSession(['success' => 'Test success message'])
        ->get(route('booking.success'))
        ->assertOk()
        ->assertSee(__('booking.success_title'));
});

test('form validation requires all fields', function () {
    WorkingHour::factory()->create([
        'day_of_week' => now()->addDay()->dayOfWeek,
        'is_active' => true,
        'start_time' => '09:00',
        'end_time' => '17:00',
    ]);

    Volt::test('pages.booking')
        ->call('selectSlot', now()->addDay()->format('Y-m-d'), '09:00')
        ->set('guestName', '')
        ->set('guestEmail', '')
        ->set('guestPhone', '')
        ->set('problemSummary', '')
        ->set('captchaAnswer', '')
        ->call('showConfirm')
        ->assertHasErrors(['guestName', 'guestEmail', 'guestPhone', 'problemSummary', 'captchaAnswer']);
});

test('guest name must be at least 3 characters', function () {
    WorkingHour::factory()->create([
        'day_of_week' => now()->addDay()->dayOfWeek,
        'is_active' => true,
        'start_time' => '09:00',
        'end_time' => '17:00',
    ]);

    Volt::test('pages.booking')
        ->call('selectSlot', now()->addDay()->format('Y-m-d'), '09:00')
        ->set('guestName', 'AB')
        ->set('guestEmail', 'test@example.com')
        ->set('guestPhone', '+970599123456')
        ->set('problemSummary', 'This is a valid problem summary for testing.')
        ->set('captchaAnswer', session('captcha_answer'))
        ->call('showConfirm')
        ->assertHasErrors(['guestName']);
});

test('problem summary must be at least 20 characters', function () {
    WorkingHour::factory()->create([
        'day_of_week' => now()->addDay()->dayOfWeek,
        'is_active' => true,
        'start_time' => '09:00',
        'end_time' => '17:00',
    ]);

    Volt::test('pages.booking')
        ->call('selectSlot', now()->addDay()->format('Y-m-d'), '09:00')
        ->set('guestName', 'John Doe')
        ->set('guestEmail', 'test@example.com')
        ->set('guestPhone', '+970599123456')
        ->set('problemSummary', 'Too short')
        ->set('captchaAnswer', session('captcha_answer'))
        ->call('showConfirm')
        ->assertHasErrors(['problemSummary']);
});

test('slot no longer available error is shown', function () {
    // Create a working hour but no available slots
    WorkingHour::factory()->create([
        'day_of_week' => now()->addDay()->dayOfWeek,
        'is_active' => true,
        'start_time' => '09:00',
        'end_time' => '10:00',
    ]);

    $date = now()->addDay()->format('Y-m-d');

    // Book the only available slot
    Consultation::factory()->guest()->create([
        'booking_date' => $date,
        'booking_time' => '09:00',
        'status' => ConsultationStatus::Approved,
    ]);

    // Try to book the same slot
    Volt::test('pages.booking')
        ->call('selectSlot', $date, '09:00')
        ->set('guestName', 'John Doe')
        ->set('guestEmail', 'different@example.com')
        ->set('guestPhone', '+970599123456')
        ->set('problemSummary', 'I need legal advice regarding a contract dispute.')
        ->set('captchaAnswer', session('captcha_answer'))
        ->call('showConfirm')
        ->assertHasErrors(['selectedTime']);
});
