<?php

use App\Models\Ecommerce\Product\Product\Product;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Str;

uses(RefreshDatabase::class);

beforeEach(function () {
    Config::set('ecommerce.api.token', 'test-token');
});

function createProductForSearch(array $attributes = []): Product
{
    $name = $attributes['name'] ?? 'Test Product '.Str::random(5);

    return Product::create(array_merge([
        'name' => $name,
        'slug' => Str::slug($name),
        'is_visible' => true,
        'price_amount' => 100.00,
        'stock' => 10,
        'parent_id' => null,
    ], $attributes));
}

test('can search product by barcode', function () {
    // Arrange
    $product = createProductForSearch([
        'name' => 'Barcode Product',
        'barcode' => '1234567890123',
    ]);

    // Act
    $response = $this->withHeaders([
        'Api-Token' => 'test-token',
        'Accept' => 'application/json',
    ])->getJson('/api/v1/search-product-barcode?barcode=1234567890123');

    // Assert
    $response->assertOk()
        ->assertJson([
            'data' => [
                'id' => $product->id,
                'name' => 'Barcode Product',
                'stock' => 10,
            ],
        ]);
});

test('returns empty result for non-existent barcode', function () {
    // Act
    $response = $this->withHeaders([
        'Api-Token' => 'test-token',
        'Accept' => 'application/json',
    ])->getJson('/api/v1/search-product-barcode?barcode=nonexistent');

    // Assert
    $response->assertUnprocessable(); // 422
    $response->assertJsonValidationErrors(['barcode']);
});

test('can search product by query string (name)', function () {
    // Arrange
    createProductForSearch(['name' => 'Apple iPhone 13']);
    createProductForSearch(['name' => 'Samsung Galaxy S21']);

    // Act
    $response = $this->withHeaders([
        'Api-Token' => 'test-token',
        'Accept' => 'application/json',
    ])->getJson('/api/v1/search-product?q=iPhone');

    // Assert
    $response->assertOk();
    $this->assertCount(1, $response->json('data'));
    $this->assertEquals('Apple iPhone 13', $response->json('data.0.name'));
});

test('can search product by query string (sku)', function () {
    // Arrange
    createProductForSearch(['name' => 'Product A', 'sku' => 'SKU-123']);
    createProductForSearch(['name' => 'Product B', 'sku' => 'SKU-456']);

    // Act
    $response = $this->withHeaders([
        'Api-Token' => 'test-token',
        'Accept' => 'application/json',
    ])->getJson('/api/v1/search-product?q=SKU-123');

    // Assert
    $response->assertOk();
    $this->assertCount(1, $response->json('data'));
    $this->assertEquals('Product A', $response->json('data.0.name'));
});

test('can search product by query string (barcode)', function () {
    // Arrange
    createProductForSearch(['name' => 'Product X', 'barcode' => 'BAR-123']);
    createProductForSearch(['name' => 'Product Y', 'barcode' => 'BAR-456']);

    // Act
    $response = $this->withHeaders([
        'Api-Token' => 'test-token',
        'Accept' => 'application/json',
    ])->getJson('/api/v1/search-product?q=BAR-123');

    // Assert
    $response->assertOk();
    $this->assertCount(1, $response->json('data'));
    $this->assertEquals('Product X', $response->json('data.0.name'));
});

test('can search product by id (numeric query)', function () {
    // Arrange
    $product = createProductForSearch(['name' => 'Product ID Search']);

    // Act
    $response = $this->withHeaders([
        'Api-Token' => 'test-token',
        'Accept' => 'application/json',
    ])->getJson("/api/v1/search-product?q={$product->id}");

    // Assert
    $response->assertOk();
    // It might return other products if they match name/sku/barcode with the ID, but unlikely with random names.
    // Ideally it should find the product by ID.
    $ids = collect($response->json('data'))->pluck('id');
    $this->assertContains($product->id, $ids);
});

test('search requires q parameter', function () {
    // Act
    $response = $this->withHeaders([
        'Api-Token' => 'test-token',
        'Accept' => 'application/json',
    ])->getJson('/api/v1/search-product');

    // Assert
    $response->assertUnprocessable(); // 422
    $response->assertJsonValidationErrors(['q']);
});
