<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
use App\Models\User;
use App\Models\Product;
use App\Models\Category;
use App\Models\Booking;
use App\Models\ProductAvailability;
use App\Models\Favorite;
use App\Models\Page;

class UserApiTest extends TestCase
{
    use RefreshDatabase, WithFaker;

    public function test_user_can_register()
    {
        $userData = [
            'first_name'            => 'John',
            'last_name'             => 'Doe',
            'email'                 => 'john.doe@example.com',
            'phone'                 => '123456789',
            'password'              => 'Password123!',
            'password_confirmation' => 'Password123!',
        ];

        $response = $this->postJson('/api/user/register', $userData);

        $response->assertStatus(201)
            ->assertJsonStructure([
                'success',
                'data' => [
                    'user' => [
                        'id',
                        'first_name',
                        'last_name',
                        'email',
                        'phone',
                    ],
                    'token',
                ],
                'message',
            ]);
    }

    public function test_user_cannot_register_with_missing_data()
    {
        $userData = [
            'first_name'            => 'John',
            'last_name'             => 'Doe',
            'email'                 => 'john.doe@example.com',
            'phone'                 => '123456789',
            'password'              => 'Password123!',
            'password_confirmation' => 'Password123!',
        ];

        foreach (array_keys($userData) as $key) {
            $data = $userData;
            unset($data[$key]);

            $response = $this->postJson('/api/user/register', $data);

            $response->assertStatus(422);
        }
    }

    public function test_user_can_login()
    {
        $user = User::factory()->create([
            'password' => bcrypt('Password123!'),
        ]);

        $loginData = [
            'email'    => $user->email,
            'password' => 'Password123!',
        ];

        $response = $this->postJson('/api/user/login', $loginData);

        $response->assertStatus(200)
            ->assertJsonStructure([
                'success',
                'data' => [
                    'user' => [
                        'id',
                        'first_name',
                        'last_name',
                        'email',
                        'phone',
                    ],
                    'token',
                ],
                'message',
            ]);
    }

    public function test_user_can_view_profile()
    {
        $user = User::factory()->create();
        $this->actingAs($user);

        $response = $this->getJson('/api/user/profile');

        $response->assertStatus(200)
            ->assertJson([
                'success' => true,
                'data'    => [
                    'id'         => $user->id,
                    'first_name' => $user->first_name,
                    'last_name'  => $user->last_name,
                    'email'      => $user->email,
                    'phone'      => $user->phone,
                ],
                'message' => 'Operation successful.',
            ]);
    }

    public function test_user_can_update_profile()
    {
        $user = User::factory()->create();
        $this->actingAs($user);

        $updateData = [
            'first_name' => 'Jane',
            'last_name'  => 'Doe',
            'email'      => 'jane.doe@example.com',
            'phone'      => '987654321',
        ];

        $response = $this->putJson('/api/user/profile', $updateData);

        $response->assertStatus(200)
            ->assertJson([
                'success' => true,
                'message' => 'messages.profile_updated_successfully',
            ]);

        $this->assertDatabaseHas('users', [
            'id'         => $user->id,
            'first_name' => 'Jane',
            'last_name'  => 'Doe',
            'email'      => 'jane.doe@example.com',
            'phone'      => '987654321',
        ]);
    }

    public function test_user_can_change_password()
    {
        $user = User::factory()->create([
            'password' => bcrypt('Password123!'),
        ]);
        $this->actingAs($user);

        $passwordData = [
            'current_password'      => 'Password123!',
            'password'              => 'NewPassword123!',
            'password_confirmation' => 'NewPassword123!',
        ];

        $response = $this->putJson('/api/user/password/change', $passwordData);

        $response->assertStatus(200)
            ->assertJson([
                'success' => true,
                'message' => 'messages.password_changed_successfully',
            ]);
    }

    public function test_user_can_delete_account()
    {
        $user = User::factory()->create();
        $this->actingAs($user);

        $response = $this->deleteJson('/api/user/profile');

        $response->assertStatus(200)
            ->assertJson([
                'success' => true,
                'message' => 'Account deleted successfully.',
            ]);

        $this->assertSoftDeleted('users', ['id' => $user->id]);
    }

