<?php

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

return new class extends Migration
{
    public function up(): void
    {
        if (Schema::hasTable('task_collections')) {
            if (Schema::hasColumn('task_collections', 'tenant_id')) {
                Schema::table('task_collections', function (Blueprint $table) {
                    $table->dropForeign(['tenant_id']);
                });

                Schema::table('task_collections', function (Blueprint $table) {
                    $table->unsignedBigInteger('tenant_id')->nullable()->change();
                });

                Schema::table('task_collections', function (Blueprint $table) {
                    $table->foreign('tenant_id')
                        ->references('id')
                        ->on('tenants')
                        ->nullOnDelete();
                });
            }

            Schema::table('task_collections', function (Blueprint $table) {
                if (! Schema::hasColumn('task_collections', 'slug')) {
                    $table->string('slug')->nullable()->after('tenant_id');
                }

                if (! Schema::hasColumn('task_collections', 'name_translations')) {
                    $table->json('name_translations')->nullable()->after('slug');
                }

                if (! Schema::hasColumn('task_collections', 'description_translations')) {
                    $table->json('description_translations')->nullable()->after('name_translations');
                }

                if (! Schema::hasColumn('task_collections', 'event_type_id')) {
                    $table->foreignId('event_type_id')
                        ->nullable()
                        ->after('description_translations')
                        ->constrained()
                        ->nullOnDelete();
                }
            });

            if (Schema::hasColumn('task_collections', 'name')) {
                DB::table('task_collections')
                    ->select('id', 'name', 'description', 'slug')
                    ->orderBy('id')
                    ->chunk(100, function ($rows) {
                        foreach ($rows as $row) {
                            $name = $row->name;
                            $description = $row->description;

                            $translations = [
                                'de' => $name,
                            ];

                            $descriptionTranslations = $description
                                ? [
                                    'de' => $description,
                                ]
                                : null;

                            $slugBase = Str::slug($name ?: ('collection-' . $row->id));

                            if (empty($slugBase)) {
                                $slugBase = 'collection-' . $row->id;
                            }

                            $slug = $row->slug ?: ($slugBase . '-' . $row->id);

                            DB::table('task_collections')
                                ->where('id', $row->id)
                                ->update([
                                    'name_translations' => json_encode($translations, JSON_UNESCAPED_UNICODE),
                                    'description_translations' => $descriptionTranslations
                                        ? json_encode($descriptionTranslations, JSON_UNESCAPED_UNICODE)
                                        : null,
                                    'slug' => $slug,
                                ]);
                        }
                    });

                Schema::table('task_collections', function (Blueprint $table) {
                    $table->dropColumn(['name', 'description']);
                });

                Schema::table('task_collections', function (Blueprint $table) {
                    $table->unique('slug');
                });
            }
        }

        if (Schema::hasTable('tasks')) {
            if (Schema::hasColumn('tasks', 'tenant_id')) {
                Schema::table('tasks', function (Blueprint $table) {
                    $table->dropForeign(['tenant_id']);
                });

                Schema::table('tasks', function (Blueprint $table) {
                    $table->unsignedBigInteger('tenant_id')->nullable()->change();
                });

                Schema::table('tasks', function (Blueprint $table) {
                    $table->foreign('tenant_id')
                        ->references('id')
                        ->on('tenants')
                        ->nullOnDelete();
                });
            }

            Schema::table('tasks', function (Blueprint $table) {
                if (! Schema::hasColumn('tasks', 'slug')) {
                    $table->string('slug')->nullable()->after('id');
                }
            });

            if (! Schema::hasColumn('tasks', 'slug')) {
                return;
            }

                DB::table('tasks')
                    ->select('id', 'slug', 'title')
                    ->orderBy('id')
                    ->chunk(100, function ($rows) {
                        foreach ($rows as $row) {
                        if (! empty($row->slug)) {
                            continue;
                        }

                        $titleData = $row->title;

                        if (is_string($titleData)) {
                            $json = json_decode($titleData, true);
                        } else {
                            $json = $titleData;
                        }

                        $base = $json['de']
                            ?? $json['en']
                            ?? ('task-' . $row->id);

                        $slug = Str::slug($base);

                        if (empty($slug)) {
                            $slug = 'task-' . $row->id;
                        }

                        DB::table('tasks')
                            ->where('id', $row->id)
                            ->update([
                                'slug' => $slug . '-' . $row->id,
                            ]);
                        }
                    });

            Schema::table('tasks', function (Blueprint $table) {
                $table->unique('slug');
            });
        }
    }

    public function down(): void
    {
        if (Schema::hasTable('tasks')) {
            $fallbackTenantId = DB::table('tenants')->orderBy('id')->value('id');

            if ($fallbackTenantId) {
                DB::table('tasks')->whereNull('tenant_id')->update(['tenant_id' => $fallbackTenantId]);
            }

            if (Schema::hasColumn('tasks', 'slug')) {
                Schema::table('tasks', function (Blueprint $table) {
                    $table->dropUnique(['slug']);
                    $table->dropColumn('slug');
                });
            }

            if (Schema::hasColumn('tasks', 'tenant_id')) {
                Schema::table('tasks', function (Blueprint $table) {
                    $table->dropForeign(['tenant_id']);
                });

                Schema::table('tasks', function (Blueprint $table) {
                    $table->unsignedBigInteger('tenant_id')->nullable(false)->change();
                });

                Schema::table('tasks', function (Blueprint $table) {
                    $table->foreign('tenant_id')
                        ->references('id')
                        ->on('tenants')
                        ->cascadeOnDelete();
                });
            }
        }

        if (Schema::hasTable('task_collections')) {
            $fallbackTenantId = DB::table('tenants')->orderBy('id')->value('id');

            if ($fallbackTenantId) {
                DB::table('task_collections')->whereNull('tenant_id')->update(['tenant_id' => $fallbackTenantId]);
            }

            if (Schema::hasColumn('task_collections', 'name_translations') &&
                ! Schema::hasColumn('task_collections', 'name')) {
                Schema::table('task_collections', function (Blueprint $table) {
                    $table->string('name')->default('')->after('tenant_id');
                    $table->text('description')->nullable()->after('name');
                });

                DB::table('task_collections')
                    ->select('id', 'name_translations', 'description_translations')
                    ->orderBy('id')
                    ->chunk(100, function ($rows) {
                        foreach ($rows as $row) {
                            $names = is_string($row->name_translations)
                                ? json_decode($row->name_translations, true) ?: []
                                : ($row->name_translations ?? []);

                            $descriptions = is_string($row->description_translations)
                                ? json_decode($row->description_translations, true) ?: []
                                : ($row->description_translations ?? []);

                            DB::table('task_collections')
                                ->where('id', $row->id)
                                ->update([
                                    'name' => $names['de'] ?? $names['en'] ?? 'Collection ' . $row->id,
                                    'description' => $descriptions['de'] ?? $descriptions['en'] ?? null,
                                ]);
                        }
                    });

                Schema::table('task_collections', function (Blueprint $table) {
                    if (Schema::hasColumn('task_collections', 'description_translations')) {
                        $table->dropColumn('description_translations');
                    }

                    if (Schema::hasColumn('task_collections', 'name_translations')) {
                        $table->dropColumn('name_translations');
                    }
                });
            }

            if (Schema::hasColumn('task_collections', 'event_type_id')) {
                Schema::table('task_collections', function (Blueprint $table) {
                    $table->dropForeign(['event_type_id']);
                    $table->dropColumn('event_type_id');
                });
            }

            if (Schema::hasColumn('task_collections', 'slug')) {
                Schema::table('task_collections', function (Blueprint $table) {
                    $table->dropUnique(['slug']);
                    $table->dropColumn('slug');
                });
            }

            if (Schema::hasColumn('task_collections', 'tenant_id')) {
                Schema::table('task_collections', function (Blueprint $table) {
                    $table->dropForeign(['tenant_id']);
                    $table->unsignedBigInteger('tenant_id')->nullable(false)->change();
                    $table->foreign('tenant_id')
                        ->references('id')
                        ->on('tenants')
                        ->cascadeOnDelete();
                });
            }
        }
    }
};
