<?php

namespace Tests\Feature;

use App\Models\PlatformInstance;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;

class StoreCommunityIdMigrationTest extends TestCase
{
    use RefreshDatabase;

    private function runMigration(): void
    {
        $migration = require database_path('migrations/2024_01_01_000015_store_numeric_community_id_on_platform_channels.php');

        $migration->up();
    }

    private function restoreSlugColumn(): void
    {
        Schema::table('platform_channels', function (Blueprint $table) {
            $table->dropUnique('platform_channels_channel_id_unique');
        });

        Schema::table('platform_channels', function (Blueprint $table) {
            $table->string('channel_id')->change();
        });

        Schema::table('platform_channels', function (Blueprint $table) {
            $table->unique(['platform_instance_id', 'channel_id'], 'platform_channels_channel_id_unique');
        });
    }

    private function seedChannel(PlatformInstance $instance, string $channelId, string $name): int
    {
        return DB::table('platform_channels')->insertGetId([
            'platform_instance_id' => $instance->id,
            'name' => $name,
            'display_name' => ucfirst($name),
            'channel_id' => $channelId,
            'is_active' => true,
            'created_at' => now(),
            'updated_at' => now(),
        ]);
    }

    private function prepare(): PlatformInstance
    {
        $this->restoreSlugColumn();
        DB::table('platform_channels')->delete();

        return PlatformInstance::factory()->create(['url' => 'https://lemmy.test']);
    }

    public function test_it_keeps_a_channel_whose_id_is_already_numeric(): void
    {
        $instance = $this->prepare();
        $id = $this->seedChannel($instance, '8', 'news');

        $this->runMigration();

        $this->assertSame(8, (int) DB::table('platform_channels')->where('id', $id)->value('channel_id'));
        $this->assertSame('news', DB::table('platform_channels')->where('id', $id)->value('name'));
    }

    public function test_it_deletes_a_channel_whose_id_is_still_a_slug(): void
    {
        $instance = $this->prepare();
        $id = $this->seedChannel($instance, 'news', 'news');

        $this->runMigration();

        $this->assertDatabaseMissing('platform_channels', ['id' => $id]);
    }

    public function test_it_keeps_numeric_channels_while_deleting_slug_ones(): void
    {
        $instance = $this->prepare();
        $kept = $this->seedChannel($instance, '8', 'news');
        $deleted = $this->seedChannel($instance, 'nieuws', 'nieuws');

        $this->runMigration();

        $this->assertDatabaseHas('platform_channels', ['id' => $kept]);
        $this->assertDatabaseMissing('platform_channels', ['id' => $deleted]);
    }

    public function test_it_makes_no_http_requests(): void
    {
        Http::preventStrayRequests();

        $instance = $this->prepare();
        $this->seedChannel($instance, 'news', 'news');
        $this->seedChannel($instance, '8', 'other');

        $this->runMigration();

        Http::assertNothingSent();
    }
}
