<?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
    {
        Schema::table('conversations', function (Blueprint $table): void {
            if (! Schema::hasColumn('conversations', 'uuid')) {
                $table->uuid('uuid')->nullable()->after('id')->unique();
            }

            if (! Schema::hasColumn('conversations', 'last_message_id')) {
                $table->unsignedBigInteger('last_message_id')->nullable()->after('created_by')->index();
            }

            if (! Schema::hasColumn('conversations', 'is_active')) {
                $table->boolean('is_active')->default(true)->after('last_message_at')->index();
            }
        });

        Schema::table('conversation_participants', function (Blueprint $table): void {
            if (! Schema::hasColumn('conversation_participants', 'last_read_message_id')) {
                $table->unsignedBigInteger('last_read_message_id')->nullable()->after('last_read_at')->index();
            }

            if (! Schema::hasColumn('conversation_participants', 'is_hidden')) {
                $table->boolean('is_hidden')->default(false)->after('is_archived');
            }

            $table->index(['user_id', 'last_read_at'], 'conversation_participants_user_last_read_idx');
        });

        Schema::table('messages', function (Blueprint $table): void {
            if (! Schema::hasColumn('messages', 'uuid')) {
                $table->uuid('uuid')->nullable()->after('id')->unique();
            }

            if (! Schema::hasColumn('messages', 'client_temp_id')) {
                $table->string('client_temp_id', 120)->nullable()->after('uuid');
                $table->index(['conversation_id', 'client_temp_id'], 'messages_conversation_client_temp_idx');
            }

            if (! Schema::hasColumn('messages', 'message_type')) {
                $table->string('message_type', 32)->default('text')->after('sender_id');
            }

            if (! Schema::hasColumn('messages', 'meta_json')) {
                $table->json('meta_json')->nullable()->after('body');
            }

            if (! Schema::hasColumn('messages', 'reply_to_message_id')) {
                $table->unsignedBigInteger('reply_to_message_id')->nullable()->after('meta_json')->index();
            }
        });

        Schema::table('message_attachments', function (Blueprint $table): void {
            if (! Schema::hasColumn('message_attachments', 'disk')) {
                $table->string('disk', 64)->default('local')->after('message_id');
            }
        });

        if (! Schema::hasTable('message_reads')) {
            Schema::create('message_reads', function (Blueprint $table): void {
                $table->id();
                $table->foreignId('message_id')->constrained()->cascadeOnDelete();
                $table->foreignId('user_id')->constrained()->cascadeOnDelete();
                $table->timestamp('read_at');

                $table->unique(['message_id', 'user_id']);
                $table->index('user_id');
            });
        }

        DB::table('conversations')
            ->select('id')
            ->whereNull('uuid')
            ->orderBy('id')
            ->chunkById(200, function ($rows): void {
                foreach ($rows as $row) {
                    DB::table('conversations')
                        ->where('id', $row->id)
                        ->update(['uuid' => (string) Str::uuid()]);
                }
            });

        DB::table('messages')
            ->select('id')
            ->whereNull('uuid')
            ->orderBy('id')
            ->chunkById(200, function ($rows): void {
                foreach ($rows as $row) {
                    DB::table('messages')
                        ->where('id', $row->id)
                        ->update(['uuid' => (string) Str::uuid()]);
                }
            });

        DB::table('conversations')
            ->select('id')
            ->orderBy('id')
            ->chunkById(200, function ($rows): void {
                foreach ($rows as $row) {
                    $lastMessageId = DB::table('messages')
                        ->where('conversation_id', $row->id)
                        ->whereNull('deleted_at')
                        ->orderByDesc('created_at')
                        ->orderByDesc('id')
                        ->value('id');

                    DB::table('conversations')
                        ->where('id', $row->id)
                        ->update([
                            'last_message_id' => $lastMessageId,
                            'is_active' => true,
                        ]);
                }
            });
    }

    public function down(): void
    {
        if (Schema::hasTable('message_reads')) {
            Schema::drop('message_reads');
        }

        Schema::table('message_attachments', function (Blueprint $table): void {
            if (Schema::hasColumn('message_attachments', 'disk')) {
                $table->dropColumn('disk');
            }
        });

        Schema::table('messages', function (Blueprint $table): void {
            if (Schema::hasColumn('messages', 'reply_to_message_id')) {
                $table->dropIndex('messages_reply_to_message_id_index');
                $table->dropColumn('reply_to_message_id');
            }

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

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

            if (Schema::hasColumn('messages', 'client_temp_id')) {
                $table->dropIndex('messages_conversation_client_temp_idx');
                $table->dropColumn('client_temp_id');
            }

            if (Schema::hasColumn('messages', 'uuid')) {
                $table->dropUnique(['uuid']);
                $table->dropColumn('uuid');
            }
        });

        Schema::table('conversation_participants', function (Blueprint $table): void {
            if (Schema::hasColumn('conversation_participants', 'is_hidden')) {
                $table->dropColumn('is_hidden');
            }

            if (Schema::hasColumn('conversation_participants', 'last_read_message_id')) {
                $table->dropIndex('conversation_participants_last_read_message_id_index');
                $table->dropColumn('last_read_message_id');
            }

            $table->dropIndex('conversation_participants_user_last_read_idx');
        });

        Schema::table('conversations', function (Blueprint $table): void {
            if (Schema::hasColumn('conversations', 'is_active')) {
                $table->dropColumn('is_active');
            }

            if (Schema::hasColumn('conversations', 'last_message_id')) {
                $table->dropIndex('conversations_last_message_id_index');
                $table->dropColumn('last_message_id');
            }

            if (Schema::hasColumn('conversations', 'uuid')) {
                $table->dropUnique(['uuid']);
                $table->dropColumn('uuid');
            }
        });
    }
};
