<?php

namespace Tests\Feature;

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

class ProductApiTest extends TestCase
{
    use RefreshDatabase;

    public function test_guest_can_list_products_with_cursor_pagination(): void
    {
        $category = Category::factory()->create();
        Product::factory()->count(25)->create(['category_id' => $category->id]);

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

        $response->assertOk();
        $response->assertJsonStructure([
            'data' => [
                '*' => [
                    'id', 'category_id', 'category', 'source', 'name_ar', 'name_en',
                    'description_ar', 'description_en', 'price', 'discount_price',
                    'currency', 'clicks', 'direct_commission_rate',
                    'estimated_direct_commission', 'indirect_commission_rate',
                    'estimated_indirect_commission', 'sales_180day', 'positive_feedback',
                    'promotion_url', 'code_name', 'code_start_time', 'code_end_time',
                    'code_value', 'code_quantity', 'code_minimum_spend',
                    'created_at', 'updated_at',
                ],
            ],
        ]);

        $this->assertCount(10, $response->json('data'));

        $responseData = $response->json();
        $this->assertTrue(
            isset($responseData['meta']['next_cursor']) || isset($responseData['next_cursor']),
            'Response should have a next_cursor in either root or meta'
        );
    }

    public function test_guest_can_list_products_with_page_pagination(): void
    {
        $category = Category::factory()->create();
        Product::factory()->count(25)->create(['category_id' => $category->id]);

        $response = $this->getJson('/api/v1/products?pagination=page&page=2&per_page=10');

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

        $response->assertJsonPath('meta.current_page', 2);
        $response->assertJsonPath('meta.per_page', 10);
        $this->assertCount(10, $response->json('data'));
    }

    public function test_guest_can_filter_products_by_category(): void
    {
        $category1 = Category::factory()->create();
        $category2 = Category::factory()->create();

        Product::factory()->count(10)->create(['category_id' => $category1->id]);
        Product::factory()->count(5)->create(['category_id' => $category2->id]);

        $response = $this->getJson("/api/v1/products?category_id={$category2->id}");

        $response->assertOk();
        $this->assertCount(5, $response->json('data'));

        foreach ($response->json('data') as $product) {
            $this->assertEquals($category2->id, $product['category_id']);
        }
    }

    public function test_guest_can_filter_products_by_price_range(): void
    {
        $category = Category::factory()->create();
        Product::factory()->create(['category_id' => $category->id, 'price' => 50.00]);
        Product::factory()->create(['category_id' => $category->id, 'price' => 150.00]);
        Product::factory()->create(['category_id' => $category->id, 'price' => 250.00]);
        Product::factory()->create(['category_id' => $category->id, 'price' => 350.00]);

        $response = $this->getJson('/api/v1/products?min_price=100&max_price=300');

        $response->assertOk();
        $this->assertCount(2, $response->json('data'));

        foreach ($response->json('data') as $product) {
            $price = (float) $product['price'];
            $this->assertGreaterThanOrEqual(100, $price);
            $this->assertLessThanOrEqual(300, $price);
        }
    }

    public function test_guest_can_search_products_by_name(): void
    {
        $category = Category::factory()->create();
        Product::factory()->create([
            'category_id' => $category->id,
            'name_en' => 'Gaming Laptop',
            'name_ar' => 'لابتوب جيمنج',
        ]);
        Product::factory()->create([
            'category_id' => $category->id,
            'name_en' => 'Office Chair',
            'name_ar' => 'كرسي مكتب',
        ]);
        Product::factory()->create([
            'category_id' => $category->id,
            'name_en' => 'Laptop Stand',
            'name_ar' => 'حامل لابتوب',
        ]);

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

        $response->assertOk();
        $this->assertCount(2, $response->json('data'));
    }

    public function test_guest_can_sort_products(): void
    {
        $category = Category::factory()->create();
        Product::factory()->create(['category_id' => $category->id, 'price' => 300.00]);
        Product::factory()->create(['category_id' => $category->id, 'price' => 100.00]);
        Product::factory()->create(['category_id' => $category->id, 'price' => 200.00]);

        $response = $this->getJson('/api/v1/products?sort_by=price&sort_direction=asc');

        $response->assertOk();
        $products = $response->json('data');

        $this->assertEquals(100.00, (float) $products[0]['price']);
        $this->assertEquals(200.00, (float) $products[1]['price']);
        $this->assertEquals(300.00, (float) $products[2]['price']);
    }

    public function test_guest_can_combine_filters(): void
    {
        $category1 = Category::factory()->create();
        $category2 = Category::factory()->create();

        Product::factory()->create([
            'category_id' => $category1->id,
            'name_en' => 'Laptop A',
            'price' => 150.00,
        ]);
        Product::factory()->create([
            'category_id' => $category1->id,
            'name_en' => 'Laptop B',
            'price' => 250.00,
        ]);
        Product::factory()->create([
            'category_id' => $category2->id,
            'name_en' => 'Laptop C',
            'price' => 200.00,
        ]);

        $response = $this->getJson(
            "/api/v1/products?category_id={$category1->id}&min_price=100&max_price=200&search=laptop"
        );

        $response->assertOk();
        $this->assertCount(1, $response->json('data'));
        $this->assertEquals('Laptop A', $response->json('data.0.name_en'));
    }

    public function test_products_include_category_relationship(): void
    {
        $category = Category::factory()->create([
            'name_en' => 'Electronics',
            'name_ar' => 'الإلكترونيات',
        ]);
        Product::factory()->create(['category_id' => $category->id]);

        $response = $this->getJson('/api/v1/products');

        $response->assertOk();
        $response->assertJsonPath('data.0.category.name_en', 'Electronics');
        $response->assertJsonPath('data.0.category.name_ar', 'الإلكترونيات');
    }
}
