<?php

namespace Tests\Unit\Models;

use App\Models\Feed;
use App\Models\Keyword;
use App\Models\PlatformChannel;
use App\Models\Route;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class RouteTest extends TestCase
{
    use RefreshDatabase;

    public function test_fillable_fields(): void
    {
        $fillableFields = ['feed_id', 'platform_channel_id', 'is_active', 'priority', 'auto_approve'];
        $route = new Route;

        $this->assertEquals($fillableFields, $route->getFillable());
    }

    public function test_casts_is_active_to_boolean(): void
    {
        $feed = Feed::factory()->create();
        $channel = PlatformChannel::factory()->create();

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

        $this->assertIsBool($route->is_active);
        $this->assertTrue($route->is_active);

        $route->update(['is_active' => '0']);
        $route->refresh();

        $this->assertIsBool($route->is_active);
        $this->assertFalse($route->is_active);
    }

    public function test_primary_key_configuration(): void
    {
        $route = new Route;

        $this->assertNull($route->getKeyName());
        $this->assertFalse($route->getIncrementing());
    }

    public function test_table_name(): void
    {
        $route = new Route;

        $this->assertEquals('routes', $route->getTable());
    }

    public function test_belongs_to_feed_relationship(): void
    {
        $feed = Feed::factory()->create();
        $channel = PlatformChannel::factory()->create();

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

        $this->assertInstanceOf(Feed::class, $route->feed);
        $this->assertEquals($feed->id, $route->feed->id);
        $this->assertEquals($feed->name, $route->feed->name);
    }

    public function test_belongs_to_platform_channel_relationship(): void
    {
        $feed = Feed::factory()->create();
        $channel = PlatformChannel::factory()->create();

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

        $this->assertInstanceOf(PlatformChannel::class, $route->platformChannel);
        $this->assertEquals($channel->id, $route->platformChannel->id);
        $this->assertEquals($channel->name, $route->platformChannel->name);
    }

    public function test_has_many_keywords_relationship(): void
    {
        $feed = Feed::factory()->create();
        $channel = PlatformChannel::factory()->create();

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

        // Create keywords for this route
        /** @var Keyword $keyword1 */
        $keyword1 = Keyword::factory()->create([
            'feed_id' => $feed->id,
            'platform_channel_id' => $channel->id,
            'keyword' => 'test1',
        ]);

        /** @var Keyword $keyword2 */
        $keyword2 = Keyword::factory()->create([
            'feed_id' => $feed->id,
            'platform_channel_id' => $channel->id,
            'keyword' => 'test2',
        ]);

        // Create keyword for different route (should not be included)
        $otherFeed = Feed::factory()->create();
        Keyword::factory()->create([
            'feed_id' => $otherFeed->id,
            'platform_channel_id' => $channel->id,
            'keyword' => 'other',
        ]);

        $keywords = $route->keywords;

        $this->assertCount(2, $keywords);
        $this->assertTrue($keywords->contains('id', $keyword1->id));
        $this->assertTrue($keywords->contains('id', $keyword2->id));
        $this->assertInstanceOf(Keyword::class, $keywords->first());
    }

    public function test_keywords_relationship_filters_by_feed_and_channel(): void
    {
        $feed1 = Feed::factory()->create();
        $feed2 = Feed::factory()->create();
        $channel1 = PlatformChannel::factory()->create();
        $channel2 = PlatformChannel::factory()->create();

        $route = Route::create([
            'feed_id' => $feed1->id,
            'platform_channel_id' => $channel1->id,
            'is_active' => true,
            'priority' => 50,
        ]);

        // Create keyword for this exact route
        /** @var Keyword $matchingKeyword */
        $matchingKeyword = Keyword::factory()->create([
            'feed_id' => $feed1->id,
            'platform_channel_id' => $channel1->id,
            'keyword' => 'matching',
        ]);

        // Create keyword for same feed but different channel
        Keyword::factory()->create([
            'feed_id' => $feed1->id,
            'platform_channel_id' => $channel2->id,
            'keyword' => 'different_channel',
        ]);

        // Create keyword for same channel but different feed
        Keyword::factory()->create([
            'feed_id' => $feed2->id,
            'platform_channel_id' => $channel1->id,
            'keyword' => 'different_feed',
        ]);

        $keywords = $route->keywords;

        $this->assertCount(1, $keywords);
        $this->assertEquals($matchingKeyword->id, $keywords->first()->id);
        $this->assertEquals('matching', $keywords->first()->keyword);
    }

    public function test_route_creation_with_factory(): void
    {
        $route = Route::factory()->create();

        $this->assertInstanceOf(Route::class, $route);
        $this->assertNotNull($route->feed_id);
        $this->assertNotNull($route->platform_channel_id);
        $this->assertIsBool($route->is_active);
        $this->assertIsInt($route->priority);
    }

    public function test_route_creation_with_explicit_values(): void
    {
        $feed = Feed::factory()->create();
        $channel = PlatformChannel::factory()->create();

        $route = Route::create([
            'feed_id' => $feed->id,
            'platform_channel_id' => $channel->id,
            'is_active' => false,
            'priority' => 75,
        ]);

        $this->assertEquals($feed->id, $route->feed_id);
        $this->assertEquals($channel->id, $route->platform_channel_id);
        $this->assertFalse($route->is_active);
        $this->assertEquals(75, $route->priority);
    }

    public function test_route_update(): void
    {
        /** @var Route $route */
        $route = Route::factory()->create([
            'is_active' => true,
            'priority' => 50,
        ]);

        $route->update([
            'is_active' => false,
            'priority' => 25,
        ]);

        $route->refresh();

        $this->assertFalse($route->is_active);
        $this->assertEquals(25, $route->priority);
    }

    public function test_route_with_multiple_keywords_active_and_inactive(): void
    {
        $feed = Feed::factory()->create();
        $channel = PlatformChannel::factory()->create();

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

        Keyword::factory()->create([
            'feed_id' => $feed->id,
            'platform_channel_id' => $channel->id,
            'keyword' => 'active_keyword',
            'is_active' => true,
        ]);

        Keyword::factory()->create([
            'feed_id' => $feed->id,
            'platform_channel_id' => $channel->id,
            'keyword' => 'inactive_keyword',
            'is_active' => false,
        ]);

        $keywords = $route->keywords;
        $activeKeywords = $keywords->where('is_active', true);
        $inactiveKeywords = $keywords->where('is_active', false);

        $this->assertCount(2, $keywords);
        $this->assertCount(1, $activeKeywords);
        $this->assertCount(1, $inactiveKeywords);
        $this->assertEquals('active_keyword', $activeKeywords->first()->keyword);
        $this->assertEquals('inactive_keyword', $inactiveKeywords->first()->keyword);
    }
}
