<?php

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

return new class extends Migration
{
    private const LEGACY_PRODUCT_VARIANT = 'App\\Domains\\Catalog\\Models\\ProductVariant';

    private const LEGACY_BUNDLE = 'App\\Domains\\Bundle\\Models\\Bundle';

    public function up(): void
    {
        Schema::table('carrito_items', function (Blueprint $table): void {
            $table->foreignId('catalog_item_id')->nullable()->after('cart_id');
            $table->foreignId('variant_id')->nullable()->after('catalog_item_id');
        });

        DB::table('carrito_items')->orderBy('id')->each(function (object $cartItem): void {
            if ($cartItem->buyable_type !== self::LEGACY_PRODUCT_VARIANT) {
                if ($cartItem->buyable_type === self::LEGACY_BUNDLE) {
                    DB::table('bundle_items')
                        ->where('bundle_id', $cartItem->buyable_id)
                        ->orderBy('id')
                        ->each(function (object $bundleItem) use ($cartItem): void {
                            $variant = DB::table('variantes')
                                ->select('inventory_id')
                                ->where('id', $bundleItem->producto_variante_id)
                                ->first();

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

                            $inventory = DB::table('inventories')
                                ->select('reserved_stock')
                                ->where('id', $variant->inventory_id)
                                ->first();

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

                            $reservedAmount = $cartItem->cantidad * $bundleItem->cantidad;
                            DB::table('inventories')->where('id', $variant->inventory_id)->update([
                                'reserved_stock' => max(0, $inventory->reserved_stock - $reservedAmount),
                            ]);
                        });
                }

                DB::table('carrito_items')->where('id', $cartItem->id)->delete();

                return;
            }

            $variant = DB::table('variantes')
                ->select(['id', 'catalog_item_id'])
                ->where('id', $cartItem->buyable_id)
                ->first();

            if ($variant === null) {
                DB::table('carrito_items')->where('id', $cartItem->id)->delete();

                return;
            }

            DB::table('carrito_items')->where('id', $cartItem->id)->update([
                'catalog_item_id' => $variant->catalog_item_id,
                'variant_id' => $variant->id,
            ]);
        });

        Schema::table('carrito_items', function (Blueprint $table): void {
            $table->dropUnique(['cart_id', 'buyable_type', 'buyable_id']);
            $table->dropColumn(['buyable_type', 'buyable_id']);
        });

        Schema::table('carrito_items', function (Blueprint $table): void {
            $table->unsignedBigInteger('catalog_item_id')->nullable(false)->change();
            $table->foreign('catalog_item_id')->references('id')->on('catalog_items')->cascadeOnDelete();
            $table->foreign('variant_id')->references('id')->on('variantes')->cascadeOnDelete();
            $table->unique(
                ['cart_id', 'catalog_item_id', 'variant_id'],
                'cart_catalog_item_variant_unique'
            );
        });
    }

    public function down(): void
    {
        throw new RuntimeException('This destructive cart migration cannot be reversed.');
    }
};
