<?php

declare(strict_types=1);

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

return new class extends Migration
{
    public function up(): void
    {
        Schema::table('nova_cards', function (Blueprint $table): void {
            $table->unsignedSmallInteger('schema_version')->default(1)->after('project_json');
            $table->foreignId('original_card_id')->nullable()->after('background_image_id')->constrained('nova_cards')->nullOnDelete();
            $table->foreignId('root_card_id')->nullable()->after('original_card_id')->constrained('nova_cards')->nullOnDelete();
            $table->boolean('allow_remix')->default(true)->after('allow_download');
            $table->unsignedInteger('likes_count')->default(0)->after('downloads_count');
            $table->unsignedInteger('favorites_count')->default(0)->after('likes_count');
            $table->unsignedInteger('saves_count')->default(0)->after('favorites_count');
            $table->unsignedInteger('remixes_count')->default(0)->after('saves_count');
            $table->unsignedInteger('challenge_entries_count')->default(0)->after('remixes_count');
            $table->timestamp('last_engaged_at')->nullable()->after('published_at');

            $table->index('schema_version');
            $table->index('original_card_id');
            $table->index('root_card_id');
            $table->index('likes_count');
            $table->index('favorites_count');
            $table->index('saves_count');
            $table->index('remixes_count');
        });

        Schema::create('nova_card_reactions', function (Blueprint $table): void {
            $table->id();
            $table->foreignId('card_id')->constrained('nova_cards')->cascadeOnDelete();
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->string('type', 24);
            $table->timestamps();

            $table->unique(['card_id', 'user_id', 'type']);
            $table->index(['type', 'created_at']);
        });

        Schema::create('nova_card_collections', function (Blueprint $table): void {
            $table->id();
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->string('slug', 140);
            $table->string('name', 120);
            $table->text('description')->nullable();
            $table->enum('visibility', ['private', 'public'])->default('private');
            $table->boolean('official')->default(false);
            $table->unsignedInteger('cards_count')->default(0);
            $table->timestamps();

            $table->unique(['user_id', 'slug']);
            $table->index(['visibility', 'updated_at']);
        });

        Schema::create('nova_card_collection_items', function (Blueprint $table): void {
            $table->id();
            $table->foreignId('collection_id')->constrained('nova_card_collections')->cascadeOnDelete();
            $table->foreignId('card_id')->constrained('nova_cards')->cascadeOnDelete();
            $table->text('note')->nullable();
            $table->unsignedInteger('sort_order')->default(0);
            $table->timestamps();

            $table->unique(['collection_id', 'card_id']);
            $table->index(['card_id', 'created_at']);
        });

        Schema::create('nova_card_versions', function (Blueprint $table): void {
            $table->id();
            $table->foreignId('card_id')->constrained('nova_cards')->cascadeOnDelete();
            $table->foreignId('user_id')->nullable()->constrained()->nullOnDelete();
            $table->unsignedInteger('version_number');
            $table->string('label', 120)->nullable();
            $table->string('snapshot_hash', 64);
            $table->json('snapshot_json');
            $table->timestamps();

            $table->unique(['card_id', 'version_number']);
            $table->index(['card_id', 'created_at']);
            $table->index('snapshot_hash');
        });

        Schema::create('nova_card_challenges', function (Blueprint $table): void {
            $table->id();
            $table->foreignId('user_id')->nullable()->constrained()->nullOnDelete();
            $table->string('slug', 140)->unique();
            $table->string('title', 140);
            $table->text('description')->nullable();
            $table->text('prompt')->nullable();
            $table->json('rules_json')->nullable();
            $table->enum('status', ['draft', 'active', 'completed', 'archived'])->default('draft');
            $table->boolean('official')->default(false);
            $table->boolean('featured')->default(false);
            $table->foreignId('winner_card_id')->nullable()->constrained('nova_cards')->nullOnDelete();
            $table->unsignedInteger('entries_count')->default(0);
            $table->timestamp('starts_at')->nullable();
            $table->timestamp('ends_at')->nullable();
            $table->timestamps();

            $table->index(['status', 'featured', 'starts_at']);
        });

        Schema::create('nova_card_challenge_entries', function (Blueprint $table): void {
            $table->id();
            $table->foreignId('challenge_id')->constrained('nova_card_challenges')->cascadeOnDelete();
            $table->foreignId('card_id')->constrained('nova_cards')->cascadeOnDelete();
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->enum('status', ['active', 'hidden', 'rejected', 'featured', 'winner', 'submitted'])->default('active');
            $table->text('note')->nullable();
            $table->timestamps();

            $table->unique(['challenge_id', 'card_id']);
            $table->index(['user_id', 'created_at']);
        });

        Schema::create('nova_card_asset_packs', function (Blueprint $table): void {
            $table->id();
            $table->string('slug', 140)->unique();
            $table->string('name', 120);
            $table->text('description')->nullable();
            $table->enum('type', ['asset', 'template'])->default('asset');
            $table->string('preview_image')->nullable();
            $table->json('manifest_json')->nullable();
            $table->boolean('official')->default(false);
            $table->boolean('active')->default(true);
            $table->unsignedInteger('order_num')->default(0);
            $table->timestamps();

            $table->index(['type', 'active', 'official', 'order_num']);
        });

        Schema::create('nova_card_assets', function (Blueprint $table): void {
            $table->id();
            $table->foreignId('asset_pack_id')->nullable()->constrained('nova_card_asset_packs')->nullOnDelete();
            $table->string('asset_key', 80);
            $table->string('label', 120);
            $table->string('type', 32)->default('glyph');
            $table->string('preview_image')->nullable();
            $table->json('data_json')->nullable();
            $table->boolean('official')->default(false);
            $table->boolean('active')->default(true);
            $table->unsignedInteger('order_num')->default(0);
            $table->timestamps();

            $table->unique(['asset_pack_id', 'asset_key']);
            $table->index(['type', 'active', 'order_num']);
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('nova_card_assets');
        Schema::dropIfExists('nova_card_asset_packs');
        Schema::dropIfExists('nova_card_challenge_entries');
        Schema::dropIfExists('nova_card_challenges');
        Schema::dropIfExists('nova_card_versions');
        Schema::dropIfExists('nova_card_collection_items');
        Schema::dropIfExists('nova_card_collections');
        Schema::dropIfExists('nova_card_reactions');

        Schema::table('nova_cards', function (Blueprint $table): void {
            $table->dropConstrainedForeignId('original_card_id');
            $table->dropConstrainedForeignId('root_card_id');
            $table->dropColumn([
                'schema_version',
                'allow_remix',
                'likes_count',
                'favorites_count',
                'saves_count',
                'remixes_count',
                'challenge_entries_count',
                'last_engaged_at',
            ]);
        });
    }
};