<?php

namespace Tests\Unit\Actions;

use App\Actions\BackfillRouteArticlesAction;
use App\Actions\CreateRouteArticlesAction;
use App\Enums\ApprovalStatusEnum;
use App\Models\Article;
use App\Models\Feed;
use App\Models\Keyword;
use App\Models\PlatformChannel;
use App\Models\Route;
use App\Models\RouteArticle;
use App\Models\Setting;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class BackfillRouteArticlesActionTest extends TestCase
{
    use RefreshDatabase;

    private function action(): BackfillRouteArticlesAction
    {
        return new BackfillRouteArticlesAction(new CreateRouteArticlesAction);
    }

    private function route(bool $isActive = true): Route
    {
        $feed = Feed::factory()->create();
        $channel = PlatformChannel::factory()->create();

        return Route::create([
            'feed_id' => $feed->id,
            'platform_channel_id' => $channel->id,
            'priority' => 50,
            'is_active' => $isActive,
        ]);
    }

    private function strandedArticle(Route $route): Article
    {
        return Article::factory()->create([
            'feed_id' => $route->feed_id,
            'title' => 'A title',
            'description' => 'A description',
            'content' => 'Some article content',
        ]);
    }

    public function test_it_backfills_articles_missing_a_route_article(): void
    {
        $route = $this->route();
        $article = $this->strandedArticle($route);

        $this->action()->execute($route);

        $this->assertDatabaseHas('route_articles', [
            'article_id' => $article->id,
            'feed_id' => $route->feed_id,
            'platform_channel_id' => $route->platform_channel_id,
        ]);
    }

    public function test_it_is_idempotent(): void
    {
        $route = $this->route();
        $this->strandedArticle($route);

        $this->action()->execute($route);
        $this->action()->execute($route);

        $this->assertSame(1, RouteArticle::count());
    }

    public function test_it_skips_articles_already_routed_to_this_route(): void
    {
        $route = $this->route();
        $article = $this->strandedArticle($route);

        RouteArticle::create([
            'feed_id' => $route->feed_id,
            'platform_channel_id' => $route->platform_channel_id,
            'article_id' => $article->id,
            'approval_status' => ApprovalStatusEnum::APPROVED,
        ]);

        $this->action()->execute($route);

        $this->assertSame(1, RouteArticle::count());
        $this->assertSame(ApprovalStatusEnum::APPROVED, RouteArticle::first()->approval_status);
    }

    public function test_it_skips_articles_without_stored_content(): void
    {
        $route = $this->route();
        Article::factory()->create([
            'feed_id' => $route->feed_id,
            'content' => null,
        ]);

        $this->action()->execute($route);

        $this->assertSame(0, RouteArticle::count());
    }

    public function test_it_does_nothing_for_an_inactive_route(): void
    {
        $route = $this->route(isActive: false);
        $this->strandedArticle($route);

        $this->action()->execute($route);

        $this->assertSame(0, RouteArticle::count());
    }

    public function test_it_does_not_touch_articles_in_other_feeds(): void
    {
        $route = $this->route();
        $this->strandedArticle($route);

        $otherFeed = Feed::factory()->create();
        $otherArticle = Article::factory()->create([
            'feed_id' => $otherFeed->id,
            'content' => 'Other content',
        ]);

        $this->action()->execute($route);

        $this->assertSame(0, RouteArticle::where('article_id', $otherArticle->id)->count());
    }

    public function test_keyword_matching_uses_the_stored_content_without_refetching(): void
    {
        Setting::setBool('enable_publishing_approvals', true);
        $route = $this->route();
        Article::factory()->create([
            'feed_id' => $route->feed_id,
            'title' => 'A title',
            'description' => 'A description',
            'content' => 'news from Brussels today',
        ]);

        Keyword::create([
            'feed_id' => $route->feed_id,
            'platform_channel_id' => $route->platform_channel_id,
            'keyword' => 'brussels',
            'is_active' => true,
        ]);

        $this->action()->execute($route);

        $this->assertSame(ApprovalStatusEnum::PENDING, RouteArticle::first()->approval_status);
    }
}
