<?php

namespace Tests\Feature;

use App\Models\User;
use App\Models\Product;
use App\Models\ProductVariant;
use App\Models\ProductAttribute;
use App\Models\ProductAttributeValue;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class ProductAttributeSystemTest extends TestCase
{
    use RefreshDatabase;

    private User $admin;
    private Product $product;

    protected function setUp(): void
    {
        parent::setUp();

        $this->admin = User::create([
            'name' => 'Admin User',
            'email' => 'admin@sawdabazar.com',
            'password' => bcrypt('password123'),
            'role' => 'admin',
        ]);

        $category = \App\Models\Category::create([
            'name' => 'Test Category',
            'slug' => 'test-category',
            'is_visible' => true,
        ]);

        $this->product = Product::create([
            'name' => 'Test Product',
            'slug' => 'test-product',
            'sku' => 'TP-001',
            'price' => 500.00,
            'compare_at_price' => 600.00,
            'cost_price' => 400.00,
            'quantity' => 10,
            'published_at' => now(),
            'category_id' => $category->id,
        ]);
    }

    /**
     * Test admin can load list page of variant names.
     */
    public function test_admin_can_load_variant_names_list_page(): void
    {
        $this->actingAs($this->admin);

        $response = $this->get('/admin/variant-names');
        $response->assertStatus(200);
    }

    /**
     * Test admin can create a variant name with attribute values.
     */
    public function test_admin_can_create_variant_name_with_values(): void
    {
        $this->actingAs($this->admin);

        \Livewire\Livewire::actingAs($this->admin);
        \Filament\Facades\Filament::setCurrentPanel(\Filament\Facades\Filament::getPanel('admin'));

        \Livewire\Livewire::test(\App\Filament\Resources\Products\Pages\CreateProductAttribute::class)
            ->fillForm([
                'name' => 'Fabric',
                'values' => [
                    ['value' => 'Cotton'],
                    ['value' => 'Silk'],
                ]
            ])
            ->call('create')
            ->assertHasNoErrors();

        $this->assertDatabaseHas('product_attributes', [
            'name' => 'Fabric',
        ]);

        $attribute = ProductAttribute::where('name', 'Fabric')->first();
        $this->assertNotNull($attribute);

        $this->assertDatabaseHas('product_attribute_values', [
            'product_attribute_id' => $attribute->id,
            'value' => 'Cotton',
        ]);

        $this->assertDatabaseHas('product_attribute_values', [
            'product_attribute_id' => $attribute->id,
            'value' => 'Silk',
        ]);
    }

    /**
     * Test variant name options select integration in ProductForm.
     */
    public function test_predefined_attributes_are_used_and_serialized_in_product_variants(): void
    {
        // Seed an attribute
        $attribute = ProductAttribute::create(['name' => 'Material']);
        ProductAttributeValue::create(['product_attribute_id' => $attribute->id, 'value' => 'Leather']);
        ProductAttributeValue::create(['product_attribute_id' => $attribute->id, 'value' => 'Canvas']);

        $this->actingAs($this->admin);

        \Livewire\Livewire::actingAs($this->admin);
        \Filament\Facades\Filament::setCurrentPanel(\Filament\Facades\Filament::getPanel('admin'));

        // Check options serialization when creating a product variant
        \Livewire\Livewire::test(\App\Filament\Resources\Products\Pages\EditProduct::class, [
            'record' => $this->product->id,
        ])
            ->fillForm([
                'variants' => [
                    [
                        'sku' => 'TP-VAR-01',
                        'price' => 600.00,
                        'quantity' => 5,
                        'options' => [
                            [
                                'attribute_name' => 'Material',
                                'attribute_value' => 'Leather'
                            ]
                        ]
                    ]
                ]
            ])
            ->call('save')
            ->assertHasNoErrors();

        // Check database format is key-value JSON (compatibility preserved!)
        $this->assertDatabaseHas('product_variants', [
            'product_id' => $this->product->id,
            'sku' => 'TP-VAR-01',
            'price' => 600.00,
            'quantity' => 5,
            'options' => json_encode(['Material' => 'Leather']),
        ]);

        // Verify that it is correctly hydrated back to the form structure on edit
        $variant = ProductVariant::where('sku', 'TP-VAR-01')->first();
        $this->assertNotNull($variant);

        \Livewire\Livewire::test(\App\Filament\Resources\Products\Pages\EditProduct::class, [
            'record' => $this->product->id,
        ])
            ->tap(function ($livewire) use ($variant) {
                $variants = $livewire->get('data.variants');
                $firstVariant = reset($variants);
                $this->assertEquals('TP-VAR-01', $firstVariant['sku']);
                
                // Form repeater format is transformed from database JSON key-value
                $options = $firstVariant['options'];
                $firstOption = reset($options);
                $this->assertEquals('Material', $firstOption['attribute_name']);
                $this->assertEquals('Leather', $firstOption['attribute_value']);
            });
    }
}
