<?php

namespace Tests\Unit\Models;

use App\Models\Feed;
use App\Models\Keyword;
use App\Models\PlatformChannel;
use Carbon\Carbon;
use Illuminate\Database\QueryException;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class KeywordTest extends TestCase
{
    use RefreshDatabase;

    public function test_fillable_fields(): void
    {
        $fillableFields = ['feed_id', 'platform_channel_id', 'keyword', 'is_active'];
        $keyword = new Keyword;

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

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

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

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

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

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

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

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

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

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

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

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

    public function test_keyword_creation_with_factory(): void
    {
        $keyword = Keyword::factory()->create();

        $this->assertInstanceOf(Keyword::class, $keyword);
        $this->assertNotNull($keyword->feed_id);
        $this->assertNotNull($keyword->platform_channel_id);
        $this->assertIsString($keyword->keyword);
        $this->assertIsBool($keyword->is_active);
    }

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

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

        $this->assertEquals($feed->id, $keyword->feed_id);
        $this->assertEquals($channel->id, $keyword->platform_channel_id);
        $this->assertEquals('Belgium', $keyword->keyword);
        $this->assertFalse($keyword->is_active);
    }

    public function test_keyword_update(): void
    {
        /** @var Keyword $keyword */
        $keyword = Keyword::factory()->create([
            'keyword' => 'original',
            'is_active' => true,
        ]);

        $keyword->update([
            'keyword' => 'updated',
            'is_active' => false,
        ]);

        $keyword->refresh();

        $this->assertEquals('updated', $keyword->keyword);
        $this->assertFalse($keyword->is_active);
    }

    public function test_keyword_deletion(): void
    {
        /** @var Keyword $keyword */
        $keyword = Keyword::factory()->create();
        $keywordId = $keyword->id;

        $keyword->delete();

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

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

        $specialKeywords = [
            'België', // Accented characters
            'COVID-19', // Numbers and hyphens
            'U.S.A.', // Periods
            'keyword with spaces',
            'UPPERCASE',
            'lowercase',
            'MixedCase',
        ];

        foreach ($specialKeywords as $keywordText) {
            $keyword = Keyword::create([
                'feed_id' => $feed->id,
                'platform_channel_id' => $channel->id,
                'keyword' => $keywordText,
                'is_active' => true,
            ]);

            $this->assertEquals($keywordText, $keyword->keyword);
            $this->assertDatabaseHas('keywords', [
                'keyword' => $keywordText,
                'feed_id' => $feed->id,
                'platform_channel_id' => $channel->id,
            ]);
        }
    }

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

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

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

        $this->assertDatabaseHas('keywords', [
            'id' => $keyword1->id,
            'keyword' => 'keyword1',
            'is_active' => true,
        ]);

        $this->assertDatabaseHas('keywords', [
            'id' => $keyword2->id,
            'keyword' => 'keyword2',
            'is_active' => false,
        ]);
    }

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

        // Create first keyword
        Keyword::create([
            'feed_id' => $feed->id,
            'platform_channel_id' => $channel->id,
            'keyword' => 'unique_keyword',
            'is_active' => true,
        ]);

        // Attempt to create duplicate should fail
        $this->expectException(QueryException::class);

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

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

        // Same keyword for different routes should be allowed
        $keyword1 = Keyword::create([
            'feed_id' => $feed1->id,
            'platform_channel_id' => $channel1->id,
            'keyword' => 'common_keyword',
            'is_active' => true,
        ]);

        $keyword2 = Keyword::create([
            'feed_id' => $feed2->id,
            'platform_channel_id' => $channel2->id,
            'keyword' => 'common_keyword',
            'is_active' => true,
        ]);

        $this->assertDatabaseHas('keywords', ['id' => $keyword1->id]);
        $this->assertDatabaseHas('keywords', ['id' => $keyword2->id]);
        $this->assertNotEquals($keyword1->id, $keyword2->id);
    }

    public function test_keyword_timestamps(): void
    {
        /** @var Keyword $keyword */
        $keyword = Keyword::factory()->create();

        $this->assertNotNull($keyword->created_at);
        $this->assertNotNull($keyword->updated_at);
        $this->assertInstanceOf(Carbon::class, $keyword->created_at);
        $this->assertInstanceOf(Carbon::class, $keyword->updated_at);
    }

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

        // Create without specifying is_active
        $keyword = Keyword::create([
            'feed_id' => $feed->id,
            'platform_channel_id' => $channel->id,
            'keyword' => 'test',
        ]);

        // Refresh to get the actual database values including defaults
        $keyword->refresh();

        // Should default to true based on migration default
        $this->assertIsBool($keyword->is_active);
        $this->assertTrue($keyword->is_active);
    }
}
