<?php

use App\Models\Ecommerce\Product\Product\Product;
use App\Models\System\Settings\OS;
use App\Models\User;
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');
    Config::set('hashing.bcrypt.rounds', 10); // Fix for hashed cast verification
});

function createProductForReview(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 list product reviews', function () {
    // Arrange
    $product = createProductForReview();
    $user = User::factory()->create();

    $product->reviews()->create([
        'user_id' => $user->id,
        'rating' => 5,
        'content' => 'Great product!',
        'is_visible' => true,
        'is_recommended' => true,
    ]);

    $product->reviews()->create([
        'user_id' => $user->id,
        'rating' => 4,
        'content' => 'Good product',
        'is_visible' => true,
        'is_recommended' => false,
    ]);

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

    // Assert
    $response->assertOk()
        ->assertJsonStructure([
            'data' => [
                '*' => [
                    'id',
                    'rating',
                    'content',
                ],
            ],
        ]);

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

test('does not list invisible reviews', function () {
    // Arrange
    $product = createProductForReview();
    $user = User::factory()->create();

    $product->reviews()->create([
        'user_id' => $user->id,
        'rating' => 5,
        'content' => 'Visible',
        'is_visible' => true,
    ]);

    $product->reviews()->create([
        'user_id' => $user->id,
        'rating' => 1,
        'content' => 'Invisible',
        'is_visible' => false,
    ]);

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

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

test('can store a review', function () {
    // Arrange
    $product = createProductForReview();
    $user = User::factory()->create();

    // Act
    $response = $this->actingAs($user)
        ->withHeaders([
            'Api-Token' => 'test-token',
            'Accept' => 'application/json',
        ])->postJson("/api/v1/products/{$product->id}/reviews", [
            'rating' => 5,
            'title' => 'Review Title',
            'content' => 'Amazing!',
            'is_recommended' => true,
            'source' => OS::WEBSITE,
        ]);

    // Assert
    $response->assertStatus(201); // Created

    $this->assertDatabaseHas('reviews', [
        'product_id' => $product->id,
        'user_id' => $user->id,
        'rating' => 5,
        'content' => 'Amazing!',
        'title' => 'Review Title',
        'source' => OS::WEBSITE,
    ]);
});

test('guest cannot store a review', function () {
    // Arrange
    $product = createProductForReview();

    // Act
    $response = $this->withHeaders([
        'Api-Token' => 'test-token',
        'Accept' => 'application/json',
    ])->postJson("/api/v1/products/{$product->id}/reviews", [
        'rating' => 5,
        'content' => 'Amazing!',
    ]);

    // Assert
    $response->assertUnauthorized();
});

test('validates review input', function () {
    // Arrange
    $product = createProductForReview();
    $user = User::factory()->create();

    // Act
    $response = $this->actingAs($user)
        ->withHeaders([
            'Api-Token' => 'test-token',
            'Accept' => 'application/json',
        ])->postJson("/api/v1/products/{$product->id}/reviews", [
            // Missing rating and source
            'content' => 'No rating',
        ]);

    // Assert
    $response->assertUnprocessable();
    $response->assertJsonValidationErrors(['rating', 'source']);
});
