<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;

return new class extends Migration
{
    private const TENANT_CODE = 'desfile_pura_tendencia';

    public function up(): void
    {
        $this->swapRowAndSeat(
            array_map('strval', range(1, 5)),
            array_map('strval', range(1, 17)),
        );
    }

    public function down(): void
    {
        $this->swapRowAndSeat(
            array_map('strval', range(1, 17)),
            array_map('strval', range(1, 5)),
        );
    }

    /**
     * @param  list<string>  $rowOptions
     * @param  list<string>  $seatOptions
     */
    private function swapRowAndSeat(array $rowOptions, array $seatOptions): void
    {
        DB::transaction(function () use ($rowOptions, $seatOptions): void {
            $entryId = DB::table('catalog_items')
                ->where('tenant_code', self::TENANT_CODE)
                ->where('slug', 'entrada')
                ->value('id');

            if ($entryId === null) {
                return;
            }

            $attributes = DB::table('attribute')
                ->where('tenant_codigo', self::TENANT_CODE)
                ->whereIn('codigo', ['tipo', 'sector', 'fila', 'asiento'])
                ->pluck('id', 'codigo');

            if (! $attributes->has(['tipo', 'sector', 'fila', 'asiento'])) {
                return;
            }

            $this->replaceOptions((int) $attributes['fila'], $rowOptions);
            $this->replaceOptions((int) $attributes['asiento'], $seatOptions);

            $itemAttributes = DB::table('item_attributes')
                ->join('attribute', 'attribute.id', '=', 'item_attributes.attribute_id')
                ->where('item_attributes.catalog_item_id', $entryId)
                ->whereIn('attribute.codigo', ['tipo', 'sector', 'fila', 'asiento'])
                ->pluck('item_attributes.id', 'attribute.codigo');

            if (! $itemAttributes->has(['tipo', 'sector', 'fila', 'asiento'])) {
                return;
            }

            foreach (['tipo' => 1, 'sector' => 2, 'fila' => 3, 'asiento' => 4] as $code => $sortOrder) {
                DB::table('item_attributes')->where('id', $itemAttributes[$code])->update([
                    'sort_order' => $sortOrder,
                ]);
            }

            $definitions = DB::table('variant_values')
                ->join('item_attributes', 'item_attributes.id', '=', 'variant_values.item_attribute_id')
                ->join('attribute', 'attribute.id', '=', 'item_attributes.attribute_id')
                ->join('variantes', 'variantes.id', '=', 'variant_values.variant_id')
                ->where('variantes.catalog_item_id', $entryId)
                ->whereIn('attribute.codigo', ['tipo', 'sector', 'fila', 'asiento'])
                ->get([
                    'variant_values.id',
                    'variant_values.variant_id',
                    'variant_values.value',
                    'attribute.codigo',
                ])
                ->groupBy('variant_id');

            foreach ($definitions as $variantId => $variantDefinitions) {
                $values = $variantDefinitions->keyBy('codigo');
                $row = $values->get('fila');
                $seat = $values->get('asiento');

                if ($row === null || $seat === null) {
                    continue;
                }

                DB::table('variant_values')->where('id', $row->id)->update(['value' => $seat->value]);
                DB::table('variant_values')->where('id', $seat->id)->update(['value' => $row->value]);

                $type = $values->get('tipo')?->value;
                $sector = $values->get('sector')?->value;
                if ($type !== null && $sector !== null) {
                    DB::table('variantes')->where('id', $variantId)->update([
                        'descripcion' => "Sector {$sector} - Fila {$seat->value} - Asiento {$row->value} - {$type}",
                    ]);
                }
            }
        });
    }

    /** @param list<string> $options */
    private function replaceOptions(int $attributeId, array $options): void
    {
        DB::table('attribute_options')->where('attribute_id', $attributeId)->delete();

        $now = now();
        DB::table('attribute_options')->insert(array_map(
            fn (string $option, int $index): array => [
                'attribute_id' => $attributeId,
                'validity_time_id' => null,
                'value' => $option,
                'label' => $option,
                'sort_order' => $index + 1,
                'metadata' => null,
                'created_at' => $now,
                'updated_at' => $now,
            ],
            $options,
            array_keys($options),
        ));
    }
};
