<?php

use App\Models\Ecommerce\Product\Brand\Brand;
use App\Models\Ecommerce\Product\Category\Category;
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 createProductForFilterTest(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));
}

function createCategoryForFilterTest(array $attributes = []): Category
{
    $name = $attributes['name'] ?? 'Test Category '.Str::random(5);
    $nameValue = is_array($name) ? $name : ['en' => $name];
    $slug = Str::slug(is_array($name) ? ($name['en'] ?? reset($name)) : $name);

    return Category::create(array_merge([
        'name' => $nameValue,
        'slug' => $slug,
        'is_visible' => true,
        'sort_order' => 1,
        'type' => 'default',
    ], $attributes));
}

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

    return Brand::create(array_merge([
        'name' => $name,
        'slug' => Str::slug($name),
        'is_visible' => true,
        'sort_order' => 1,
    ], $attributes));
}

test('can filter products by name', function () {
    // Arrange
    createProductForFilterTest(['name' => 'Apple iPhone']);
    createProductForFilterTest(['name' => 'Samsung Galaxy']);

    // Act
    $response = $this->withHeaders([
        'Api-Token' => 'test-token',
        'Accept' => 'application/json',
    ])->getJson('/api/v1/products?name=Apple');

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

test('can filter products by min price', function () {
    // Arrange
    createProductForFilterTest(['name' => 'Cheap', 'price_amount' => 50]);
    createProductForFilterTest(['name' => 'Expensive', 'price_amount' => 150]);

    // Act
    $response = $this->withHeaders([
        'Api-Token' => 'test-token',
        'Accept' => 'application/json',
    ])->getJson('/api/v1/products?min_price=100');

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

test('can filter products by max price', function () {
    // Arrange
    createProductForFilterTest(['name' => 'Cheap', 'price_amount' => 50]);
    createProductForFilterTest(['name' => 'Expensive', 'price_amount' => 150]);

    // Act
    $response = $this->withHeaders([
        'Api-Token' => 'test-token',
        'Accept' => 'application/json',
    ])->getJson('/api/v1/products?max_price=100');

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

test('can filter products by price range', function () {
    // Arrange
    createProductForFilterTest(['name' => 'Cheap', 'price_amount' => 50]);
    createProductForFilterTest(['name' => 'Medium', 'price_amount' => 100]);
    createProductForFilterTest(['name' => 'Expensive', 'price_amount' => 150]);

    // Act
    $response = $this->withHeaders([
        'Api-Token' => 'test-token',
        'Accept' => 'application/json',
    ])->getJson('/api/v1/products?min_price=80&max_price=120');

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

test('can filter products by brand ids', function () {
    // Arrange
    $brand1 = createBrandForFilterTest(['name' => 'Brand 1']);
    $brand2 = createBrandForFilterTest(['name' => 'Brand 2']);

    createProductForFilterTest(['name' => 'Product 1', 'brand_id' => $brand1->id]);
    createProductForFilterTest(['name' => 'Product 2', 'brand_id' => $brand2->id]);
    createProductForFilterTest(['name' => 'Product 3']); // No brand

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

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

    // Test multiple brands
    $responseMulti = $this->withHeaders([
        'Api-Token' => 'test-token',
        'Accept' => 'application/json',
    ])->getJson("/api/v1/products?brands={$brand1->id},{$brand2->id}");

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

test('can filter products by category ids', function () {
    // Arrange
    $category1 = createCategoryForFilterTest(['name' => 'Category 1']);
    $category2 = createCategoryForFilterTest(['name' => 'Category 2']);

    $product1 = createProductForFilterTest(['name' => 'Product 1']);
    $product2 = createProductForFilterTest(['name' => 'Product 2']);
    $product3 = createProductForFilterTest(['name' => 'Product 3']);

    $category1->products()->attach($product1->id);
    $category2->products()->attach($product2->id);
    // Product 3 has no category

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

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

    // Test multiple categories
    $responseMulti = $this->withHeaders([
        'Api-Token' => 'test-token',
        'Accept' => 'application/json',
    ])->getJson("/api/v1/products?categories={$category1->id},{$category2->id}");

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

// Note: 'backorder' filter logic in ProductFilterer seems to check 'backorder' column on products table.
// However, I don't see 'backorder' in the create_products_table migration I read earlier.
// It might be a column added later or I missed it.
// Let's assume it exists or check if it fails.
// Looking at ProductFilterer: $this->queryBuilder->where('products.backorder', $this->request->backorder);
// If the column doesn't exist, this test will fail with SQL error.
// I'll skip it for now unless I confirm the column exists.
// Wait, I read the migration earlier:
// 2023_06_12_133956_create_products_table.php
// It did NOT have backorder column.
// Let me check if there are other migrations adding it.
// I'll assume it might not work or is added in another migration I didn't read fully (I truncated the list).
// But `ProductFilterer.php` uses it, so it MUST exist on the model/table.
