<?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;
use Livewire\Livewire;

class SkuGenerationTest extends TestCase
{
    use RefreshDatabase;

    private User $admin;
    private $category;

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

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

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

    /**
     * Test the static generateUniqueSku helper function on the Product model.
     */
    public function test_generate_unique_sku_from_product_name(): void
    {
        // Multi-word name
        $sku1 = Product::generateUniqueSku('Premium Silk Shirt');
        $this->assertMatchesRegularExpression('/^PSS-\d{4}$/', $sku1);

        // Single word name
        $sku2 = Product::generateUniqueSku('Chino');
        $this->assertMatchesRegularExpression('/^CHIN-\d{4}$/', $sku2);

        // Special characters name
        $sku3 = Product::generateUniqueSku('Zip Jacket 123');
        $this->assertMatchesRegularExpression('/^ZJ1-\d{4}$/', $sku3);

        // Empty/Fallback case
        $sku4 = Product::generateUniqueSku('');
        $this->assertMatchesRegularExpression('/^PROD-\d{4}$/', $sku4);
    }

    /**
     * Test SKU uniqueness/collision handling.
     */
    public function test_generate_unique_sku_prevents_duplicate_collisions(): void
    {
        // Force mock two products having same name
        $sku = Product::generateUniqueSku('Cool Jacket');
        
        Product::create([
            'name' => 'Cool Jacket 1',
            'slug' => 'cool-jacket-1',
            'sku' => $sku,
            'price' => 100.00,
            'compare_at_price' => 120.00,
            'cost_price' => 80.00,
            'quantity' => 5,
            'published_at' => now(),
            'category_id' => $this->category->id,
        ]);

        // Generate SKU again for same name, should generate a different one
        $newSku = Product::generateUniqueSku('Cool Jacket');
        
        $this->assertNotEquals($sku, $newSku);
    }

    /**
     * Test that SKU auto-fills on name update if SKU is empty.
     */
    public function test_form_auto_fills_sku_on_name_update(): void
    {
        Livewire::actingAs($this->admin);
        \Filament\Facades\Filament::setCurrentPanel(\Filament\Facades\Filament::getPanel('admin'));

        Livewire::test(\App\Filament\Resources\Products\Pages\CreateProduct::class)
            ->fillForm([
                'name' => 'Winter Leather Gloves',
            ])
            ->assertFormSet([
                'slug' => 'winter-leather-gloves',
            ])
            ->tap(function ($component) {
                $sku = $component->get('data.sku');
                $this->assertNotEmpty($sku);
                $this->assertMatchesRegularExpression('/^WLG-\d{4}$/', $sku);
            });
    }

    /**
     * Test that SKU manual generation suffix action works.
     */
    public function test_manual_sku_generation_action_works(): void
    {
        Livewire::actingAs($this->admin);
        \Filament\Facades\Filament::setCurrentPanel(\Filament\Facades\Filament::getPanel('admin'));

        Livewire::test(\App\Filament\Resources\Products\Pages\CreateProduct::class)
            ->fillForm([
                'name' => 'Original Item',
                'sku' => '',
            ])
            // Trigger suffix action 'generateSku'
            ->callFormComponentAction('sku', 'generateSku')
            ->tap(function ($component) {
                $sku = $component->get('data.sku');
                $this->assertNotEmpty($sku);
                $this->assertMatchesRegularExpression('/^OI-\d{4}$/', $sku);
            });
    }

    /**
     * Test variant SKU is auto-filled when options are selected.
     */
    public function test_variant_sku_auto_fills_on_options_updated(): void
    {
        $attribute = ProductAttribute::where('name', 'Size')->first();
        if (!$attribute) {
            $attribute = ProductAttribute::create(['name' => 'Size']);
        }
        if (!ProductAttributeValue::where('product_attribute_id', $attribute->id)->where('value', 'XL')->exists()) {
            ProductAttributeValue::create(['product_attribute_id' => $attribute->id, 'value' => 'XL']);
        }

        // Create product first
        $product = Product::create([
            'name' => 'Denim Shirt',
            'slug' => 'denim-shirt',
            'sku' => 'DS-1002',
            'price' => 450.00,
            'compare_at_price' => 500.00,
            'cost_price' => 300.00,
            'quantity' => 15,
            'published_at' => now(),
            'category_id' => $this->category->id,
        ]);

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

        Livewire::test(\App\Filament\Resources\Products\Pages\EditProduct::class, [
            'record' => $product->id,
        ])
            // Set variant details and its options
            ->fillForm([
                'variants' => [
                    [
                        'sku' => '',
                        'price' => 500.00,
                        'quantity' => 10,
                        'options' => [
                            [
                                'attribute_name' => 'Size',
                                'attribute_value' => 'XL',
                            ]
                        ]
                    ]
                ]
            ])
            ->tap(function ($component) {
                $variants = $component->get('data.variants');
                $firstVariant = reset($variants);
                $this->assertEquals('DS-1002-XL', $firstVariant['sku']);
            });
    }
}
