<?php

use App\Enums\FuelType;
use App\Jobs\DispatchUserNotificationJob;
use App\Jobs\SendScheduledWhatsAppJob;
use App\Models\NotificationLog;
use App\Models\Plan;
use App\Models\User;
use App\Models\UserNotificationPreference;
use App\Notifications\FuelPriceAlert;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Queue;

uses(RefreshDatabase::class);

beforeEach(function (): void {
    $this->artisan('db:seed', ['--class' => 'PlanSeeder']);
});

// ─── DispatchUserNotificationJob — sent logging ───────────────────────────────

it('logs a sent entry for each allowed channel', function (): void {
    // Free tier allows email (weekly_digest). User has email pref enabled.
    $user = User::factory()->create();

    UserNotificationPreference::factory()->create([
        'user_id' => $user->id,
        'channel' => 'email',
        'fuel_type' => FuelType::E10->value,
        'enabled' => true,
    ]);

    (new DispatchUserNotificationJob($user, 'price_threshold', FuelType::E10->value, price: 143.9))->handle();

    $log = NotificationLog::where('user_id', $user->id)->where('channel', 'email')->first();

    expect($log)->not->toBeNull()
        ->and($log->sent)->toBeTrue()
        ->and($log->trigger_type)->toBe('price_threshold')
        ->and($log->fuel_type)->toBe(FuelType::E10->value);
});

it('actually dispatches FuelPriceAlert with the allowed channels', function (): void {
    Notification::fake();

    $user = User::factory()->create();

    UserNotificationPreference::factory()->create([
        'user_id' => $user->id,
        'channel' => 'email',
        'fuel_type' => FuelType::E10->value,
        'enabled' => true,
    ]);

    (new DispatchUserNotificationJob($user, 'price_threshold', FuelType::E10->value, price: 143.9))->handle();

    Notification::assertSentTo($user, FuelPriceAlert::class, function (FuelPriceAlert $n) {
        return $n->triggerType === 'price_threshold'
            && $n->fuelType === FuelType::E10->value
            && $n->price === 143.9
            && in_array('email', $n->channels, true);
    });
});

it('does not dispatch FuelPriceAlert when no channels are allowed', function (): void {
    Notification::fake();

    // Free user with no preferences — channelsFor returns []
    $user = User::factory()->create();

    (new DispatchUserNotificationJob($user, 'price_threshold', FuelType::E10->value))->handle();

    Notification::assertNothingSent();
});

// ─── DispatchUserNotificationJob — tier_restricted logging ───────────────────

it('logs tier_restricted for channels the user wants but their tier forbids', function (): void {
    // Free tier: sms is disabled. User has sms pref enabled.
    $user = User::factory()->create();

    UserNotificationPreference::factory()->create([
        'user_id' => $user->id,
        'channel' => 'sms',
        'fuel_type' => FuelType::E10->value,
        'enabled' => true,
    ]);

    (new DispatchUserNotificationJob($user, 'price_threshold', FuelType::E10->value))->handle();

    $log = NotificationLog::where('user_id', $user->id)
        ->where('channel', 'sms')
        ->first();

    expect($log)->not->toBeNull()
        ->and($log->sent)->toBeFalse()
        ->and($log->missed_reason)->toBe('tier_restricted');
});

// ─── DispatchUserNotificationJob — daily_limit logging ───────────────────────

it('logs daily_limit when the channel is allowed but the limit is exhausted', function (): void {
    $user = User::factory()->create();

    // Patch the free plan to allow sms with limit 1
    Plan::where('name', 'free')->first()->update([
        'sms_enabled' => true,
        'sms_daily_limit' => 1,
    ]);

    UserNotificationPreference::factory()->create([
        'user_id' => $user->id,
        'channel' => 'sms',
        'fuel_type' => FuelType::E10->value,
        'enabled' => true,
    ]);

    // Pre-log one sent SMS to hit the daily limit
    NotificationLog::factory()->create([
        'user_id' => $user->id,
        'channel' => 'sms',
        'sent' => true,
        'created_at' => now(),
    ]);

    (new DispatchUserNotificationJob($user, 'price_threshold', FuelType::E10->value))->handle();

    $missed = NotificationLog::where('user_id', $user->id)
        ->where('channel', 'sms')
        ->where('sent', false)
        ->first();

    expect($missed)->not->toBeNull()
        ->and($missed->missed_reason)->toBe('daily_limit');
});

