<?php

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

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

    private const SOURCE_TENANT_CODE = 'fiesta_futbol_infantil';

    /** @var list<string> */
    private array $storedPaths = [];

    public function up(): void
    {
        if (DB::table('tenants')->where('codigo', self::TENANT_CODE)->exists()) {
            return;
        }

        $heroExtraId = DB::table('website_type_extras')
            ->where('website_type_code', 'onticket')
            ->where('codigo', 'heroConfig')
            ->value('id');

        if (
            $heroExtraId === null
            || ! DB::table('website_type')->where('codigo', 'onticket')->exists()
            || ! DB::table('tenants')->where('codigo', self::SOURCE_TENANT_CODE)->exists()
        ) {
            // This data migration targets installations whose reference data was
            // already provisioned. Fresh test databases do not contain seed data.
            return;
        }

        try {
            DB::transaction(function () use ($heroExtraId): void {
                $headerLogoId = $this->storeImage(
                    'images/tennants/desfile_pura_tendencia/desfile_pura_tendencia_header.png',
                    'desfile_pura_tendencia_header.png',
                    'tenants/'.self::TENANT_CODE,
                );
                $footerLogoId = $this->storeImage(
                    'images/tennants/desfile_pura_tendencia/desfile_pura_tendencia_footer.png',
                    'desfile_pura_tendencia_footer.png',
                    'tenants/'.self::TENANT_CODE,
                );
                $heroImageId = $this->storeImage(
                    'images/tennants/desfile_pura_tendencia/desfile_pura_tendencia_hero.png',
                    'desfile_pura_tendencia_hero.png',
                    'tenants/'.self::TENANT_CODE.'/extras/heroConfig',
                );

                $now = now();

                DB::table('tenants')->insert([
                    'codigo' => self::TENANT_CODE,
                    'nombre' => 'Desfile Pura Tendencia',
                    'dominio' => 'desfile-pura-tendencia.localhost',
                    'event_title' => 'Desfile Pura Tendencia',
                    'event_location' => 'Salón Centro Recreativo Luz y Fuerza',
                    'event_date_text' => '16 de Octubre 2026',
                    'primary_color' => '#BA69A9',
                    'secondary_color' => '#A0A0A0',
                    'danger_color' => '#FF8888',
                    'success_color' => '#198754',
                    'header_bg_color' => '#ffffff',
                    'footer_bg_color' => '#D4441C',
                    'header_logo_id' => $headerLogoId,
                    'footer_logo_id' => $footerLogoId,
                    'website_type_code' => 'onticket',
                    'display_categories' => false,
                    'display_seach_bar' => false,
                    'created_at' => $now,
                    'updated_at' => $now,
                ]);

                $validityTimeId = DB::table('validity_times')->insertGetId([
                    'type' => 'fixed_window',
                    'start_time' => null,
                    'end_time' => null,
                    'fixed_starts_at' => '2026-10-16 20:30:00',
                    'fixed_expires_at' => '2026-10-16 23:59:00',
                    'created_at' => $now,
                    'updated_at' => $now,
                ]);

                DB::table('event_dates')->insert([
                    'tenant_code' => self::TENANT_CODE,
                    'validity_time_id' => $validityTimeId,
                    'date' => '2026-10-16',
                    'time_start' => '20:30:00',
                    'time_end' => '23:59:00',
                ]);

                $this->createEntryCatalog($validityTimeId, $now);

                DB::table('websites_extras')->insert([
                    'website_code' => self::TENANT_CODE,
                    'website_type_extra_id' => $heroExtraId,
                    'config' => json_encode([
                        'title_html' => '<h1>LA NOCHE DE LA MODA</h1>',
                        'description_html' => 'Viví una experiencia de <b>Alta Costura con conducción exclusiva de Pampita</b> y las colecciones de Pucheta-Paz.',
                        'background_image_id' => $heroImageId,
                    ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
                    'is_enabled' => true,
                    'created_at' => $now,
                    'updated_at' => $now,
                ]);

                $menuAssignments = DB::table('tenants_menues')
                    ->where('tenant_code', self::SOURCE_TENANT_CODE)
                    ->where('menu_code', 'not like', 'adminapp.fiesta-futbol-infantil.%')
                    ->orderBy('id')
                    ->get(['menu_code', 'static_content']);

                foreach ($menuAssignments as $assignment) {
                    DB::table('tenants_menues')->insert([
                        'tenant_code' => self::TENANT_CODE,
                        'menu_code' => $assignment->menu_code,
                        'static_content' => $assignment->static_content,
                        'created_at' => $now,
                        'updated_at' => $now,
                    ]);
                }
            });
        } catch (Throwable $throwable) {
            Storage::disk('s3')->delete($this->storedPaths);

            throw $throwable;
        }
    }

    public function down(): void
    {
        // Intentionally irreversible: once active, this tenant can own users,
        // purchases, tickets and catalog data that a rollback must not delete.
    }

    private function storeImage(string $relativePath, string $filename, string $directory): int
    {
        $sourcePath = public_path($relativePath);

        if (! is_file($sourcePath)) {
            throw new RuntimeException("Image not found at path: {$sourcePath}");
        }

        $contents = file_get_contents($sourcePath);

        if ($contents === false) {
            throw new RuntimeException("Could not read image at path: {$sourcePath}");
        }

        $key = (string) Str::uuid();
        $storedPath = trim($directory, '/').'/'.$key.'.png';

        if (! Storage::disk('s3')->put($storedPath, $contents)) {
            throw new RuntimeException("Could not store image at path: {$storedPath}");
        }

        $this->storedPaths[] = $storedPath;

        return DB::table('attachments')->insertGetId([
            'key' => $key,
            'path' => $storedPath,
            'filename' => $filename,
            'type' => 'image',
            'mime_type' => 'image/png',
            'extension' => 'png',
            'size' => strlen($contents),
            'created_at' => now(),
            'updated_at' => now(),
        ]);
    }

    private function createEntryCatalog(int $validityTimeId, DateTimeInterface $now): void
    {
        $attributes = [
            'tipo' => [
                'name' => 'Tipo',
                'options' => ['VIP + LUNCH', 'NORMAL'],
            ],
            'sector' => [
                'name' => 'Sector',
                'options' => ['A', 'B', 'C', 'D'],
            ],
            'fila' => [
                'name' => 'Fila',
                'options' => array_map('strval', range(1, 17)),
            ],
            'asiento' => [
                'name' => 'Asiento',
                'options' => array_map('strval', range(1, 5)),
            ],
        ];
        $attributeIds = [];

        foreach ($attributes as $code => $definition) {
            $attributeId = DB::table('attribute')->insertGetId([
                'tenant_codigo' => self::TENANT_CODE,
                'codigo' => $code,
                'nombre' => $definition['name'],
                'is_required' => true,
                'metadata_schema' => null,
                'type' => 'select',
                'created_at' => $now,
                'updated_at' => $now,
            ]);
            $attributeIds[$code] = $attributeId;

            foreach ($definition['options'] as $index => $option) {
                DB::table('attribute_options')->insert([
                    'attribute_id' => $attributeId,
                    'validity_time_id' => null,
                    'value' => $option,
                    'label' => $option,
                    'sort_order' => $index + 1,
                    'metadata' => null,
                    'created_at' => $now,
                    'updated_at' => $now,
                ]);
            }
        }

        $catalogItemId = DB::table('catalog_items')->insertGetId([
            'tenant_code' => self::TENANT_CODE,
            'category_id' => null,
            'brand_id' => null,
            'inventory_id' => null,
            'type' => 'standard',
            'slug' => 'entrada',
            'nombre' => 'Entrada',
            'descripcion' => 'Entrada para Desfile Pura Tendencia',
            'precio' => 40000,
            'inventory_policy' => 'tracked',
            'has_tickets' => true,
            'ticket_generation_policy' => 'one_per_unit',
            'validity_time_id' => $validityTimeId,
            'max_units_per_user' => null,
        ]);
        $itemAttributeIds = [];

        foreach (array_keys($attributes) as $index => $code) {
            $itemAttributeIds[$code] = DB::table('item_attributes')->insertGetId([
                'catalog_item_id' => $catalogItemId,
                'attribute_id' => $attributeIds[$code],
                'allow_multi_select' => false,
                'sort_order' => $index + 1,
                'created_at' => $now,
                'updated_at' => $now,
            ]);
        }

        foreach (['A', 'B', 'C', 'D'] as $sector) {
            $lastRow = in_array($sector, ['B', 'D'], true) ? 16 : 17;

            foreach (range(1, $lastRow) as $row) {
                foreach (range(1, 5) as $seat) {
                    [$type, $price] = $this->entryTypeAndPrice($sector, $seat);
                    $inventoryId = DB::table('inventories')->insertGetId([
                        'sold_units' => 0,
                        'reserved_stock' => 0,
                        'real_stock' => 1,
                    ]);
                    $variantId = DB::table('variantes')->insertGetId([
                        'catalog_item_id' => $catalogItemId,
                        'event_date_id' => null,
                        'inventory_id' => $inventoryId,
                        'descripcion' => "Sector {$sector} - Fila {$row} - Asiento {$seat} - {$type}",
                        'precio' => $price,
                    ]);

                    foreach ([
                        'tipo' => $type,
                        'sector' => $sector,
                        'fila' => (string) $row,
                        'asiento' => (string) $seat,
                    ] as $code => $value) {
                        DB::table('variant_values')->insert([
                            'variant_id' => $variantId,
                            'item_attribute_id' => $itemAttributeIds[$code],
                            'value' => $value,
                            'created_at' => $now,
                            'updated_at' => $now,
                        ]);
                    }
                }
            }
        }

        $entryImageId = $this->storeImage(
            'images/tennants/desfile_pura_tendencia/catalog/entrada_pasarela.png',
            'entrada_pasarela.png',
            'catalog-items',
        );

        DB::table('catalog_items_attachments')->insert([
            'variant_id' => null,
            'catalog_item_id' => $catalogItemId,
            'attachment_id' => $entryImageId,
            'orden' => 0,
        ]);

        DB::table('featured_groups')->insert([
            'tenant_code' => self::TENANT_CODE,
            'source_type' => 'all',
            'category_id' => null,
            'product_layout' => 'ticket_selector',
            'group_layout' => 'single',
            'group_name' => 'Entradas',
            'group_order' => 0,
        ]);
    }

    /** @return array{string, int} */
    private function entryTypeAndPrice(string $sector, int $seat): array
    {
        $prices = in_array($sector, ['A', 'C'], true)
            ? [1 => 250000, 2 => 200000, 3 => 100000, 4 => 75000, 5 => 50000]
            : [1 => 240000, 2 => 190000, 3 => 90000, 4 => 65000, 5 => 40000];

        return [
            $seat <= 2 ? 'VIP + LUNCH' : 'NORMAL',
            $prices[$seat],
        ];
    }
};
