<?php

namespace Tests\Feature;

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

class KeyPlatformChannelPostsMigrationTest extends TestCase
{
    use RefreshDatabase;

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

        $migration->up();
    }

    private function restoreLegacyTable(): void
    {
        Schema::dropIfExists('platform_channel_posts');

        Schema::create('platform_channel_posts', function (Blueprint $table) {
            $table->id();
            $table->string('platform');
            $table->string('channel_id');
            $table->string('channel_name')->nullable();
            $table->string('post_id');
            $table->string('title')->nullable();
            $table->string('url')->nullable();
            $table->timestamp('posted_at')->nullable();
            $table->timestamps();

            $table->unique(['platform', 'channel_id', 'post_id'], 'channel_post_unique');
            $table->index(['platform', 'channel_id', 'url']);
            $table->index(['platform', 'channel_id', 'title']);
        });
    }

    private function seedLegacyRow(string $channelId, ?string $channelName, string $postId): void
    {
        DB::table('platform_channel_posts')->insert([
            'platform' => 'lemmy',
            'channel_id' => $channelId,
            'channel_name' => $channelName,
            'post_id' => $postId,
            'url' => "https://news.test/{$postId}",
            'title' => "Post {$postId}",
            'posted_at' => now(),
            'created_at' => now(),
            'updated_at' => now(),
        ]);
    }

    public function test_maps_rows_to_the_local_channel_by_name(): void
    {
        $this->restoreLegacyTable();

        $channel = PlatformChannel::factory()->create(['name' => 'newsbottest', 'channel_id' => 'newsbottest']);
        $this->seedLegacyRow('217', 'newsbottest', '1');
        $this->seedLegacyRow('217', 'newsbottest', '2');

        $this->runMigration();

        $this->assertSame(2, DB::table('platform_channel_posts')
            ->where('platform_channel_id', $channel->id)->count());
    }

    public function test_drops_rows_that_match_no_channel(): void
    {
        $this->restoreLegacyTable();

        PlatformChannel::factory()->create(['name' => 'newsbottest', 'channel_id' => 'newsbottest']);
        $this->seedLegacyRow('999', 'a-community-that-no-longer-exists', '1');

        $this->runMigration();

        $this->assertSame(0, DB::table('platform_channel_posts')->count());
    }

    public function test_drops_rows_whose_channel_name_is_ambiguous_across_instances(): void
    {
        $this->restoreLegacyTable();

        $first = PlatformInstance::factory()->create(['url' => 'https://one.test']);
        $second = PlatformInstance::factory()->create(['url' => 'https://two.test']);

        PlatformChannel::factory()->create([
            'platform_instance_id' => $first->id,
            'name' => 'news',
            'channel_id' => 'news',
        ]);
        PlatformChannel::factory()->create([
            'platform_instance_id' => $second->id,
            'name' => 'news',
            'channel_id' => 'news-two',
        ]);

        $this->seedLegacyRow('8', 'news', '1');

        $this->runMigration();

        $this->assertSame(0, DB::table('platform_channel_posts')->count());
    }

    public function test_leaves_a_schema_the_new_code_can_use(): void
    {
        $this->restoreLegacyTable();

        $channel = PlatformChannel::factory()->create(['name' => 'newsbottest', 'channel_id' => 'newsbottest']);
        $this->seedLegacyRow('217', 'newsbottest', '1');

        $this->runMigration();

        $this->assertTrue(Schema::hasColumn('platform_channel_posts', 'platform_channel_id'));
        $this->assertFalse(Schema::hasColumn('platform_channel_posts', 'channel_id'));
        $this->assertFalse(Schema::hasColumn('platform_channel_posts', 'channel_name'));
        $this->assertFalse(Schema::hasColumn('platform_channel_posts', 'platform'));

        $this->assertTrue(
            PlatformChannelPost::duplicateExists($channel, 'https://news.test/1', 'Post 1')
        );
    }
}
