<?php

namespace Tests\Feature\Catalog;

use App\Domains\Attachable\Enums\AttachmentType;
use App\Domains\Attachable\Models\Attachment;
use App\Domains\Catalog\Models\Attribute;
use App\Domains\Catalog\Models\CatalogItem;
use App\Domains\Shared\Enums\FieldType;
use App\Domains\Tenant\Models\Tenant;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;

class CatalogItemControllerTest extends TestCase
{
    use RefreshDatabase;

    public function test_it_creates_a_catalog_item_with_item_and_variant_images(): void
    {
        Storage::fake('s3');
        $tenant = $this->createTenant();
        $attribute = Attribute::query()->create([
            'tenant_codigo' => $tenant->codigo,
            'codigo' => 'size',
            'nombre' => 'Size',
            'type' => FieldType::String,
        ]);
        $image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==';

        $response = $this->postJson("/api/tenants/{$tenant->codigo}/catalog-items", [
            'slug' => 'shirt',
            'nombre' => 'Shirt',
            'group_order' => 7,
            'precio' => 100,
            'max_units_per_user' => 4,
            'attribute_codes' => [$attribute->codigo],
            'images' => [$image, $image],
            'variants' => [
                [
                    'real_stock' => 5,
                    'values' => ['size' => 'M'],
                    'images' => [$image],
                ],
            ],
        ]);

        $response
            ->assertCreated()
            ->assertJsonPath('data.nombre', 'Shirt')
            ->assertJsonMissingPath('data.group_order')
            ->assertJsonPath('data.max_units_per_user', 4)
            ->assertJsonCount(2, 'data.images')
            ->assertJsonCount(1, 'data.variants')
            ->assertJsonCount(1, 'data.variants.0.images');

        $item = CatalogItem::query()->where('slug', 'shirt')->firstOrFail();
        $variant = $item->variants()->firstOrFail();

        $this->assertSame([0, 1], $item->attachments()->get()->pluck('pivot.orden')->all());
        $this->assertSame(4, $item->max_units_per_user);
        $this->assertSame(7, $item->group_order);
        $this->assertSame([0], $variant->attachments()->get()->pluck('pivot.orden')->all());
        $this->assertDatabaseHas('catalog_items_attachments', [
            'catalog_item_id' => $item->id,
            'variant_id' => $variant->id,
            'orden' => 0,
            'is_enabled' => true,
        ]);
    }

    public function test_it_validates_images_before_creating_the_catalog_item(): void
    {
        $tenant = $this->createTenant('validation');

        $this->postJson("/api/tenants/{$tenant->codigo}/catalog-items", [
            'slug' => 'invalid-image',
            'nombre' => 'Invalid image',
            'precio' => 100,
            'real_stock' => 1,
            'images' => ['not-an-image'],
        ])->assertUnprocessable()->assertJsonValidationErrors('images.0');

        $this->assertDatabaseMissing('catalog_items', ['slug' => 'invalid-image']);
    }

    public function test_it_rejects_a_non_positive_user_purchase_limit(): void
    {
        $tenant = $this->createTenant('purchase-limit-validation');

        $this->postJson("/api/tenants/{$tenant->codigo}/catalog-items", [
            'slug' => 'invalid-purchase-limit',
            'nombre' => 'Invalid purchase limit',
            'precio' => 100,
            'real_stock' => 10,
            'max_units_per_user' => 0,
        ])->assertUnprocessable()->assertJsonValidationErrors('max_units_per_user');

        $this->assertDatabaseMissing('catalog_items', ['slug' => 'invalid-purchase-limit']);
    }

    private function createTenant(string $code = 'catalog-controller'): Tenant
    {
        $headerLogo = $this->createAttachment("{$code}-header");
        $footerLogo = $this->createAttachment("{$code}-footer");

        return Tenant::query()->create([
            'codigo' => $code,
            'nombre' => ucfirst($code),
            'dominio' => "{$code}.local",
            'primary_color' => '#000000',
            'secondary_color' => '#000000',
            'danger_color' => '#000000',
            'success_color' => '#000000',
            'header_bg_color' => '#000000',
            'footer_bg_color' => '#000000',
            'header_logo_id' => $headerLogo->id,
            'footer_logo_id' => $footerLogo->id,
        ]);
    }

    private function createAttachment(string $name): Attachment
    {
        return Attachment::query()->create([
            'path' => "test/{$name}.png",
            'filename' => "{$name}.png",
            'type' => AttachmentType::Image,
            'mime_type' => 'image/png',
        ]);
    }
}