// ─── DispatchUserNotificationJob — does not log user-disabled channels ────────

it('does not log channels the user has explicitly disabled', function (): void {
    $user = User::factory()->create();

    Plan::where('name', 'free')->first()->update([
        'sms_enabled' => true,
        'sms_daily_limit' => 3,
    ]);

    UserNotificationPreference::factory()->create([
        'user_id' => $user->id,
        'channel' => 'sms',
        'fuel_type' => FuelType::E10->value,
        'enabled' => false,
    ]);

    (new DispatchUserNotificationJob($user, 'price_threshold', FuelType::E10->value))->handle();

    expect(NotificationLog::where('user_id', $user->id)->where('channel', 'sms')->count())->toBe(0);
});

// ─── DispatchUserNotificationJob — queued on notifications queue ──────────────

it('is dispatched on the notifications queue', function (): void {
    Queue::fake();

    $user = User::factory()->create();

    DispatchUserNotificationJob::dispatch($user, 'price_threshold', FuelType::E10->value);

    Queue::assertPushedOn('notifications', DispatchUserNotificationJob::class);
});

// ─── SendScheduledWhatsAppJob — dispatches per eligible user ─────────────────

it('dispatches DispatchUserNotificationJob for eligible whatsapp users', function (): void {
    Queue::fake();

    $user = User::factory()->create();

    Plan::where('name', 'free')->first()->update([
        'whatsapp_enabled' => true,
        'whatsapp_daily_limit' => 5,
        'whatsapp_scheduled_updates' => 2,
    ]);

    UserNotificationPreference::factory()->create([
        'user_id' => $user->id,
        'channel' => 'whatsapp',
        'fuel_type' => FuelType::E10->value,
        'enabled' => true,
    ]);

    (new SendScheduledWhatsAppJob('morning'))->handle();

    Queue::assertPushedOn('notifications', DispatchUserNotificationJob::class);
});

// ─── SendScheduledWhatsAppJob — skips users over daily limit ─────────────────

it('skips users who have hit their whatsapp daily limit', function (): void {
    Queue::fake();

    $user = User::factory()->create();

    Plan::where('name', 'free')->first()->update([
        'whatsapp_enabled' => true,
        'whatsapp_daily_limit' => 1,
        'whatsapp_scheduled_updates' => 2,
    ]);

    UserNotificationPreference::factory()->create([
        'user_id' => $user->id,
        'channel' => 'whatsapp',
        'fuel_type' => FuelType::E10->value,
        'enabled' => true,
    ]);

    NotificationLog::factory()->create([
        'user_id' => $user->id,
        'channel' => 'whatsapp',
        'sent' => true,
        'created_at' => now(),
    ]);

    (new SendScheduledWhatsAppJob('evening'))->handle();

    Queue::assertNothingPushed();
});

// ─── SendScheduledWhatsAppJob — correct trigger type per period ───────────────

it('passes scheduled_morning trigger for morning period', function (): void {
    Queue::fake();

    $user = User::factory()->create();

    Plan::where('name', 'free')->first()->update([
        'whatsapp_enabled' => true,
        'whatsapp_daily_limit' => 5,
        'whatsapp_scheduled_updates' => 2,
    ]);

    UserNotificationPreference::factory()->create([
        'user_id' => $user->id,
        'channel' => 'whatsapp',
        'fuel_type' => FuelType::E10->value,
        'enabled' => true,
    ]);

    (new SendScheduledWhatsAppJob('morning'))->handle();

    Queue::assertPushed(DispatchUserNotificationJob::class, function (DispatchUserNotificationJob $job): bool {
        return $job->triggerType === 'scheduled_morning';
    });
});