    public function test_user_can_search_products()
    {
        Product::factory()->create(['name_en' => 'Test Product']);
        $user = User::factory()->create();
        $this->actingAs($user);

        $response = $this->getJson('/api/user/products?search=Test');

        $response->assertStatus(200)
            ->assertJsonStructure([
                'success',
                'data' => [
                    '*' => [
                        'id',
                        'name',
                    ],
                ],
                'message',
            ]);
    }

    public function test_user_can_filter_products()
    {
        $category = Category::factory()->create();
        Product::factory()->create(['category_id' => $category->id]);
        $user = User::factory()->create();
        $this->actingAs($user);

        $response = $this->getJson('/api/user/products?category_id=' . $category->id);

        $response->assertStatus(200)
            ->assertJsonStructure([
                'success',
                'data' => [
                    'data' => [
                        '*' => [
                            'id',
                            'name_en',
                            'name_ar',
                        ],
                    ],
                ],
                'message',
            ]);
    }

    public function test_user_can_view_product_details()
    {
        $product = Product::factory()->create();
        $user = User::factory()->create();
        $this->actingAs($user);

        $response = $this->getJson('/api/user/products/' . $product->id);

        $response->assertStatus(200)
            ->assertJson([
                'success' => true,
                'data'    => [
                    'id'      => $product->id,
                    'name_en' => $product->name_en,
                    'name_ar' => $product->name_ar,
                ],
                'message' => 'Product retrieved successfully.',
            ]);
    }

    public function test_user_can_add_product_to_cart()
    {
        $product = Product::factory()->create();
        $user = User::factory()->create();
        $this->actingAs($user);

        $response = $this->postJson('/api/user/cart', ['product_id' => $product->id]);

        $response->assertStatus(201)
            ->assertJson([
                'success' => true,
                'message' => 'Item added to cart successfully.',
            ]);

        $this->assertDatabaseHas('cart_items', [
            'user_id'    => $user->id,
            'product_id' => $product->id,
        ]);
    }

    public function test_user_can_view_cart()
    {
        $user = User::factory()->create();
        $this->actingAs($user);
        $product = Product::factory()->create();
        $user->cartItems()->create(['product_id' => $product->id]);

        $response = $this->getJson('/api/user/cart');

        $response->assertStatus(200)
            ->assertJsonStructure([
                'success',
                'data' => [
                    '*' => [
                        'id',
                        'product_id',
                    ],
                ],
                'message',
            ]);
    }

    public function test_user_can_remove_product_from_cart()
    {
        $user = User::factory()->create();
        $this->actingAs($user);
        $product = Product::factory()->create();
        $cartItem = $user->cartItems()->create(['product_id' => $product->id]);

        $response = $this->deleteJson('/api/user/cart/items/' . $cartItem->id);

        $response->assertStatus(204);

        $this->assertDatabaseMissing('cart_items', ['id' => $cartItem->id]);
    }

    public function test_user_can_create_booking()
    {
        $user = User::factory()->create();
        $this->actingAs($user);
        $product = Product::factory()->create();
        ProductAvailability::factory()->create(['product_id' => $product->id, 'date' => now()->addDay()->format('Y-m-d')]);

        $bookingData = [
            'items' => [
                [
                    'product_id'   => $product->id,
                    'service_date' => now()->addDay()->format('Y-m-d'),
                ],
            ],
        ];

        $response = $this->postJson('/api/user/bookings', $bookingData);

        $response->assertStatus(201)
            ->assertJson([
                'success' => true,
                'message' => 'Booking created successfully.',
            ]);
    }

    public function test_user_can_view_booking_history()
    {
        $user = User::factory()->create();
        $this->actingAs($user);
        Booking::factory()->create(['user_id' => $user->id]);

        $response = $this->getJson('/api/user/bookings');

        $response->assertStatus(200)
            ->assertJsonStructure([
                'success',
                'data' => [
                    '*' => [
                        'id',
                        'booking_status',
                    ],
                ],
                'message',
            ]);
    }

