<?php

namespace Tests\Feature;

use App\Models\Category;
use App\Models\Favourite;
use App\Models\Product;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class FavouriteApiTest extends TestCase
{
    use RefreshDatabase;

    public function test_authenticated_user_can_get_empty_favourites_list(): void
    {
        $user = User::factory()->create();

        $response = $this->actingAs($user)->getJson('/api/v1/favourites');

        $response->assertOk();
        $response->assertJsonStructure([
            'data' => [],
            'links',
            'meta',
        ]);
        $response->assertJsonCount(0, 'data');
    }

    public function test_authenticated_user_can_get_favourites_list(): void
    {
        $user = User::factory()->create();
        $category = Category::factory()->create();
        $product = Product::factory()->create(['category_id' => $category->id]);

        Favourite::factory()->create([
            'user_id' => $user->id,
            'product_id' => $product->id,
        ]);

        $response = $this->actingAs($user)->getJson('/api/v1/favourites');

        $response->assertOk();
        $response->assertJsonStructure([
            'data' => [
                [
                    'id',
                    'user_id',
                    'product_id',
                    'product' => [
                        'id',
                        'product_id',
                        'category_id',
                        'category',
                        'source',
                        'image_url',
                        'name_ar',
                        'name_en',
                        'price',
                        'discount_price',
                        'currency',
                    ],
                    'created_at',
                    'updated_at',
                ],
            ],
            'links',
            'meta',
        ]);
        $response->assertJsonCount(1, 'data');
    }

    public function test_authenticated_user_can_add_product_to_favourites(): void
    {
        $user = User::factory()->create();
        $category = Category::factory()->create();
        $product = Product::factory()->create(['category_id' => $category->id]);

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

        $response->assertStatus(201);
        $response->assertJsonStructure([
            'data' => [
                'id',
                'user_id',
                'product_id',
                'product' => [
                    'id',
                    'product_id',
                    'category_id',
                    'category',
                    'source',
                    'image_url',
                    'name_ar',
                    'name_en',
                    'price',
                    'discount_price',
                    'currency',
                ],
                'created_at',
                'updated_at',
            ],
        ]);
        $response->assertJsonPath('data.product_id', $product->id);
        $response->assertJsonPath('data.user_id', $user->id);

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

    public function test_authenticated_user_cannot_add_nonexistent_product_to_favourites(): void
    {
        $user = User::factory()->create();

        $response = $this->actingAs($user)->postJson('/api/v1/favourites', [
            'product_id' => 999,
        ]);

        $response->assertUnprocessable();
        $response->assertJsonValidationErrors(['product_id']);
    }

    public function test_authenticated_user_cannot_add_product_to_favourites_without_product_id(): void
    {
        $user = User::factory()->create();

        $response = $this->actingAs($user)->postJson('/api/v1/favourites', []);

        $response->assertUnprocessable();
        $response->assertJsonValidationErrors(['product_id']);
    }

    public function test_authenticated_user_can_remove_product_from_favourites(): void
    {
        $user = User::factory()->create();
        $category = Category::factory()->create();
        $product = Product::factory()->create(['category_id' => $category->id]);

        Favourite::factory()->create([
            'user_id' => $user->id,
            'product_id' => $product->id,
        ]);

        $response = $this->actingAs($user)->deleteJson("/api/v1/favourites/{$product->id}");

        $response->assertOk();
        $response->assertJson([
            'message' => 'Product removed from favourites.',
        ]);

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

    public function test_authenticated_user_gets_404_when_removing_nonexistent_favourite(): void
    {
        $user = User::factory()->create();
        $category = Category::factory()->create();
        $product = Product::factory()->create(['category_id' => $category->id]);

        $response = $this->actingAs($user)->deleteJson("/api/v1/favourites/{$product->id}");

        $response->assertStatus(404);
        $response->assertJson([
            'message' => 'Favourite not found.',
        ]);
    }

    public function test_unauthenticated_user_cannot_access_favourites(): void
    {
        $response = $this->getJson('/api/v1/favourites');
        $response->assertUnauthorized();

        $response = $this->postJson('/api/v1/favourites', ['product_id' => 1]);
        $response->assertUnauthorized();

        $response = $this->deleteJson('/api/v1/favourites/1');
        $response->assertUnauthorized();
    }

    public function test_authenticated_user_can_paginate_favourites(): void
    {
        $user = User::factory()->create();
        $category = Category::factory()->create();

        // Create 20 products
        $products = Product::factory()->count(20)->create(['category_id' => $category->id]);

        // Add all to favourites
        foreach ($products as $product) {
            Favourite::factory()->create([
                'user_id' => $user->id,
                'product_id' => $product->id,
            ]);
        }

        $response = $this->actingAs($user)->getJson('/api/v1/favourites?per_page=10');

        $response->assertOk();
        $response->assertJsonCount(10, 'data');
        $response->assertJsonPath('meta.total', 20);
        $response->assertJsonPath('meta.per_page', 10);
    }

    public function test_authenticated_user_only_sees_their_own_favourites(): void
    {
        $user1 = User::factory()->create();
        $user2 = User::factory()->create();
        $category = Category::factory()->create();
        $product1 = Product::factory()->create(['category_id' => $category->id]);
        $product2 = Product::factory()->create(['category_id' => $category->id]);

        Favourite::factory()->create([
            'user_id' => $user1->id,
            'product_id' => $product1->id,
        ]);

        Favourite::factory()->create([
            'user_id' => $user2->id,
            'product_id' => $product2->id,
        ]);

        $response = $this->actingAs($user1)->getJson('/api/v1/favourites');

        $response->assertOk();
        $response->assertJsonCount(1, 'data');
        $response->assertJsonPath('data.0.product_id', $product1->id);
    }
}
