<?php

namespace Tests\Unit\Purchase;

use App\Domains\Catalog\Enums\InventorySubject;
use App\Domains\Catalog\Models\Attribute;
use App\Domains\Catalog\Models\AttributeOption;
use App\Domains\Catalog\Models\CatalogItem;
use App\Domains\Catalog\Models\ItemAttribute;
use App\Domains\Catalog\Models\Variant;
use App\Domains\Catalog\Models\VariantDefinition;
use App\Domains\Purchase\Exceptions\InsufficientStockException;
use App\Domains\Purchase\Services\Checkout\InsufficientStockMessageBuilder;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Support\Facades\App;
use Tests\TestCase;

class InsufficientStockMessageBuilderTest extends TestCase
{
    public function test_insufficient_stock_exception_exposes_every_conflicting_variant(): void
    {
        $exception = new InsufficientStockException([
            [
                'index' => 1,
                'catalog_item_id' => 10,
                'variant_id' => 102,
                'requested_quantity' => 1,
                'available_quantity' => 0,
                'message' => 'El asiento A2 ya no está disponible.',
            ],
            [
                'index' => 3,
                'catalog_item_id' => 10,
                'variant_id' => 104,
                'requested_quantity' => 1,
                'available_quantity' => 0,
                'message' => 'El asiento B4 ya no está disponible.',
            ],
        ]);

        $this->assertSame(
            'El asiento A2 ya no está disponible. El asiento B4 ya no está disponible.',
            $exception->getMessage(),
        );
        $this->assertSame([
            'direct_items.1.cantidad' => ['El asiento A2 ya no está disponible.'],
            'direct_items.3.cantidad' => ['El asiento B4 ya no está disponible.'],
        ], $exception->errors());
        $this->assertSame([102, 104], collect($exception->unavailableItems)->pluck('variant_id')->all());
    }

    public function test_it_builds_a_localized_seat_message_from_the_variant_selection(): void
    {
        [$catalogItem, $variant] = $this->seatSelection();
        $builder = app(InsufficientStockMessageBuilder::class);

        App::setLocale('es');
        $this->assertSame(
            'Sector A · Fila 2 · Asiento 3',
            $variant->getSelectionLabel(),
        );
        $this->assertSame(
            'El asiento Sector A · Fila 2 · Asiento 3 ya no está disponible.',
            $builder->build($catalogItem, $variant, 0),
        );

        App::setLocale('en');
        $this->assertSame(
            'Sector A · Row 2 · Seat 3',
            $variant->getSelectionLabel(),
        );
        $this->assertSame(
            'Seat Sector A · Row 2 · Seat 3 is no longer available.',
            $builder->build($catalogItem, $variant, 0),
        );
    }

    /** @return array{CatalogItem, Variant} */
    private function seatSelection(): array
    {
        $catalogItem = new CatalogItem([
            'nombre' => 'Entrada',
            'inventory_subject' => InventorySubject::Seat->value,
        ]);
        $itemAttributes = collect([
            ['id' => 1, 'code' => 'sector', 'name' => 'Sector', 'value' => 'A'],
            ['id' => 2, 'code' => 'fila', 'name' => 'Fila', 'value' => '2'],
            ['id' => 3, 'code' => 'asiento', 'name' => 'Asiento', 'value' => '3'],
        ])->map(function (array $data): ItemAttribute {
            $attribute = new Attribute([
                'codigo' => $data['code'],
                'nombre' => $data['name'],
            ]);
            $attribute->setRelation('options', new EloquentCollection([
                new AttributeOption([
                    'value' => $data['value'],
                    'label' => $data['value'],
                ]),
            ]));

            $itemAttribute = new ItemAttribute([
                'sort_order' => $data['id'],
                'allow_multi_select' => false,
            ]);
            $itemAttribute->id = $data['id'];
            $itemAttribute->setRelation('attribute', $attribute);

            return $itemAttribute;
        })->values();

        $catalogItem->setRelation('itemAttributes', new EloquentCollection($itemAttributes));

        $definitions = $itemAttributes->map(function (ItemAttribute $itemAttribute): VariantDefinition {
            $value = $itemAttribute->attribute->options->first()->value;
            $definition = new VariantDefinition(['value' => $value]);
            $definition->item_attribute_id = $itemAttribute->id;
            $definition->setRelation('itemAttribute', $itemAttribute);

            return $definition;
        });

        $variant = new Variant;
        $variant->setRelation('catalogItem', $catalogItem);
        $variant->setRelation('definitions', new EloquentCollection($definitions));
        $variant->setRelation('eventDates', new EloquentCollection);
        $variant->setRelation('eventDate', null);

        return [$catalogItem, $variant];
    }
}