    public function test_user_can_cancel_booking()
    {
        $user = User::factory()->create();
        $this->actingAs($user);
        $booking = Booking::factory()->create(['user_id' => $user->id]);

        $response = $this->postJson('/api/user/bookings/' . $booking->id . '/cancel');

        $response->assertStatus(200)
            ->assertJson([
                'success' => true,
                'message' => 'messages.booking_canceled_successfully',
            ]);

        $this->assertDatabaseHas('bookings', [
            'id'     => $booking->id,
            'status' => 'canceled',
        ]);
    }

    public function test_user_can_pay_for_booking()
    {
        $user = User::factory()->create();
        $this->actingAs($user);
        $booking = Booking::factory()->create(['user_id' => $user->id]);

        $paymentData = [
            'payment_method' => 'visa',
            'payment_token'  => 'tok_visa',
        ];

        $response = $this->postJson('/api/user/bookings/' . $booking->id . '/pay', $paymentData);

        $response->assertStatus(200)
            ->assertJson([
                'success' => true,
                'message' => 'messages.payment_successful',
            ]);
    }

    public function test_user_can_add_product_to_favorites()
    {
        $user = User::factory()->create();
        $this->actingAs($user);
        $product = Product::factory()->create();

        $response = $this->postJson('/api/user/favorites', ['product_id' => $product->id]);

        $response->assertStatus(201)
            ->assertJson([
                'success' => true,
                'message' => 'Item added to favorites successfully.',
            ]);

        $this->assertDatabaseHas('favorites', [
            'user_id'    => $user->id,
            'product_id' => $product->id,
        ]);
    }

    public function test_user_can_view_favorites()
    {
        $user = User::factory()->create();
        $this->actingAs($user);
        $product = Product::factory()->create();
        Favorite::factory()->create(['user_id' => $user->id, 'product_id' => $product->id]);

        $response = $this->getJson('/api/user/favorites');

        $response->assertStatus(200)
            ->assertJsonStructure([
                'success',
                'data' => [
                    'data' => [
                        '*' => [
                            'id',
                            'name_en',
                            'name_ar',
                        ],
                    ],
                ],
                'message',
            ]);
    }

    public function test_user_can_rate_and_review_product()
    {
        $user = User::factory()->create();
        $this->actingAs($user);
        $product = Product::factory()->create();

        $reviewData = [
            'product_id' => $product->id,
            'rating'     => 5,
            'comment'    => 'Great product!',
        ];

        $response = $this->postJson('/api/user/reviews', $reviewData);

        $response->assertStatus(201)
            ->assertJson([
                'success' => true,
                'message' => 'messages.review_submitted_successfully',
            ]);

        $this->assertDatabaseHas('reviews', [
            'user_id'    => $user->id,
            'product_id' => $product->id,
            'rating'     => 5,
            'comment'    => 'Great product!',
        ]);
    }

    public function test_user_can_view_static_page()
    {
        $page = Page::factory()->create();

        $response = $this->getJson('/api/user/pages/' . $page->slug);

        $response->assertStatus(200)
            ->assertJson([
                'success' => true,
                'data'    => [
                    'title_en'   => $page->title_en,
                    'content_en' => $page->content_en,
                ],
                'message' => 'Operation successful.',
            ]);
    }

    public function test_user_can_contact_support()
    {
        $contactData = [
            'name'    => 'John Doe',
            'email'   => 'john.doe@example.com',
            'phone'   => '123456789',
            'message' => 'This is a test message.',
        ];

        $response = $this->postJson('/api/user/contact', $contactData);

        $response->assertStatus(200)
            ->assertJson([
                'success' => true,
                'message' => 'messages.message_sent_successfully',
            ]);
    }

    public function test_user_can_view_notifications()
    {
        $user = User::factory()->create();
        $this->actingAs($user);

        $response = $this->getJson('/api/user/notifications');

        $response->assertStatus(200)
            ->assertJsonStructure([
                'success',
                'data' => [],
                'message',
            ]);
    }
}
