<?php

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

/**
 * The mirror was written with Lemmy's numeric community id and read with the
 * community slug, so duplicate detection never matched (#123). Keying on the
 * local platform_channels.id removes the ambiguity and the per-instance
 * collision that both remote identifiers share.
 */
return new class extends Migration
{
    public function up(): void
    {
        Schema::table('platform_channel_posts', function (Blueprint $table) {
            $table->dropUnique('channel_post_unique');
            $table->dropIndex(['platform', 'channel_id', 'url']);
            $table->dropIndex(['platform', 'channel_id', 'title']);
            $table->unsignedBigInteger('platform_channel_id')->nullable()->after('id');
        });

        // A name shared by two instances is ambiguous; those rows stay unmapped.
        DB::table('platform_channel_posts')->orderBy('id')->chunkById(200, function ($rows) {
            foreach ($rows as $row) {
                $matches = DB::table('platform_channels')
                    ->where('name', $row->channel_name)
                    ->orWhere('channel_id', $row->channel_name)
                    ->pluck('id');

                if ($matches->count() !== 1) {
                    continue;
                }

                DB::table('platform_channel_posts')
                    ->where('id', $row->id)
                    ->update(['platform_channel_id' => $matches->first()]);
            }
        });

        // Unmappable rows are discarded rather than guessed: the mirror is a
        // cache SyncChannelPostsJob rebuilds every ten minutes.
        DB::table('platform_channel_posts')->whereNull('platform_channel_id')->delete();

        Schema::table('platform_channel_posts', function (Blueprint $table) {
            $table->unsignedBigInteger('platform_channel_id')->nullable(false)->change();
            $table->dropColumn(['platform', 'channel_id', 'channel_name']);
        });

        Schema::table('platform_channel_posts', function (Blueprint $table) {
            $table->foreign('platform_channel_id')->references('id')->on('platform_channels')->onDelete('cascade');
            $table->unique(['platform_channel_id', 'post_id'], 'channel_post_unique');
            $table->index(['platform_channel_id', 'url']);
            $table->index(['platform_channel_id', 'title']);
        });
    }

    public function down(): void
    {
        Schema::table('platform_channel_posts', function (Blueprint $table) {
            $table->dropForeign(['platform_channel_id']);
            $table->dropUnique('channel_post_unique');
            $table->dropIndex(['platform_channel_id', 'url']);
            $table->dropIndex(['platform_channel_id', 'title']);
            $table->string('platform')->default('lemmy');
            $table->string('channel_id')->default('');
            $table->string('channel_name')->nullable();
        });

        DB::table('platform_channel_posts')->update([
            'channel_id' => DB::raw('platform_channel_id'),
        ]);

        Schema::table('platform_channel_posts', function (Blueprint $table) {
            $table->dropColumn('platform_channel_id');
            $table->unique(['platform', 'channel_id', 'post_id'], 'channel_post_unique');
            $table->index(['platform', 'channel_id', 'url']);
            $table->index(['platform', 'channel_id', 'title']);
        });
    }
};
