<?php

namespace Tests\Unit\Services;

use Tests\TestCase;
use App\Services\Notification\NotificationService;
use App\Models\User;
use App\Models\BroadcastCampaign;
use App\Models\NotificationTemplate;
use App\Models\UserNotificationSetting;
use Illuminate\Foundation\Testing\RefreshDatabase;

class NotificationServiceTest extends TestCase
{
    use RefreshDatabase;

    private NotificationService $service;
    private User $user;

    protected function setUp(): void
    {
        parent::setUp();
        
        $this->service = app(NotificationService::class);
        $this->user = User::factory()->create();
    }

    /** @test */
    public function it_creates_broadcast_campaign()
    {
        $campaignData = [
            'name' => 'Test Campaign',
            'message' => 'Hello {{name}}!',
            'created_by' => $this->user->id,
            'target_filters' => [
                'active_since' => now()->subDays(7)
            ]
        ];

        $campaign = $this->service->createCampaign($campaignData);

        $this->assertInstanceOf(BroadcastCampaign::class, $campaign);
        $this->assertEquals('Test Campaign', $campaign->name);
        $this->assertEquals('Hello {{name}}!', $campaign->message);
        $this->assertEquals($this->user->id, $campaign->created_by);
    }

    /** @test */
    public function it_generates_campaign_recipients()
    {
        // Create test users
        $users = User::factory()->count(5)->create([
            'notifications_enabled' => true,
            'last_activity_at' => now()->subDays(1)
        ]);

        // Create notification settings for users
        foreach ($users as $user) {
            UserNotificationSetting::forUser($user);
        }

        $campaign = BroadcastCampaign::create([
            'name' => 'Test Campaign',
            'message' => 'Test message',
            'created_by' => $this->user->id,
            'target_filters' => [
                'active_since' => now()->subDays(7)
            ]
        ]);

        $recipientCount = $this->service->generateRecipients($campaign);

        $this->assertGreaterThan(0, $recipientCount);
        $this->assertEquals($recipientCount, $campaign->fresh()->total_recipients);
        $this->assertEquals($recipientCount, $campaign->recipients()->count());
    }

    /** @test */
    public function it_sends_template_notification()
    {
        $template = NotificationTemplate::create([
            'name' => 'Welcome Message',
            'key' => 'welcome',
            'message' => 'Welcome {{name}}! Your user ID is {{user_id}}.',
            'is_active' => true,
        ]);

        $results = $this->service->sendTemplate(
            'welcome',
            [$this->user->id],
            ['name' => 'Test User']
        );

        $this->assertIsArray($results);
        $this->assertCount(1, $results);
        $this->assertEquals($this->user->id, $results[0]['user_id']);
    }

    /** @test */
    public function it_validates_template_variables()
    {
        $template = NotificationTemplate::create([
            'name' => 'Test Template',
            'key' => 'test',
            'message' => 'Hello {{name}}, your balance is {{balance}}.',
            'variables' => ['name', 'balance'],
            'is_active' => true,
        ]);

        $this->expectException(\Exception::class);
        $this->expectExceptionMessage('Missing template variables');

        $this->service->sendTemplate(
            'test',
            [$this->user->id],
            ['name' => 'Test User'] // Missing 'balance' variable
        );
    }

    /** @test */
    public function it_gets_user_notification_settings()
    {
        $settings = $this->service->getUserSettings($this->user);

        $this->assertInstanceOf(UserNotificationSetting::class, $settings);
        $this->assertEquals($this->user->id, $settings->user_id);
        $this->assertTrue($settings->broadcasts_enabled);
        $this->assertTrue($settings->announcements_enabled);
    }

    /** @test */
    public function it_updates_user_notification_settings()
    {
        $settings = $this->service->updateUserSettings($this->user, [
            'broadcasts_enabled' => false,
            'marketing_enabled' => false,
        ]);

        $this->assertFalse($settings->broadcasts_enabled);
        $this->assertFalse($settings->marketing_enabled);
        $this->assertTrue($settings->announcements_enabled); // Should remain unchanged
    }

    /** @test */
    public function it_excludes_opted_out_users_from_campaigns()
    {
        // Create users with different opt-in statuses
        $optedInUser = User::factory()->create(['notifications_enabled' => true]);
        $optedOutUser = User::factory()->create(['notifications_enabled' => true]);
        
        UserNotificationSetting::forUser($optedInUser);
        $optedOutSettings = UserNotificationSetting::forUser($optedOutUser);
        $optedOutSettings->optOut();

        $campaign = BroadcastCampaign::create([
            'name' => 'Test Campaign',
            'message' => 'Test message',
            'created_by' => $this->user->id,
        ]);

        $recipientCount = $this->service->generateRecipients($campaign);

        // Should only include opted-in users
        $recipientUserIds = $campaign->recipients()->pluck('user_id')->toArray();
        $this->assertContains($optedInUser->id, $recipientUserIds);
        $this->assertNotContains($optedOutUser->id, $recipientUserIds);
    }

    /** @test */
    public function it_respects_rate_limiting_filters()
    {
        $recentUser = User::factory()->create([
            'notifications_enabled' => true,
            'last_broadcast_at' => now()->subHours(12) // Recent broadcast
        ]);
        
        $eligibleUser = User::factory()->create([
            'notifications_enabled' => true,
            'last_broadcast_at' => now()->subDays(2) // Old broadcast
        ]);

        UserNotificationSetting::forUser($recentUser);
        UserNotificationSetting::forUser($eligibleUser);

        $campaign = BroadcastCampaign::create([
            'name' => 'Test Campaign',
            'message' => 'Test message',
            'created_by' => $this->user->id,
            'target_filters' => [
                'exclude_recent_broadcast' => 24 // 24 hours
            ]
        ]);

        $this->service->generateRecipients($campaign);

        $recipientUserIds = $campaign->recipients()->pluck('user_id')->toArray();
        $this->assertNotContains($recentUser->id, $recipientUserIds);
        $this->assertContains($eligibleUser->id, $recipientUserIds);
    }
}