<?php

namespace Tests\Unit;

use App\Contracts\WhatsAppServiceContract;
use App\Models\User;
use App\Services\Notifications\EventNotificationService;
use App\Services\Settings\SettingService;
use App\Support\NotificationSettings;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Mail\Events\MessageSent;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Mail;
use Mockery;
use Tests\TestCase;

class EventNotificationServiceTest extends TestCase
{
    use RefreshDatabase;

    protected function tearDown(): void
    {
        Mockery::close();

        parent::tearDown();
    }

    public function test_skips_email_when_event_email_is_disabled(): void
    {
        Mail::fake();

        $this->configureEvent('staff_created', emailEnabled: false, smsEnabled: false);

        $user = User::factory()->create([
            'email' => 'staff@example.com',
            'phone' => '9999999999',
        ]);

        app(EventNotificationService::class)->send('staff_created', $user, [
            'password' => 'secret123',
        ]);

        Mail::assertNothingSent();
    }

    public function test_sends_email_when_event_email_is_enabled(): void
    {
        Event::fake([MessageSent::class]);

        $this->configureEvent('staff_created', emailEnabled: true, smsEnabled: false);

        $user = User::factory()->create([
            'email' => 'staff@example.com',
            'phone' => null,
        ]);

        app(EventNotificationService::class)->send('staff_created', $user, [
            'password' => 'secret123',
        ]);

        Event::assertDispatched(MessageSent::class);
    }

    public function test_skips_sms_when_event_sms_is_disabled(): void
    {
        Mail::fake();

        $whatsapp = Mockery::mock(WhatsAppServiceContract::class);
        $whatsapp->shouldReceive('isEnabled')->andReturn(true);
        $whatsapp->shouldNotReceive('send');
        $this->app->instance(WhatsAppServiceContract::class, $whatsapp);

        $this->configureEvent('forgot_password', emailEnabled: false, smsEnabled: false);

        $user = User::factory()->create([
            'email' => 'user@example.com',
            'phone' => '8888888888',
        ]);

        app(EventNotificationService::class)->send('forgot_password', $user, [
            'reset_url' => 'https://example.com/reset',
        ]);

        Mail::assertNothingSent();
    }

    public function test_sends_sms_when_event_sms_is_enabled(): void
    {
        Mail::fake();

        $whatsapp = new class implements WhatsAppServiceContract
        {
            /** @var list<array{phone: string, message: string}> */
            public array $sent = [];

            public function isEnabled(): bool
            {
                return true;
            }

            public function send(string $phone, string $message): bool
            {
                $this->sent[] = ['phone' => $phone, 'message' => $message];

                return true;
            }
        };
        $this->app->instance(WhatsAppServiceContract::class, $whatsapp);

        $this->configureEvent('forgot_password', emailEnabled: false, smsEnabled: true);

        $user = User::factory()->create([
            'email' => 'user@example.com',
            'phone' => '7777777777',
        ]);

        app(EventNotificationService::class)->send('forgot_password', $user, [
            'reset_url' => 'https://example.com/reset',
        ]);

        $this->assertCount(1, $whatsapp->sent);
        $this->assertSame('7777777777', $whatsapp->sent[0]['phone']);
        $this->assertStringContainsString('https://example.com/reset', $whatsapp->sent[0]['message']);
    }

    private function configureEvent(string $eventKey, bool $emailEnabled, bool $smsEnabled): void
    {
        $defaults = NotificationSettings::defaults($eventKey);

        app(SettingService::class)->updateMany([
            NotificationSettings::settingKey($eventKey, 'email_enabled') => [
                'value' => $emailEnabled ? '1' : '0',
                'category' => 'notifications',
                'type' => 'boolean',
            ],
            NotificationSettings::settingKey($eventKey, 'email_subject') => [
                'value' => $defaults['email_subject'] ?? '',
                'category' => 'notifications',
                'type' => 'string',
            ],
            NotificationSettings::settingKey($eventKey, 'email_body') => [
                'value' => $defaults['email_body'] ?? '',
                'category' => 'notifications',
                'type' => 'string',
            ],
            NotificationSettings::settingKey($eventKey, 'sms_enabled') => [
                'value' => $smsEnabled ? '1' : '0',
                'category' => 'notifications',
                'type' => 'boolean',
            ],
            NotificationSettings::settingKey($eventKey, 'sms_body') => [
                'value' => $defaults['sms_body'] ?? '',
                'category' => 'notifications',
                'type' => 'string',
            ],
            'app.name' => [
                'value' => 'Test App',
                'category' => 'general',
                'type' => 'string',
            ],
        ]);
    }
}
